Đã đăng: 2 năm
Tôi đã bắt đầu mày mò với máy chủ HTTP của Node.js và thực sự thích viết Javascript phía máy chủ nhưng có điều gì đó khiến tôi không thể bắt đầu sử dụng Node.js cho ứng dụng web của mình.

Tôi hiểu toàn bộ khái niệm I / O không đồng bộ nhưng tôi hơi lo ngại về các trường hợp cạnh mà mã thủ tục rất tốn CPU chẳng hạn như thao tác hình ảnh hoặc sắp xếp các tập dữ liệu lớn.

Theo tôi hiểu, máy chủ sẽ rất nhanh cho các yêu cầu trang web đơn giản như xem danh sách người dùng hoặc xem một bài đăng trên blog. Tuy nhiên, nếu tôi muốn viết mã đòi hỏi rất nhiều CPU (ví dụ như trong phần cuối của quản trị viên) để tạo đồ họa hoặc thay đổi kích thước hàng nghìn hình ảnh, yêu cầu sẽ rất chậm (vài giây). Vì mã này không đồng bộ, mọi yêu cầu đến máy chủ trong vài giây đó sẽ bị chặn cho đến khi yêu cầu chậm của tôi được thực hiện.

Một gợi ý là sử dụng Nhân viên web cho các tác vụ chuyên sâu về CPU. Tuy nhiên, tôi e rằng nhân viên web sẽ khó viết mã sạch vì nó hoạt động bằng cách bao gồm một tệp JS riêng biệt. Điều gì sẽ xảy ra nếu mã chuyên sâu của CPU nằm trong phương thức của một đối tượng? Thật là tệ khi viết một tệp JS cho mọi phương pháp sử dụng nhiều CPU.

Một gợi ý khác là tạo ra một quy trình con, nhưng điều đó làm cho mã này thậm chí còn ít khả năng bảo trì hơn.

Bất kỳ đề xuất để vượt qua trở ngại (nhận thức) này? Làm thế nào để bạn viết mã hướng đối tượng sạch sẽ với Node.js trong khi đảm bảo các tác vụ nặng của CPU được thực thi không đồng bộ?
Chia sẻ trên dòng thời gian

Thủ Thuật Hay Đã tham gia: 7 năm

Đã đăng: 2 năm
Đây là sự hiểu lầm về định nghĩa của máy chủ web - nó chỉ nên được sử dụng để "nói chuyện" với khách hàng. Các tác vụ tải nặng nên được giao cho các chương trình độc lập (tất nhiên cũng có thể được viết bằng JS).
Có thể bạn sẽ nói rằng nó bẩn, nhưng tôi đảm bảo với bạn rằng một quy trình máy chủ web bị mắc kẹt trong việc thay đổi kích thước hình ảnh còn tồi tệ hơn (ngay cả đối với Apache, khi nó không chặn các truy vấn khác). Tuy nhiên, bạn có thể sử dụng một thư viện chung để tránh dư thừa mã.

CHỈNH SỬA: Tôi đã đưa ra một phép loại suy; ứng dụng web phải như một nhà hàng. Bạn có bồi bàn (máy chủ web) và đầu bếp (công nhân). Nhân viên phục vụ tiếp xúc với khách hàng và làm những công việc đơn giản như cung cấp thực đơn hoặc giải thích xem món ăn nào đó có phải là món ăn chay không. Mặt khác, họ giao những nhiệm vụ khó hơn cho nhà bếp. Bởi vì nhân viên phục vụ chỉ làm những việc đơn giản nên họ đáp ứng nhanh và đầu bếp có thể tập trung vào công việc của họ.

Node.js ở đây sẽ là một người phục vụ đơn lẻ nhưng rất tài năng có thể xử lý nhiều yêu cầu cùng một lúc, và Apache sẽ là một nhóm những người phục vụ ngu ngốc chỉ xử lý một yêu cầu mỗi người. Nếu người phục vụ Node.js này bắt đầu nấu ăn, đó sẽ là một thảm họa ngay lập tức. Tuy nhiên, việc nấu nướng cũng có thể làm kiệt quệ ngay cả một lượng lớn nhân viên phục vụ của Apache, chưa kể đến sự hỗn loạn trong nhà bếp và sự suy giảm dần độ nhạy bén.

297 hữu ích
5 bình luận
chia sẻ
Tạ Kiên Giang
Tạ Kiên Giang
·
05:21 21/02/2017
05:21:32 21/02/2017
Bạn không muốn mã chuyên sâu của CPU của mình thực thi không đồng bộ, bạn muốn nó thực thi song song . Bạn cần thực hiện công việc xử lý ra khỏi chuỗi đang phân phát các yêu cầu HTTP. Đó là cách duy nhất để giải quyết vấn đề này. Với NodeJS, câu trả lời là mô-đun cụm, đối với các quá trình sinh sản con cái để thực hiện công việc nặng nhọc. (AFAIK Node không có bất kỳ khái niệm nào về luồng / bộ nhớ chia sẻ; nó là quá trình hoặc không có gì). Bạn có hai tùy chọn về cách bạn cấu trúc ứng dụng của mình. Bạn có thể nhận được giải pháp 80/20 bằng cách tạo ra 8 máy chủ HTTP và xử lý đồng bộ các tác vụ máy tính chuyên sâu trên các quy trình con. Làm điều đó là khá đơn giản. Bạn có thể mất một giờ để đọc về nó tại liên kết đó. Trên thực tế, nếu bạn chỉ tách mã ví dụ ở đầu liên kết đó, bạn sẽ đi được 95% con đường đến đó.

Một cách khác để cấu trúc điều này là thiết lập hàng đợi công việc và gửi các tác vụ tính toán lớn qua hàng đợi. Lưu ý rằng có rất nhiều chi phí được liên kết với IPC cho một hàng đợi công việc, vì vậy điều này chỉ hữu ích khi các nhiệm vụ lớn hơn đáng kể so với tổng chi phí.

Tôi ngạc nhiên rằng không có câu trả lời nào trong số những câu trả lời khác thậm chí đề cập đến cụm.

Thông tin cơ bản: Mã không đồng bộ là mã tạm ngừng cho đến khi điều gì đó xảy ra ở một nơi khác , tại thời điểm đó mã thức dậy và tiếp tục thực thi. Một trường hợp rất phổ biến mà một cái gì đó chậm phải xảy ra ở một nơi khác là I / O.

Mã không đồng bộ sẽ không hữu ích nếu bộ xử lý của bạn chịu trách nhiệm thực hiện công việc. Đó chính xác là trường hợp của các tác vụ "tính toán chuyên sâu".

Bây giờ, có vẻ như mã không đồng bộ là thích hợp, nhưng trên thực tế, nó rất phổ biến. Nó chỉ xảy ra không hữu ích cho các tác vụ tính toán chuyên sâu.

Ví dụ, chờ đợi trên I / O là một mô hình luôn xảy ra trong các máy chủ web. Mọi khách hàng kết nối với máy chủ của bạn đều nhận được một ổ cắm. Hầu hết thời gian các ổ cắm trống. Bạn không muốn làm bất cứ điều gì cho đến khi một ổ cắm nhận được một số dữ liệu, tại thời điểm đó bạn muốn xử lý yêu cầu. Bên dưới, một máy chủ HTTP như Node đang sử dụng thư viện sự kiện (libev) để theo dõi hàng nghìn ổ cắm đang mở. Hệ điều hành thông báo cho libev và sau đó libev thông báo cho NodeJS khi một trong các ổ cắm nhận được dữ liệu và sau đó NodeJS đặt một sự kiện vào hàng đợi sự kiện và mã http của bạn bắt đầu tại thời điểm này và xử lý các sự kiện lần lượt. Các sự kiện không được đưa vào hàng đợi cho đến khi socket có một số dữ liệu, vì vậy các sự kiện không bao giờ chờ dữ liệu - nó đã ở đó cho chúng.

Máy chủ web dựa trên sự kiện một luồng có ý nghĩa như một mô hình khi nút cổ chai đang chờ đợi trên một loạt các kết nối ổ cắm trống rỗng và bạn không muốn toàn bộ chuỗi hoặc quy trình cho mỗi kết nối không hoạt động và bạn không muốn thăm dò 250 nghìn của mình ổ cắm để tìm ổ cắm tiếp theo có dữ liệu trên đó.

18 hữu ích
4 bình luận
chia sẻ

Vũ Bảo Anh
Vũ Bảo Anh
·
04:29 23/08/2010
04:29:28 23/08/2010
Một số cách tiếp cận bạn có thể sử dụng.

Như @Tim lưu ý, bạn có thể tạo một tác vụ không đồng bộ nằm bên ngoài hoặc song song với logic phục vụ chính của bạn. Phụ thuộc vào yêu cầu chính xác của bạn, nhưng ngay cả cron cũng có thể hoạt động như một cơ chế xếp hàng.

WebWorkers có thể làm việc cho các quy trình không đồng bộ của bạn nhưng chúng hiện không được node.js hỗ trợ. Có một số tiện ích mở rộng cung cấp hỗ trợ, ví dụ: http://github.com/cramforce/node-worker

Bạn vẫn có thể sử dụng lại các mô-đun và mã thông qua cơ chế "yêu cầu" tiêu chuẩn. Bạn chỉ cần đảm bảo rằng công việc gửi ban đầu cho nhân viên chuyển tất cả các thông tin cần thiết để xử lý kết quả.

7 hữu ích
0 bình luận
chia sẻ
Hoàng Đức Thiên
Hoàng Đức Thiên
·
10:27 20/06/2018
10:27:21 20/06/2018
Sử dụng child_processlà một trong những giải pháp. Nhưng mỗi tiến trình con được sinh ra có thể tiêu tốn rất nhiều bộ nhớ so với cờ vâygoroutines