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
  • 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 đề

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...
Bấm hoặc cuộn mạnh để sang bài mới