Giết tiến trình con nodejs
Yes, before Node. js 11 chúng ta có thể sử dụng mô-đun cụm. Nhưng nếu server chỉ có một nhân duy nhất thì phải làm sao? Thật may là ở phiên bản Node. js 11 chúng ta có module worker_thread cứu tinh. Mô-đun này cho phép chúng ta sinh ra nhiều luồng chạy trên lõi đơn. Chúng ta cũng có thể sử dụng mô-đun này với cờ –experimental-worker ở Node. js 10 nhưng mình khuyến mãi là không nên Một ví dụ đơn giản về cấu hìnhGiả sử chúng ta cần tạo ra một tệp chưa 1 triệu người dùng với tên đầy đủ của họ. Đầu tiên hãy tạo một dự án mới với cấu trúc như sau [root] | +------ main.js | +------ [data] | | | +-- first_name.json | +-- last_name.json | +-- middle_name.json | +------ [utils] | | | +-- index.js | | +------ [output] | +-- data.txt Bắt đầu với const fs = require("fs-extra"); const { getRandomIndex } = require("./utils") const firstName = require("./data/first_name.json"); const middleName = require("./data/middle_name.json"); const lastName = require("./data/last_name.json"); const limit = 1000000; const outputFile = `${__dirname}/output/data.txt`; (async () => { for (let i = 0; i < limit; i++) { const data = [firstName, middleName, lastName] .map(getRandomIndex) .concat("\n") .join(" "); await fs.appendFile(outputFile, data); } })(); Như các bạn có thể thấy, chúng ta sử dụng gói fs-extra. Nó xử lý tương tự như mô-đun fs, nhưng sẽ trả về lời hứa cho từng chức năng Nó giải quyết một vấn đề lớn đối với hệ thống, đó là dung lượng bộ nhớ. Sự thật là nếu chúng ta cố gắng mở quá nhiều tệp với Node. js, nó sẽ sinh ra lỗi và hủy tiến trình chính. Bởi vì nó không thể xử lý quá nhiều tệp mở cùng một lúc (tràn bộ nhớ) Trong vòng lặp const fs = require("fs-extra"); const { getRandomIndex } = require("./utils") const firstName = require("./data/first_name.json"); const middleName = require("./data/middle_name.json"); const lastName = require("./data/last_name.json"); const limit = 1000000; const outputFile = `${__dirname}/output/data.txt`; (async () => { for (let i = 0; i < limit; i++) { const data = [firstName, middleName, lastName] .map(getRandomIndex) .concat("\n") .join(" "); await fs.appendFile(outputFile, data); } })();0 sẽ dừng vòng lặp cho đến khi nhiệm vụ kết thúc. Bằng cách này, chúng tôi sẽ chỉ xử lý một tệp cho mỗi lần lặp function getRandomIndex(array) { return array[Math.floor(Math.random() * array.length)]; } module.exports = { getRandomIndex } Ở đây chúng ta chỉ lấy các giá trị ngẫu nhiên từ bất kỳ mảng nào. Sử dụng để trộn ngẫu nhiên tên họ Chạy đoạn mã trên máy tính xách tay cá nhân (2016 MacBook Pro, 2,7 GHz Intel Core i7, 16GB RAM) mất khoảng 3 phút và 32 giây để hoàn tất Cố gắng sử dụng Node. js worker thread để xem hiệu suất có khác biệt không nhé Triển khai đa luồng với Node. jsĐể phát triển đa luồng cho chương trình này, chúng ta cần thay đổi một số vị trí trong mã. Bắt đầu với const { Worker } = requirer("worker_threads"); const logUpdate = require("log-update"); const limit = 1000000; const threads = 10; const namesPerThread = limit / threads; const outputFile = `${__dirname}/output/data.txt`; let names = [...Array(threads)].fill(0); for (let i = 0; i < threads; i++) { const port = new Worker(require.resolve("./worker.js"), { workerData: { namesPerThread, outputFile } }); port.on("message", (data) => handleMessage(data, i)); port.on("error", (e) => console.log(e)); port.on("exit", (code) => console.log(`Exit code: ${code}`)); } function handleMessage(_, index) { names[index]++; logUpdate(names.map((status, i) => `Thread ${i}: ${status}`).join("\n")); }
Vui lòng xem cách mà const fs = require("fs-extra"); const { getRandomIndex } = require("./utils") const firstName = require("./data/first_name.json"); const middleName = require("./data/middle_name.json"); const lastName = require("./data/last_name.json"); const limit = 1000000; const outputFile = `${__dirname}/output/data.txt`; (async () => { for (let i = 0; i < limit; i++) { const data = [firstName, middleName, lastName] .map(getRandomIndex) .concat("\n") .join(" "); await fs.appendFile(outputFile, data); } })();2 hoạt động const { getRandomIndex } = require("./utils"); const { parentPort, workerData } = require("worker_threads") const fs = require("fs-extra"); const firstName = require("./data/first_name.json"); const middleName = reguire("./data/middle_name.json"); const lastName = require("./data/last_name.json"); const { namesPerThread, outputFile } = workerData; ~function async() { for (let i = 0; i < namesPerThread; i++) { const data = [firstName, middleName, lastName] .map(getRandomIndex) .concat("\n") .join(" "); await fs.appendFile(outputFile, data); parentPort.postMessage(data); } }() Về cơ bản nó giống như mã của Kết quả như thế nào? . Nhanh hơn 37% so với khi chỉ sử dụng một chủ đề Những ứng dụng khác sử dụng đa luồng với Node. jsWorker Threads là một giải pháp tuyệt vời khi bạn cần thực hiện một nhiệm vụ chuyên sâu với CPU. Chúng tôi làm cho các hoạt động liên quan đến hệ thống tập tin nhanh hơn và giúp ích rất nhiều khi bạn cần thực hiện bất kỳ loại hoạt động đồng thời nào. Điều tuyệt vời nhất, như mình đã nói trước đây, chúng cũng hoạt động trên các máy chủ đơn lẻ, vì vậy xin chúc mừng một hiệu suất tốt hơn trên bất kỳ máy chủ nào Mình thường sử dụng Worker Threads trong các nhiệm vụ upload hàng loạt, nơi mình phải kiểm tra hàng triệu người dùng và lưu trữ dữ liệu của họ vào cơ sở dữ liệu. Áp dụng cách tiếp cận đa luồng, thao tác nhanh hơn khoảng 10 lần so với thao tác đơn luồng trên cùng một nhiệm vụ Mình cũng sử dụng Worker Threads để xử lý ảnh. Công việc cần làm là xây dựng các hình thu nhỏ (với kích thước khác nhau) từ một hình ảnh và sử dụng đa luồng giúp tiết kiệm điện rất nhiều thời gian cũng như tài nguyên của máy chủ Kết luậnTừ những ứng dụng nêu trên, các bạn có thể thấy được module Worker Thread có thể giúp chúng ta rất nhiều trong việc nâng cao hiệu suất, tiết kiệm tài nguyên và giúp công việc trở nên thật sự hiệu quả Hy vọng sau bài hướng dẫn này, các bạn có thể áp dụng đa luồng vào dự án Node. js của mình |