2009-03-11 29 views
9

Gần đây tôi đã đọc this document liệt kê một số chiến lược có thể được sử dụng để triển khai máy chủ socket. Cụ thể, đó là:Viết một máy chủ dựa trên socket trong Python, các chiến lược được khuyến nghị?

  1. Phục vụ nhiều khách hàng với mỗi chủ đề, và sử dụng nonblocking I/O và thông báo sẵn sàng cấp kích hoạt
  2. Phục vụ nhiều khách hàng với mỗi chủ đề, và sử dụng nonblocking I/O và sự sẵn sàng thay đổi thông báo
  3. phục vụ nhiều khách hàng với mỗi thread máy chủ, và sử dụng không đồng bộ I/O
  4. phục vụ một khách hàng với mỗi thread máy chủ, và sử dụng blocking I/O
  5. Xây dựng mã máy chủ vào kernel

Bây giờ, tôi sẽ đánh giá cao một gợi ý mà nên được sử dụng trong CPython, mà chúng ta biết có một số điểm tốt, và một số điểm xấu. Tôi chủ yếu quan tâm đến hiệu năng theo đồng thời cao, và có một số hiện thực hiện tại quá chậm.

Vì vậy, nếu tôi có thể bắt đầu bằng cách dễ dàng, "5" là ra, như tôi sẽ không được hack bất cứ điều gì vào hạt nhân.

"4" Cũng có vẻ như nó phải nằm ngoài GIL. Tất nhiên, bạn có thể sử dụng đa xử lý thay cho các chủ đề ở đây, và điều đó làm tăng đáng kể. Chặn IO cũng có lợi thế là dễ hiểu hơn.

Và đây kiến ​​thức của tôi suy yếu một chút:

"1" là truyền thống chọn hoặc thăm dò có thể được trivially kết hợp với đa xử lý.

"2" là thông báo sự sẵn sàng thay đổi, được sử dụng bởi epoll mới hơn và kqueue

"3" Tôi không chắc chắn có bất kỳ triển khai hạt nhân cho điều này có wrappers Python.

Vì vậy, trong Python, chúng tôi có một túi các công cụ tuyệt vời như Twisted. Có lẽ họ là một cách tiếp cận tốt hơn, mặc dù tôi đã chuẩn bị cho Twisted và thấy nó quá chậm trên một máy xử lý đa. Có lẽ có 4 xoắn với một cân bằng tải có thể làm điều đó, tôi không biết. Lời khuyên nào sẽ được đánh giá cao.

Trả lời

7

asyncore về cơ bản là "1" - Nó sử dụng select nội bộ và bạn chỉ có một chuỗi xử lý tất cả yêu cầu. Theo tài liệu, nó cũng có thể sử dụng poll. (EDIT: Gỡ bỏ tham chiếu Twisted, tôi nghĩ rằng nó được sử dụng asyncore, nhưng tôi đã sai).

"2" có thể được triển khai với python-epoll (Chỉ cần googled nó - không bao giờ thấy trước đây). EDIT: (từ nhận xét) Trong python 2.6 số select module có tính năng epoll, kqueue và kevent built-in (trên nền tảng được hỗ trợ). Vì vậy, bạn không cần bất kỳ thư viện bên ngoài nào để thực hiện dịch vụ kích hoạt cạnh.

Không loại trừ "4", vì GIL sẽ bị xóa khi chuỗi đang thực sự đang hoạt động hoặc chờ các hoạt động IO (phần lớn thời gian). Nó không có ý nghĩa nếu bạn đã có số lượng lớn các kết nối của khóa học. Nếu bạn đã có rất nhiều xử lý để làm, sau đó python có thể không có ý nghĩa với bất kỳ các chương trình này.

Để linh hoạt, hãy xem Twisted?

Trong thực tế, vấn đề của bạn sẽ giảm xuống mức độ xử lý bạn sẽ thực hiện đối với các yêu cầu. Nếu bạn có nhiều xử lý và cần tận dụng lợi thế của hoạt động song song đa lõi, thì có thể bạn sẽ cần nhiều quy trình. Mặt khác, nếu bạn chỉ cần nghe trên nhiều kết nối, sau đó chọn hoặc epoll, với một số lượng nhỏ các chủ đề nên làm việc.

+0

Tôi nghĩ epoll là trong stdlib trong 2.6+, và easy_installable cho 2.5. Gói được gọi là select-something. Xin lỗi vì sự mơ hồ. –

+0

Xoắn cũng có thể sử dụng epoll. Trong thực tế, Twisted biến tất cả các API thông báo sự kiện được hỗ trợ thành một API đồng bộ mà nó trình bày cho bạn. Vì vậy, nếu tốt nhất nền tảng có thể làm là chọn, ứng dụng của bạn sử dụng lựa chọn. Nếu nó có epoll, ứng dụng của bạn sử dụng epoll. Tất cả đều trong suốt cho bạn. –

+0

Nó được viết là 'asyncore' – new123456

1

http://docs.python.org/library/socketserver.html#asynchronous-mixins

Đối với máy đa xử lý (đa lõi). Với CPython do GIL, bạn sẽ cần ít nhất một quy trình trên mỗi lõi, để mở rộng quy mô. Khi bạn nói rằng bạn cần CPython, bạn có thể thử điểm chuẩn với ForkingMixIn. Với Linux 2.6 có thể đưa ra một số kết quả thú vị.

Cách khác là sử dụng Stackless Python. Đó là how EVE solved it. Nhưng tôi hiểu rằng không phải lúc nào cũng có thể.

+0

Cảm ơn, nhưng bạn đã chuẩn bị những điều đó chưa? Chúng chậm. Tôi sẽ không phát minh ra bánh xe nếu tôi không phải làm vậy. –

+0

+1 stackless/EVE, nhưng tôi đã nói CPython –

1

Tôi thích Douglas' câu trả lời, nhưng như là một dành ...

Bạn có thể sử dụng một sợi công văn tập trung/quá trình lắng nghe thông báo sẵn sàng sử dụng select và các đại biểu đến một vũng đề người lao động/processes để giúp thực hiện mục tiêu song song của bạn. Tuy nhiên, như Douglas đã đề cập, GIL sẽ không được tổ chức trong hầu hết các hoạt động I/O dài (vì không có điều Python-API đang xảy ra), vì vậy nếu độ trễ đáp ứng của bạn, bạn có thể thử di chuyển các phần quan trọng của mã của bạn vào API CPython.

2

Tôi có thể đề xuất các liên kết bổ sung không?

cogen là thư viện đa nền tảng cho lập trình dựa trên mạng, coroutine dựa trên bằng cách sử dụng trình tạo nâng cao từ python 2.5. Trên trang chính của dự án cogen có liên kết đến một số dự án với mục đích tương tự.

3

Làm thế nào về "ngã ba"? (Tôi cho rằng đó là những gì mà ForkingMixIn thực hiện) Nếu các yêu cầu được xử lý trong kiến ​​trúc "không có gì" (không phải DB hoặc hệ thống tập tin), fork() khởi động khá nhanh trên hầu hết các nixes, và bạn không phải lo lắng về tất cả các lỗi ngớ ngẩn và biến chứng từ luồng.

Chủ đề là một bệnh thiết kế buộc chúng tôi bởi hệ điều hành với quá trình trọng lượng quá nặng, IMHO. Nhân bản một bảng trang với các thuộc tính copy-on-write có vẻ như một mức giá nhỏ, đặc biệt là nếu bạn đang chạy một trình thông dịch.

Xin lỗi tôi không thể cụ thể hơn, nhưng tôi chi tiết của một lập trình viên Perl-đang chuyển đổi-to-Ruby (khi tôi không slaving hơn khối lượng của Java tại nơi làm việc)


Cập nhật : Cuối cùng tôi đã làm một số timings trên thread vs fork trong "thời gian rảnh rỗi" của tôi. Check it out:

http://roboprogs.com/devel/2009.04.html

mở rộng: http://roboprogs.com/devel/2009.12.html

+0

ngoài ra, bạn có thể lấy mã cho các mô-đun khác mà bạn biết bạn sẽ sử dụng trước khi bạn bắt đầu quá trình con. Điều này sẽ khiến chúng không bị mã hóa (JIT-ed, bất cứ điều gì) hơn và hơn. Thứ hai, giữ dữ liệu trong phụ huynh nhỏ, sử dụng "thoát" như một bộ thu gom rác siêu. – Roboprog

3

Một sollution là gevent. Gevent maries một cuộc thăm dò sự kiện dựa trên libevent với chuyển đổi nhiệm vụ hợp tác nhẹ được thực hiện bởi greenlet.

Những gì bạn nhận được là tất cả hiệu suất và khả năng mở rộng của một hệ thống sự kiện với mô hình đơn giản và đơn giản về chặn chương trình IO.

(Tôi không biết quy ước SO về trả lời câu hỏi thực sự cũ là gì, nhưng tôi vẫn quyết định thêm 2 xu)

Các vấn đề liên quan