2011-11-29 35 views
6

Tôi đã đọc tài liệu C10K cũng như nhiều tài liệu liên quan về mở rộng quy mô lên máy chủ socket. Tất cả các con đường đều trỏ đến những điều sau:Mô hình phân luồng và chia tỷ lệ cho máy chủ TCP với epoll

  1. Tránh sai lầm cổ điển của "chuỗi cho mỗi kết nối".

  2. Thích epoll hơn chọn.

  3. Tương tự như vậy, cơ chế đồng bộ cũ io trong Unix có thể khó sử dụng.

Máy chủ TCP đơn giản của tôi chỉ lắng nghe kết nối máy khách trên ổ cắm trên cổng chuyên dụng. Khi nhận được kết nối mới, phân tích cú pháp yêu cầu và gửi trả lời lại. Sau đó, đóng cửa ổ cắm một cách duyên dáng.

Tôi nghĩ rằng tôi có một xử lý tốt về cách mở rộng quy mô này lên một chuỗi đơn bằng cách sử dụng epoll. Chỉ cần một vòng lặp gọi epoll_wait cho ổ cắm nghe cũng như cho các kết nối máy khách hiện có. Khi trở về, mã sẽ xử lý mới tạo các kết nối máy khách mới cũng như quản lý trạng thái của các kết nối hiện có tùy thuộc vào ổ cắm nào vừa được báo hiệu. Và có lẽ một số logic để quản lý thời gian chờ kết nối, đóng cửa duyên dáng của ổ cắm và phân bổ nguồn lực hiệu quả cho mỗi kết nối. Dường như đủ đơn giản.

Nhưng điều gì sẽ xảy ra nếu tôi muốn mở rộng quy mô này để tận dụng nhiều chuỗi và nhiều lõi CPU? Ý tưởng cốt lõi lưu ý đến điều này là:

Một chuỗi chuyên dụng để nghe các kết nối đến trên ổ cắm nghe TCP. Sau đó, một tập hợp các luồng N (hoặc nhóm luồng) để xử lý tất cả các kết nối máy khách đồng thời hoạt động. Sau đó phát minh ra một số thread an toàn cách mà trong đó các chủ đề nghe sẽ "gửi" kết nối mới (socket) đến một trong các chủ đề công nhân có sẵn. (ala IOCP trong Windows). Chuỗi công nhân sẽ sử dụng vòng lặp epoll trên tất cả các kết nối mà nó đang xử lý để làm những gì mà phương pháp tiếp cận luồng đơn sẽ làm.

Tôi có đi đúng hướng không? Hoặc có mẫu thiết kế chuẩn để thực hiện máy chủ TCP có epoll trên nhiều chủ đề không?

Đề xuất về cách chuỗi nghe sẽ gửi kết nối mới đến nhóm luồng?

+0

Nếu bạn chọn ngôn ngữ linh hoạt, bạn có thể thử http://vibed.org/ tóm tắt bản chất không đồng bộ của lập trình không đồng bộ để bạn vẫn có thể lập trình theo cách đồng bộ. ví dụ: ubyte [] buf = new ubyte [] (1024); dữ liệu tự động = conn.read (buf); conn.write (dữ liệu); – rmc

Trả lời

-1

Tôi đoán bạn đang đi đúng hướng. Nhưng tôi cũng nghĩ rằng chi tiết phụ thuộc vào tình huống cụ thể (bandwidh, các mẫu yêu cầu, xử lý yêu cầu riêng biệt, v.v.). Tôi nghĩ bạn nên thử và đánh giá cẩn thận.

2
  1. Trước hết, lưu ý rằng đó là C * 10K *. Đừng quan tâm bản thân nếu bạn nhỏ hơn 100 (trên một hệ thống điển hình). Ngay cả khi nó phụ thuộc vào những gì ổ cắm của bạn đang hoạt động.
  2. Có, nhưng lưu ý rằng thao tác epoll yêu cầu cuộc gọi hệ thống và chi phí của chúng có thể hoặc không đắt hơn chi phí tự quản lý một số ít là fd_set. Điều tương tự cũng xảy ra với poll. Ở mức thấp, nó rẻ hơn khi thực hiện xử lý trong không gian người dùng mỗi lần lặp.
  3. IO không đồng bộ là rất đau đớn khi bạn không bị ràng buộc chỉ với một vài ổ cắm mà bạn có thể sắp xếp theo yêu cầu. Hầu hết mọi người đối phó bằng cách sử dụng vòng lặp sự kiện, nhưng những đoạn này và đảo ngược luồng chương trình của bạn.Nó cũng thường đòi hỏi phải sử dụng các khung công tác lớn, khó sử dụng cho mục đích này vì vòng lặp sự kiện đáng tin cậy và nhanh chóng không dễ dàng để có được quyền.

Câu hỏi đầu tiên là, bạn có cần điều này không? Nếu bạn đang bàn tay đối phó với lưu lượng truy cập hiện có bằng cách sinh ra các luồng để xử lý từng yêu cầu đến, thì hãy tiếp tục thực hiện theo cách này. Mã sẽ đơn giản hơn cho nó, và tất cả các thư viện của bạn sẽ chơi độc đáo.

Như tôi đã đề cập ở trên, việc tung hứng các yêu cầu đồng thời có thể phức tạp. Nếu bạn muốn làm điều này trong một vòng lặp duy nhất, bạn cũng sẽ cần phải đảm bảo về sự chết đói của CPU khi tạo ra các phản hồi của bạn.

Mô hình gửi mà bạn đề xuất là giải pháp bước đầu tiên điển hình nếu câu trả lời của bạn đắt tiền để tạo ra. Bạn có thể ngã ba hoặc sử dụng đề tài. Chi phí cho việc tạo hoặc tạo luồng không nên xem xét trong việc chọn cơ chế gộp chung: thay vào đó bạn nên sử dụng cơ chế như vậy để giới hạn hoặc đặt hàng tải được đặt trên hệ thống.

Ghép ổ cắm vào nhiều vòng epoll quá mức. Sử dụng nhiều quy trình nếu bạn đang tuyệt vọng này. Lưu ý rằng có thể accept trên ổ cắm từ nhiều luồng và quy trình.

+0

Matt, tôi thực sự chưa viết cốt lõi mạng TCP. Vì vậy, tôi rõ ràng không thấy bất kỳ lý do nào để bắt đầu với mô hình "thread per connection" nếu có một mẫu thiết kế tốt hơn để xem xét trước. Có phải nói rằng "chọn" rẻ hơn epoll cho số lượng ổ cắm thấp? Bạn có thể giải thích về vấn đề "cpu starvation" không? Tôi đồng ý với điểm thiết kế cân bằng tải. Và tôi đã xem xét nhiều chủ đề chặn tất cả. – selbie

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