Kiến trúc Node.js - Event Loop

Kiến trúc Node.js - Event Loop

Threads
  • Tuôi" để ý là cứ đợt nào ham đọc cái là lại lười viết, tuần nay tuôi đang đọc một lúc 3 cuốn, à phải là đọc 2 và nghe 1.

    Cuốn sách ám ảnh nhất đến thời điểm hiện tại: Đại dương đen - thuật lại 12 câu chuyện của 12 người mắc bệnh trầm cảm. Thần kinh vững, nhưng mới đọc 2 câu truyện đầu thôi mà cảm giác ngộp thở, bứt rứt thật khó tả 😰

    Câu chuyện tiếp theo đó thì mang lại cảm giác dễ thở hơn vì họ kiểm soát được bản thân. Nhưng sang tiếp câu chuyện thứ 4, thứ 5 thì lại như một có một bàn tay siết họng mình lại. Không thể nhắm mắt mà nghe được á, có gì đó rất đáng sợ.

    Một câu mà mình cảm thấy ám ảnh nhất là khi ba mẹ của người mắc trầm cảm luôn miệng hỏi tại sao con lại như thế mỗi khi sắp lên cơn và gào thét. Họ chỉ đành bất lực trả lời là "Làm sao mà con biết! Cũng giống như hỏi một người bị ốm là tại sao lại ốm? Làm sao mà biết được chứ! Có ai muốn đâu!".

    » Xem thêm
  • Mistral.ai là một công ty AI có trụ sở tại Pháp, được biết đến với nhiều mô hình ngôn ngữ lớn Mistral. Mới đây họ vừa ra mắt thêm một số mô hình có kích thước siêu lớn, siêu mạnh... Nhưng tạm khoan nói đến vì Mistral Chat cũng vừa được ra mắt với nhiều tính năng hay ho tương tự như Chat GPT mà lại miễn phí 😇

    » Xem thêm
  • Qwen2.5-Coder-32B đang là tâm điểm của sự chú ý khi điểm số của nó đánh bại cả GPT-4o hay kể cả là Claude Sonet 3.5. Điều đáng chú ý là nó là mã nguồn mở. Điều đó đồng nghĩa với việc bạn hoàn toàn có thể kéo models về máy và chạy cục bộ dưới máy tính của mình. Nhưng...

    Để chạy được mô hình thì GPU máy tính phải đạt cấp độ quái vật. Cụ thể trong một bài đăng của người dùng thử nghiệm Qwen2.5-Coder-32B trên GTX 3090 thì tốc độ tối đa models cho ra nằm ở mức hơn 30 tokens/s.

    Hy vọng vài nữa sẽ có một bên như Groq hay SambaNova dựng lên để "kiểm thử" hiệu năng con chip của họ, và quan trọng hơn hết là cho anh em dùng "chùa" thì hay biết mấy 🫣

    Tham khảo: Qwen2.5-Coder-32B is an LLM that can code well that runs on my Mac

    » Xem thêm

Các pha (Phases) của Event Loop

Trước đây, người ta đã đề cập rằng Event Loop sẽ giám sát Call Stack có đang trống hay không và Event Queue có đang chứa các hàm đang chờ xử lý hay không để thực hiện việc đưa chúng trở lại Call Stack. Quy trình này được thực hiện theo các giai đoạn như sơ đồ sau:

Các pha (Phases) của Event Loop

  • Timers: thực thi các hàm callback đã được lên lịch với setTimeout và setInterval.
  • I/O callbacks: thực hiện hầu hết tất cả các lệnh gọi lại ngoại trừ close callback, timers callback và setImmediate().
  • Idle, prepare: dùng cho việc xử lý nội bộ của node.js.
  • Poll: truy xuất các sự kiện I/O mới chấp nhận các kết nối đến và xử lý dữ liệu.
  • Check: xử lý hàm callback của setImmediate.
  • Close callbacks: thực thi các hàm callbacks cho các sự kiện close. Ví dụ: socket.on("close").

Điều này chứng minh các giai đoạn của Event Loop được thực thi bởi luồng chính. Mỗi giai đoạn thể hiện cách Event Loop quyết định việc đưa hàm callback nào đang chờ vào Call Stack để chúng được thực thi.

Các pha của Event Loop cũng là nguyên nhân dẫn đến thứ tự thực hiện của một số hàm trong node.js như setTimeout(cb, 0), setImmediate(), process.nextTick(cb) mà chúng ta sẽ tìm hiểu kỹ hơn về chúng trong một bài viết sau.

Tổng kết lại

Tóm lại thì node.js có 2 thành phần cấu tạo quan trọng:

Libuv - I/O không đồng bộ đa nền tảng

libuv là một thư viện hỗ trợ đa nền tảng, tập trung vào I/O không đồng bộ. Nó chủ yếu được phát triển để được sử dụng bởi node.js.

Libuv bao gồm vòng lặp sự kiện (Event Loop), TCP/UDP không đồng bộ, xử lý tệp không đồng bộ, nhóm luồng, các quy trình con và xử lý chúng một cách độc lập.

V8 JavaScript Engine

V8 là dự án open-source của Google, được viết bằng C++. Nó được sử dụng trong Chrome và Node.js.

Nó triển khai ECMAScript và WebAssembly, đồng thời chạy trên Windows 7 trở lên, macOS 10.12+ và Linux.

V8 chứa các khả năng phân bổ bộ nhớ heap, thực thi Call Stack, trình thu gom rác, trình biên dịch tối ưu hóa và trình thông dịch Javascript.

Node.js sử dụng V8 Javascript Engine và do đó còn được gọi là V8 embedder. Theo yêu cầu của V8 Engine, embedder phải triển khai một vòng lặp sự kiện. Node.js đã chọn libuv để triển khai vòng lặp. Đây là nơi V8 và libuv được kết nối bằng cách sử dụng các liên kết C++.

Là đơn luồng, node.js chỉ có một vòng lặp sự kiện. Giữa mỗi lần chạy vòng lặp sự kiện, node.js kiểm tra bất kỳ tác vụ I/O không đồng bộ nào đang chờ và kết thúc nếu không có bất kỳ sự kiện nào. Đơn giản là vòng lặp sự kiện không tạo ra ngay lập tức cho đến khi có callback đang chờ xử lý. Cuối cùng ứng dụng node.js kết thúc khi không có bất kỳ sự kiện nào trong Call Stack hoặc Event Queue.

Mô hình đồng thời chỉ với một luồng

Có thể tóm tắt về mô hình đồng thời trong luồng đơn, vòng lặp sự kiện (Event Loop) và ngăn xếp cuộc gọi (Call Stack) để xây dựng mô hình I/O không đồng bộ như sau:

  • Ứng dụng node.js được node.js thực thi.
  • Chức năng bị ràng buộc CPU (sử dụng CPU cao) được thực thi đồng bộ trên luồng chính.
  • Nếu chức năng là I/O không đồng bộ được đẩy tới nhóm luồng để thực thi không đồng bộ và luồng chính tiếp tục thực thi.
  • Sau khi chức năng không đồng bộ hoàn thành, nhóm luồng tự đẩy hàm callback và sự kiện vào Event Queue.
  • Vòng lặp sự kiện sử dụng luồng chính để theo dõi các hàm callbacks đang chờ xử lý trên Event Queue nếu Call Stack đang trống. Nó sẽ đưa các hàm callbacks vào lại Call Stack để thực thi nếu Call Stack trống.

Node.js nên dùng khi nào?

Node.js chỉ đơn giản là cung cấp mô hình I/O không đồng bộ, không bị chặn ngay cả với luồng đơn. Điều này làm cho node.js phù hợp hơn với các ứng dụng I/O chuyên sâu hơn. Các ứng dụng chuyên sâu về CPU sẽ không phù hợp với node.js vì nó sẽ chặn việc thực thi trên luồng đơn đó.

Vì ngôn ngữ lập trình Javascript được sử dụng trong node.js, các nhà phát triển có thể tạo các Application Stack đầy đủ chỉ bằng một ngôn ngữ Javascript.

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.
Author

Xin chào, tôi tên là Hoài - một anh Dev kể chuyện bằng cách viết ✍️ và làm sản phẩm 🚀. Với nhiều năm kinh nghiệm lập trình, tôi đã đóng góp một phần công sức cho nhiều sản phẩm mang lại giá trị cho người dùng tại nơi đang làm việc, cũng như cho chính bản thân. Sở thích của tôi là đọc, viết, nghiên cứu... Tôi tạo ra trang Blog này với sứ mệnh mang đến những bài viết chất lượng cho độc giả của 2coffee.dev.Hãy theo dõi tôi qua các kênh LinkedIn, Facebook, Instagram, Telegram.

Bạn thấy bài viết này có ích?
Không

Bình luận (0)

Nội dung bình luận...