Nodejs đã quyết vấn đề kết nối đồng thời cao như thế nào? Nodejs Series.

Nội dung bài viết

Nodejs Series đã qua được 3 bài viết, và bài viết này giải đáp thắc mắc vì sao Nodejs có thể cải tiến hiệu suất cao đến như vậy. Đọc từ từ sẽ rõ.


Hiệu suất của ứng dụng nhanh hay chậm?


Trước hết, tôi muốn chia sẻ về sự thật đó là những ứng dụng có điểm nghẽn không phải là do chọn công nghệ back-end hay front-end, tôi dám khẳng định là thế. Mặc dù chúng tôi cũng là nhóm đang sử dụng NodeJS để làm back-end, nhưng chúng tôi không bao giờ nói chuyện với ruby hoặc java về hiệu suất NodeJS của chúng tôi tốt như thế nào. Hệ thống ứng dụng của bạn bị tê liệt vào những lúc cao điểm như mua vè tàu tết, hay lấy vourcher mua iphone 12 chẳng hạn, không liên quan đến hiệu suất của Nodejs nếu như bạn đang sử dụng nó. . . 

Đối với một ứng dụng lớn, hầu hết các tắc nghẽn về hiệu suất thủ phạm không ai hết chính là một trong các hoạt động IO. Điều này bao gồm các hoạt động cơ sở dữ liệu (số lượng kết nối, hiệu suất máy, v.v.), dịch vụ bộ nhớ cache, IO mạng, đọc và ghi tệp và các hoạt động khác. Nếu tắc nghẽn hiệu suất của nhà sản xuất IO, cho dù bạn phân phối nó như thế nào và chất đống máy móc, cho dù ngôn ngữ đó có tuyệt vời đến đâu thì nó cũng nghẽn mà thôi.


Nodejs là đa luồng?


Có nhiều ý kiến tranh cãi khác nhau về việc Node.js là đơn luồng hay đa luồng. Việc thêm worker_threads vào có phải là Node.js đã chấp nhận đa luồng hay không? Và vẫn biết đơn luồng sẽ chậm hơn đa luồng, nhưng tại sao Redis đơn luồng nhưng vẫn rất nhanh và hiệu suất truy vấn cực kỳ cao? Sau đây là ý kiến cá nhân của mình, mỗi người có quyền hiểu khác nhau. Hãycomment một cách ôn hoà...

Ở bài trước chúng ta đang nói đến vấn đề "Vì sao Nodejs mới ra đời không hiệu quả khi có lượng kết nối cao", thì hôm nay chúng ta sẽ giải đáp thắc mắc này đó chính là Nodejs đã cải tiến gì để giải quyết vấn đề này? Thật sự mà nói để giải thích cho các bạn có thể hiểu ngay trong bài viết này quả là khó, vì vậy trước hết tôi yêu cầu các bạn phải tự tìm hiểu về những cụm từ sau nếu bạn chưa biết đó là: 



Bài viết này tôi sẽ có đề cập đến nhưng nó không sâu bằng các bạn tự đi tìm. Đó là yêu cầu tối thiểu thôi đấy. Nếu muốn nhanh hơn thì hãy xem Tôi đã hiểu process và thread như thế này. 


Node.js cung cấp khả năng "đa luồng" bằng cách cung cấp API cluster và child_process để tạo các quy trình con. Nhưng cách tạo quy trình này sẽ hy sinh bộ nhớ dùng chung và truyền dữ liệu phải được truyền qua json. (Có một số hạn chế nhất định và các vấn đề về hiệu suất) 


Dựa trên điều này, Node.js từ phiên bản V10.5.0 cung cấp thêm đó là worker_threads, nhẹ hơn so với child_process hoặc cluster. Không giống như child_process hoặc cluster, worker_threads có thể chia sẻ bộ nhớ bằng cách chuyển các ArrayBuffer hoặc chia sẻ các SharedArrayBuffer.  Trên đây là để cho các bạn biết Nodej thật sự đã triển khai cơ chế đa luồng. 


Nhưng đây trường hợp Node.js đa luồng không có nghĩa là giống như các ngôn ngữ lập trình đa luồng khác (chẳng hạn như: java). Worker_threads của Node.js khác với đa luồng của java . Nếu các luồng được thêm vào, bản chất của chính ngôn ngữ sẽ thay đổi, do đó, các luồng không thể được thêm vào dưới dạng một tập hợp các lớp hoặc hàm có sẵn mới. Hiểu tạm vậy đi. 


Vậy câu hỏi ở đây có nhiều bạn thắc mắc là "Ừ thì cứ cho là đa luồng đi, vậy hoạt động của đa luồng thế nào?" OK, hỏi thì tôi trả lời thôi. À còn nói về về Tại sao nếu làm backend sao không sử dụng java mà phải là Nodeis. java làm tốt hơn nhiều mà. Cứ đợi đấy, mọi chuyện sẽ được giải thích. Tôi có ý kiến của riêng mình, ai cũng vậy.


Xử lý đa luồng là gì?


Nhưng ai đọc nhiều bài viết của tipjs thì hiểu rồi. Trước khi đi vào một định nghĩa mà nhan nhản trên mạng thì chúng tôi lại tiếp cận bằng một vấn đề hay ví dụ thực tế. Ở đây cũng không ngoại lệ. Giải thích vấn đề như thế này cần hiểu: 


  • 1. Quy trình đơn và luồng đơn: Một người ăn thức ăn trên một bàn. 
  • 2. Quy trình đơn và đa luồng: nhiều người ăn cùng nhau trên cùng một bàn. 
  • 3. Đa quy trình và đơn luồng: mỗi người dùng bữa tại bàn riêng của mình.


Bạn có nhu cầu nào thì cứ sử dụng nhé. Nếu làm quan to thì cưới cho nó hoành tráng tiền không thành vấn đề. mỗi người dùng bữa tại bàn riêng của mình. cho nó oách. Còn ở đây chúng ta ập đến "Đa luồng". 


Xử lý đa luồng là cho phép nhiều luồng trong chương trình thực hiện nhiều việc mà không làm cho các kết nối giao diện bị tắc nghẽn vậy mới nhanh được chứ. Ví dụ, các công cụ tải xuống đa luồng như Thunder là đa luồng điển hình. Khi có tác vụ tải xuống, Thunder chia tệp thành 10 phần bằng nhau, sau đó mở 10 chuỗi để tải chúng xuống riêng biệt. Lúc này giao diện chính là một luồng riêng, sẽ không bị kẹt vì tải file. Và luồng chính có thể kiểm soát các luồng phụ. Ví dụ: nếu một luồng tải xuống chậm hoặc thậm chí dừng, luồng chính có thể buộc phải tắt nó và khởi động lại một luồng khác. Đó là lý do vì sao lập trình sử dụng đa luồng lại nhanh.



 Nếu bạn đang viết một ứng dụng phía máy chủ, trên thực tế, theo mô hình dịch vụ mạng hiện tại, chi phí mở một bàn ăn là không đáng kể, bởi vì nó phổ biến để mở các quy trình hoặc luồng theo số lượng CPU. lõi và sau đó mở chúng. Sau đó, số lượng đã được duy trì. Các quy trình và luồng sử dụng thông tin liên lạc hoặc giao tiếp không đồng bộ để xử lý nhiều kết nối đồng thời, vì vậy có thể bỏ qua chi phí mở quy trình và mở luồng. 


Trong các hệ thống hiện đại, một CPU thông thường có nhiều lõi và nhiều lõi có thể chạy nhiều luồng hoặc quy trình khác nhau cùng một lúc. Khi mỗi lõi CPU chạy một luồng, vì mỗi luồng cần chia sẻ tài nguyên, các tài nguyên này phải được sao chép từ một lõi của CPU sang lõi khác để tiếp tục tính toán, điều này sẽ chiếm thêm chi phí. Nói cách khác, khi CPU đa lõi, đa luồng sẽ không tốt bằng đa xử lý về hiệu suất. Đó là tôi nói thêm cho các bạn hiểu về đa lõi khác đa luồng đó thôi.


Tóm lại


Không cần tóm lại vì ở trên kia đã rõ ràng, ý của bài viết này nhằm giair thích cho các bạn về đa luồng trong nodejs. Nhưng Nodejs phát triển mạnh cho đến hôm nay thì không chỉ có khai thác đa luồng nhưng bản chất của đa luồng ở đây là khác với java nhé, mà còn có yêu tố về nonBloking IO, eventLoop. Hầu như các nút thắt về hiệu suất là trong các hoạt động IO. Chính vì thế thực tế, đôi khi 100 người tụ tập để ăn và 100 người xếp hàng để ăn, nhưng bạn chỉ nghe là có 100 người đến ăn. Chứ bạn đâu có nhìn rõ là hai loại hình khác nhau đâu. Chốt

Lý do tại sao Nodejs có thể xử lý đồng thời cao trong một luồng đơn là do cơ chế vòng lặp sự kiện của lớp libuv và việc triển khai nhóm luồng bên dưới.


Có thể bạn đã bị missing