Cluster trong Node.js là gì? Sử dụng Cluster để tăng khả năng chịu tải ứng dụng viết bằng Node.js

Cluster trong Node.js là gì? Sử dụng Cluster để tăng khả năng chịu tải ứng dụng viết bằng Node.js

Tin ngắn hàng ngày dành cho bạn
  • Từ lâu rồi suy nghĩ làm thế nào để tăng sự hiện diện thương hiệu, cũng như người dùng cho blog. Nghĩ đi nghĩ lại thì chỉ có cách chia sẻ lên mạng xã hội hoặc trông chờ họ tìm kiếm, cho đến khi...

    In cái áo này được cái tắc đường khỏi phải lăn tăn, càng đông càng vui vì hàng trăm con mắt nhìn thấy cơ mà 🤓

    (Có tác dụng thật nha 🤭)

    » Xem thêm
  • Một vòng của sự phát triển nhiều dự án khá là thú vị. Tóm tắt lại trong 3 bước: Thấy một cái gì đó phức tạp -> Làm cho nó đơn giản đi -> Thêm thắt tính năng cho đến khi nó phức tạp... -> Quay trở lại vòng lặp mới.

    Tại sao lại như vậy? Để mình lấy 2 ví dụ cho các bạn thấy.

    Markdown ra đời với mục tiêu tạo ra một định dạng văn bản thô "dễ viết, dễ đọc, dễ dàng chuyển thành một dạng gì đó như HTML". Vì thời đó chẳng ai đủ kiên nhẫn mà vừa ngồi viết vừa thêm định dạng cho văn bản hiển thị ở trên web như thế nào. Ấy vậy mà giờ đây người ta đang "nhồi nhét" hoặc tạo ra các biến thể dựa trên markdown để bổ sung thêm nhiều định dạng mới đến mức... chẳng nhớ nổi hết cú pháp.

    React cũng là một ví dụ. Từ thời PHP, việc khát khao tạo ra một cái gì đó tách biệt hẳn giao diện người dùng và phần xử lý logic chính của ứng dụng thành 2 phần riêng biệt cho dễ đọc, dễ viết. Kết quả là các thư viện UI/UX phát triển rất mạnh mẽ, mang lại khả năng tương tác với người dùng rất tốt, còn phần logic ứng dụng thì nằm ở một máy chủ riêng biệt. Bộ đôi Front-end, Back-end cũng từ đấy mà thịnh hành, không thể thiếu anh bồi bàn REST API. Ấy vậy mà giờ đây React trông cũng không khác biệt gì so với PHP là mấy, kéo theo là cả Vue, Svelte... lại cùng quy tất cả về một mối.

    Cơ mà không phải vòng lặp là xấu, ngược lại vòng lặp này mang tính tiến hoá nhiều hơn là "cải lùi". Nhiều khi lại tạo ra được cái hay hơi cái cũ thế là người ta lại dựa trên cái hay đó để tiếp tục lặp. Nói cách khác là chắc lọc tinh hoa từng tí một tí một á 😁

    » Xem thêm
  • Song song với các dự án chính thức thì thi thoảng mình vẫn thấy các dự án "bên lề" nhằm tối ưu hoặc cải tiến ngôn ngữ theo khía cạnh nào đó. Ví dụ nature-lang/nature là một dự án hướng tới cải tiến Go, mang lại một số thay đổi nhằm giúp cho việc sử dụng Go trở nên thân thiện hơn.

    Nhìn lại mới thấy hao hao JavaScript 😆

    » Xem thêm

Vấn đề

Node.js chỉ có một luồng để chạy mã Javascript, nghĩa là tại một thời điểm chỉ xử lý được một lệnh JS. Nếu như ứng dụng có nhiều mã JS mất thời gian để xử lý thì khả năng "nút thắt cổ chai" sẽ xuất hiện. Hay đơn giản như ứng dụng của bạn xử lý tác vụ nhẹ nhàng nhưng với số lượng yêu cầu đồng thời là rất lớn, dẫn đến kết nối timeout liên tục do không thể xử lý hết lượng yêu cầu.

Có thể nói một phần sức mạnh ứng dụng nằm ở tốc độ của Vi xử lý (CPU). Ngày nay CPU ngày càng mạnh hơn và tích hợp nhiều lõi (core) hơn. Nếu ứng dụng Node.js của bạn chỉ chạy trên một lõi của CPU thì quả là lãng phí. Phải chi có một cách nào đó giúp cho ứng dụng tận dụng được hết số lõi của CPU thì tuyệt vời. Làm một phép tính đơn giản, giả sử hiện tại ứng dụng xử lý được 1000 req/s, bây giờ tận dụng được 8 lõi của CPU thì con số đó có thể lên đến ~8000 req/s. Hơn nữa còn tăng khả năng chịu lỗi nếu chẳng may một instance bị trục trặc thì vẫn còn 7 instance sẵn sàng xử lý.

Để tận dụng sức mạnh của vi xử lý đa lõi cũng như tăng khả năng xử lý, khả năng chịu lỗi thì Cluster là một trong những phương pháp tối ưu, chúng ta cùng tìm hiểu về Cluster trong bài viết dưới đây nhé.

Cluster là gì?

Cluster trong Node.js có thể được sử dụng để chạy nhiều phiên bản (instance) Node.js để phân phối khối lượng công việc giữa chúng. Sự khác biệt giữa Cluster và Worker Threads là Cluster cách ly các quy trình (threads) của worker, trong khi Worker Threads chạy nhiều quy trình trong một phiên Node.js duy nhất.

Về bản chất, các worker được tạo ra bởi Cluster bằng cách sử dụng child_process.fork() để chúng có thể giao tiếp với tiến trình tạo ra nó thông qua IPC.

Cluster hỗ trợ hai phương pháp phân phối công việc:

  • Cách thứ nhất (mặc định trên tất cả các nền tảng ngoại trừ Windows) là cách phân phối theo vòng, trong đó quy trình chính (Primary) lắng nghe trên một cổng, lắng nghe các kết nối mới và phân phối chúng cho các worker theo kiểu vòng tròn mà các nhà phát triển tích hợp "phương pháp phân phối thông minh" để tránh làm quá tải quy trình của worker.

  • Cách tiếp cận thứ hai là cách quy trình chính tạo ra socket để lắng nghe và gửi nó đến những worker. Sau đó các worker trực tiếp xử lý các yêu cầu đó.

Trên lý thuyết, cách tiếp cận thứ hai sẽ mang lại hiệu quả tốt nhất. Tuy nhiên trong thực tế, phân phối qua socket có xu hướng mất cân bằng do sự thay đổi của bộ lập lịch hệ điều hành. Các nhà phát triển đã quan sát và thấy rằng hơn 70% tất cả các kết nối được phân phối đến chỉ trong hai quy trình, trong tổng số tám quy trình.

Những worker được tạo ra là các quy trình riêng biệt, chúng có thể bị "kill" hoặc "re-spawned" tùy thuộc vào chương trình, mà không ảnh hưởng đến các worker khác. Miễn là có một vài worker còn hoạt động, máy chủ sẽ tiếp tục xử lý yêu cầu đến và ngược lại.

Triển khai Cluster

Để triển khai Cluster chúng ta sử dụng module node:cluster tích hợp trong Node. Thông thường số lượng worker được tạo ra sẽ bằng với số lõi CPU. Ví dụ dưới đây sử dụng Node.js 18 LTS và express.js:

const cluster = require('node:cluster');
const numCPUs = require('node:os').cpus().length;
const express = require('express');

if (cluster.isPrimary) {
  console.log(`Primary ${process.pid} is running`);

  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} exited`);
  });
} else {
  const app = express();
  app.use(express).listen(port);

  console.log(`Worker ${process.pid} started`);
}

Sau đó khởi chạy với lệnh node.

$ node index.js
Primary 3596 is running
Worker 4324 started
Worker 4520 started
Worker 6056 started
Worker 5644 started

Bạn sẽ thấy số Worker được tạo ra bằng đúng số lõi CPU thông qua module node:os.

Để xem chi tiết hơn về cách triển khai, vào Node.js Cluster.

Ngoài ra chúng ta còn có thể sử dụng công cụ pm2 để triển khai ứng dụng Node.js tương tự như Cluster module.

Tổng kết

Cluster là một phương pháp nhanh và thuận tiện nhất để tăng khả năng xử lý mã Javascript ứng dụng của bạn bằng cách tận dụng đa lõi CPU. Việc triển khai Cluster khá đơn giản bằng module node:cluster được tích hợp sẵn trong Node.js. Thuật toán phân phối công việc của Cluster sẽ giúp điều phối lượng công việc đảm bảo cho các worker không bị quá tải. Nếu bạn đang sở hữu một máy chủ đa lõi và muốn tận dụng hết số lõi đó thì hãy thử triển khai Cluster ngay bây giờ.

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