Nhiều công nhân không chặn VS đơn


9

Giả sử có một máy chủ HTTP mà chấp nhận kết nối và sau đó nó đã bằng cách nào đó chờ cho tiêu đề được gửi đầy đủ vào. Tôi tự hỏi những cách phổ biến nhất của việc thực hiện nó là gì và những ưu nhược điểm nghỉ ngơi và là gì. Tôi chỉ có thể nghĩ về những điều này:

Nhiều công nhân chặn là tốt vì:

  • Nó là phản ứng nhanh hơn.
  • Dễ dàng hơn để giới thiệu các kết nối mới (công nhân chọn chúng kết nối thay vì chờ người ngoài cho đến khi có thể thêm nó vào danh sách được đồng bộ hóa).
  • Việc sử dụng CPU sẽ tự động cân bằng (mà không cần bất kỳ nỗ lực bổ sung nào) khi số lượng kết nối tăng và giảm.
  • Sử dụng CPU ít hơn (các luồng bị chặn được đưa ra khỏi vòng lặp thực thi và không yêu cầu bất kỳ logic nào để nhảy giữa các máy khách).

Công nhân không chặn đơn là tốt vì:

  • Sử dụng ít bộ nhớ.
  • Ít dễ bị tổn thương hơn đối với các máy khách lười biếng (kết nối với máy chủ và gửi tiêu đề chậm hoặc không gửi gì cả).

Như bạn có thể thấy, theo tôi, nhiều luồng công nhân có vẻ là một giải pháp tốt hơn một chút về tổng thể. Vấn đề duy nhất với nó là dễ dàng hơn để tấn công máy chủ như vậy.

Chỉnh sửa (nghiên cứu thêm): Một số tài nguyên tôi tìm thấy trên web ( Hàng ngàn Chủ đề và Chặn I / O - Cách cũ để viết Máy chủ Java là Mới một lần nữa (và cách tốt hơn) của Paul Tyma) gợi ý rằng cách tiếp cận chặn nói chung tốt hơn nhưng Tôi vẫn không thực sự biết cách xử lý các kết nối giả mạo.

PS Không đề xuất sử dụng một số thư viện hoặc ứng dụng cho nhiệm vụ. Tôi quan tâm nhiều hơn đến việc biết làm thế nào nó thực sự hoạt động hoặc có thể hoạt động hơn là làm cho nó hoạt động.

PSS Tôi đã phân chia logic thành nhiều phần và phần này chỉ xử lý việc chấp nhận các tiêu đề HTTP. Không xử lý chúng.


Lo, những năm trước đây, tôi đã viết một máy chủ luồng với việc chặn I / O, bởi vì nó rất dễ viết. Một đồng nghiệp đã viết loại khác, và nó hoạt động rất đáng ngưỡng mộ. Chúng là hai hình thức cung cấp sản phẩm chính tại một công ty tôi từng làm việc. Đối với "khách hàng lười biếng" trong kịch bản chặn, bạn có thể có thời gian chờ nhận dữ liệu.

Câu trả lời:


4

Không có viên đạn bạc

Trong thực tế, nó phụ thuộc ...

tl; dr - giải pháp dễ dàng, sử dụng nginx ...

Chặn:

Chẳng hạn, Apache theo mặc định sử dụng sơ đồ chặn trong đó quy trình được rẽ nhánh cho mọi kết nối. Điều đó có nghĩa là mọi kết nối đều cần không gian bộ nhớ riêng và lượng chi phí chuyển đổi theo ngữ cảnh tăng lên nhiều hơn khi số lượng kết nối tăng lên. Nhưng lợi ích là, khi một kết nối được đóng lại, bối cảnh có thể được xử lý và bất kỳ / tất cả bộ nhớ có thể được lấy lại dễ dàng.

Một cách tiếp cận đa luồng sẽ tương tự ở chỗ chi phí chuyển đổi ngữ cảnh tăng theo số lượng kết nối nhưng có thể hiệu quả hơn về bộ nhớ trong ngữ cảnh được chia sẻ. Vấn đề với cách tiếp cận như vậy là rất khó để quản lý bộ nhớ dùng chung theo cách an toàn. Các cách tiếp cận để khắc phục các vấn đề đồng bộ hóa bộ nhớ thường bao gồm chi phí riêng của họ, ví dụ, khóa có thể đóng băng luồng chính trên các tải nặng của CPU và sử dụng các loại không thay đổi sẽ thêm rất nhiều sao chép dữ liệu không cần thiết.

AFAIK, sử dụng cách tiếp cận đa quy trình trên máy chủ HTTP chặn thường được ưa thích vì quản lý / khôi phục bộ nhớ theo cách an toàn / đơn giản hơn theo cách an toàn. Thu gom rác trở thành một vấn đề khi khôi phục bộ nhớ đơn giản như dừng quá trình. Đối với các quy trình chạy dài (tức là một daemon), đặc tính đó đặc biệt quan trọng.

Mặc dù chi phí chuyển đổi ngữ cảnh có vẻ không đáng kể với một số lượng nhỏ công nhân, nhưng nhược điểm trở nên phù hợp hơn khi tải có quy mô lên tới hàng trăm đến hàng ngàn kết nối đồng thời. Tốt nhất, chuyển đổi ngữ cảnh quy mô O (n) thành số lượng công nhân có mặt nhưng trong thực tế, điều đó rất có thể tồi tệ hơn.

Trong đó các máy chủ sử dụng chặn có thể không phải là lựa chọn lý tưởng cho tải nặng IO, thì chúng rất lý tưởng cho công việc đòi hỏi nhiều CPU và việc truyền thông điệp được giữ ở mức tối thiểu.

Không chặn:

Không chặn sẽ là một cái gì đó giống như Node.js hoặc nginx. Chúng đặc biệt được biết đến khi nhân rộng số lượng kết nối lớn hơn nhiều cho mỗi nút dưới tải trọng chuyên sâu IO. Về cơ bản, một khi mọi người đạt đến giới hạn trên của những máy chủ dựa trên luồng / quy trình nào có thể xử lý thì họ bắt đầu khám phá các tùy chọn thay thế. Điều này còn được gọi là vấn đề C10K (tức là khả năng xử lý 10.000 kết nối đồng thời).

Các máy chủ không đồng bộ không chặn thường chia sẻ rất nhiều đặc điểm với cách tiếp cận đa luồng có khóa, bạn phải cẩn thận để tránh tải quá nhiều CPU vì bạn không muốn làm quá tải luồng chính. Ưu điểm là chi phí phát sinh do chuyển đổi ngữ cảnh về cơ bản được loại bỏ và chỉ với một thông điệp ngữ cảnh chuyển thành không thành vấn đề.

Mặc dù nó có thể không hoạt động đối với nhiều giao thức mạng, bản chất không trạng thái HTTP hoạt động đặc biệt tốt đối với các kiến ​​trúc không chặn. Bằng cách sử dụng kết hợp proxy ngược và nhiều máy chủ HTTP không chặn, có thể xác định và định tuyến xung quanh các nút chịu tải nặng.

Ngay cả trên một máy chủ chỉ có một nút, việc thiết lập bao gồm một máy chủ cho mỗi lõi bộ xử lý để tối đa hóa thông lượng.

Cả hai:

Trường hợp sử dụng 'lý tưởng' sẽ là sự kết hợp của cả hai. Một proxy ngược ở phía trước dành riêng cho các yêu cầu định tuyến ở trên cùng, sau đó là sự kết hợp giữa các máy chủ chặn và không chặn. Không chặn các tác vụ IO như phục vụ nội dung tĩnh, nội dung bộ đệm, nội dung html. Chặn các tác vụ nặng về CPU như mã hóa hình ảnh / video, truyền phát nội dung, bấm số, ghi cơ sở dữ liệu, v.v.

Trong trường hợp của bạn:

Nếu bạn chỉ kiểm tra các tiêu đề nhưng không thực sự xử lý các yêu cầu, về cơ bản những gì bạn mô tả là một proxy ngược. Trong trường hợp như vậy, tôi chắc chắn sẽ đi theo cách tiếp cận không đồng bộ.

Tôi khuyên bạn nên kiểm tra tài liệu cho proxy ngược tích hợp nginx .

Qua một bên:

Tôi đã đọc bài viết từ liên kết bạn cung cấp và điều đó có nghĩa là async là một lựa chọn kém cho việc triển khai cụ thể của họ. Vấn đề có thể được tóm tắt trong một tuyên bố.

Nhận thấy rằng khi chuyển đổi giữa các máy khách, mã để lưu và khôi phục giá trị / trạng thái là khó khăn

Họ đang xây dựng một nền tảng nhà nước. Trong trường hợp như vậy, một cách tiếp cận không đồng bộ sẽ có nghĩa là bạn phải liên tục lưu / tải trạng thái mỗi khi bối cảnh chuyển đổi (tức là khi một sự kiện xảy ra). Ngoài ra, về phía SMTP họ đang thực hiện rất nhiều công việc đòi hỏi nhiều CPU.

Có vẻ như họ đã nắm bắt khá kém về async và kết quả là đã đưa ra rất nhiều giả định tồi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.