Kiến trúc Node.js - Node.js xử lý bất đồng bộ như thế nào?

Kiến trúc Node.js - Node.js xử lý bất đồng bộ như thế nào?

Tin ngắn hàng ngày dành cho bạn
  • Hôm qua đến nay, lượt truy cập tới từ Facebook tăng đột biến. Thường như thế là do ai đó chia sẻ bài viết của blog vào một nhóm nào đó.

    Cơ mà lần này là liên kết trực tiếp đến trang chủ luôn. Tò mò ghê, không biết ai chia sẻ, chia sẻ ở đâu nữa. Muốn biết để tìm hiểu "insight" ghê 🥹

    » Xem thêm
  • Mình mới phát hiện ra thư viện idb-keyval giúp triển khai cơ sở dữ liệu dạng key-value một cách đơn giản. Như đã chia sẻ trong chuỗi bài viết về quá trình làm OpenNotas, mình loay hoay đi tìm một loại cơ sở dữ liệu để lưu trữ mà xem chừng vất vả quá, cuối cùng chốt localForage.

    idb-keyval cũng tương tự như localForage nhưng có vẻ như nó đang làm tốt hơn một chút. Đơn cử là có hàm update để cập nhật dữ liệu, hình dung đơn giản là:

    update('counter', (val) => (val || 0) + 1);

    Chứ không như hàm set là thay thế dữ liệu mất tiêu luôn.

    » Xem thêm
  • Đầu xuân năm mới, xin phép khoe số tiền kiếm được sau 1 tháng đặt quảng cáo tại indieboosting.com 🥳🥳🥳

    » Xem thêm

Vấn đề

Ở bài viết trước chúng ta đã được biết node.js là single thread, biết thế nào là các tác vụ I/O đồng bộ lẫn không đồng bộ. Vậy thì trong bài viết này tôi sẽ nói về cách node.js xử lý bất đồng bộ như thế nào.

Trước tiên thì tôi xin phép được nhắc lại một số khái niệm để các bạn nắm rõ vấn đề hơn trước khi đến với cách mà node.js xử lý bất đồng bộ!

Bất đồng bộ là gì?

Nếu như các bạn đã được tiếp xúc với một số ngôn ngữ khác trước khi biết đến Javascript như C, PHP hoặc Java thì đó là những ngôn ngữ được viết theo phong cách đồng bộ, tức là nó sẽ chạy lần lượt những đoạn mã mà bạn viết ra. Tôi lấy ví dụ như một đoạn mã đọc file trong PHP như sau:

<?php
$content = readfile("file.txt");
echo $content;
?>

Ngay sau khi hàm readfile đọc được nội dung của file.txt thì nó sẽ in ngay ra màn hình thông qua lệnh echo, bởi vì echo chỉ được gọi sau khi mà hàm readfile có kết quả. Đó chính là lập trình đồng bộ.

Quay lại với Javascript, cùng là một hàm đọc file sẽ trông như sau:

const content = readFile("file.txt");
console.log(content);

Thì kết quả in ra sẽ không phải là nội dung của file.txt bởi vì readFile là một hàm bất đồng bộ. Nó không được xử lý ngay lập tức mà thay vào đó nó đẩy nhiệm vụ này sang cho một bên khác thực hiện (cụ thể là Thread Pool) rồi tiếp tục gọi luôn hàm console.log. Mà các bạn biết đấy, lúc này content đã kịp có kết quả của việc đọc file đâu nên kết quả in ra chắc chắn là không có gì.

Vậy thì các bạn sẽ thắc mắc

Tại sao bất đồng bộ có ích cho node.js

Node.js xử lý bất đồng bộ như thế nào?

Trước tiên chúng ta hãy nhìn lại sơ đồ của cách thành phần có trong node.js:

Thành phần Node.js

Call stack là nơi chịu trách nhiệm cho việc chạy mã Javascript theo một thứ tự nhất định. Vì chỉ có duy nhất một call stack thế nên chỉ có một mã Javascript được chạy tại một thời điểm, điều đó sẽ gây ra một cuộc tắc nghẽn (chặn) nếu như đoạn mã Javascript mất nhiều thời gian để xử lý.

Node.js Standard Library chứa những thành phần tương tác với hệ thống như các tập tin, các request http, phân giải DNS... mà được libuv cung cấp, hay nói cách khác là những thành phần xử lý các I/O không đồng bộ.

Event loop đơn giản là một vòng lặp vô hạn, nó luôn luôn kiểm tra trong call stack có trống không và nếu trống nó sẽ chuyển các hàm callbacks từ Event queue vào call stack lần lượt theo thứ tự FIFO (First In First Out). Các hàm callbacks trong Event queue được Thread pool chuyển vào sau khi một I/O xử lý xong kết quả.

Tóm lại chúng ta sẽ có luồng xử lý một đoạn mã Javascript có chứa mã bất đồng bộ như sau:

Khi chạy một file js, mã Javascript sẽ lần được được đưa vào call stack để xử lý, nếu gặp bất kì một đoạn mã bất đồng bộ nào nó sẽ chuyển đoạn mã đó sang cho Thread pool và tiếp tục xử lý tiếp. Thread pool sau khi nhận được công việc từ call stack nó sẽ tiến hành xử lý ngay lập tức, sau khi có được kết quả nó chuyển kết quả vào hàm callback mà I/O đó đã đăng kí vào Event queue.

Lúc này Event loop vẫn luôn kiểm tra call stack đã xử lý xong hết mã Javascript trong file js chưa. Và nếu hết rồi nó sẽ di chuyển lần lượt các hàm callbacks từ Event queue sang call stack để nó tiếp tục xử lý.

Và nếu trong các hàm callback tiếp tục có những đoạn mã bất đồng bộ thfi công việc sẽ tiếp tục được lặp lại như các bước ở bên trên.

Chúng ta có thể thấy mặc dù node.js chỉ có một call stack để xử lý mã Javascript thế nhưng lại có nhiều Thread pool để xử lý I/O không đồng bộ vốn dĩ tốn nhiều thời gian. Node.js tận dụng sức mạnh của V8 để xử lý mã Javascript cho nên có thể nói tốc độ xử lý mã Javascript hoàn toàn phụ thuộc vào V8 mà theo như họ nói là rất "nhanh".

Mặc định sẽ có 4 Thread pool được tạo ra mỗi khi khởi chạy, con số này có thể thiết lập lên đến 1024 tùy thuộc vào cấu hình máy chủ của bạn cao hay thấp để tinh chỉnh cho phù hợp.

Cao cấp
Hello

Bí mật ngăn xếp của Blog

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (0)

Nội dung bình luận...
Bấm hoặc cuộn mạnh để sang bài mới