2012-06-24 43 views
8

Tôi có vấn đề về thiết kế:Python: Ổ cắm và chủ đề?

Tôi có hai luồng, chuỗi nhịp tim/kiểm soát và chuỗi chủ đề thư.

Cả hai đều đang chia sẻ cùng một socket, tuy nhiên chuỗi messageHandler chỉ gửi các tin nhắn và không bao giờ nhận được. Chuỗi nhịp tim gửi và nhận (nhận tin nhắn và phản ứng trên nhịp tim).

Vấn đề là tôi không chắc liệu điều này có an toàn không. Không có cơ chế, bản thân tôi, thực hiện để xem nếu các ổ cắm đang được sử dụng. Vì vậy, việc chia sẻ một socket trên python có tự động thread an toàn hay không?

Ngoài ra nếu không, lý do tôi đặt chúng trong một chuỗi riêng biệt là do nhịp tim quan trọng hơn xử lý tin nhắn. Điều này có nghĩa rằng nếu nó bị tràn ngập các tin nhắn, nó vẫn cần phải làm một nhịp tim. Vì vậy, nếu tôi phải thực hiện một bu lông, là có đi tôi có thể ưu tiên nếu nhịp tim của tôi/kiểm soát thread cần phải gửi một nhịp tim?

Trả lời

4

Thật không may, Ổ cắm được chia sẻ bởi nhiều chủ đề không phải là chủ đề an toàn. Suy nghĩ về bộ đệm hai luồng hoạt động không có khóa.

Cách thông thường để thực hiện là với hai socket, giống như ftp does.cmd socket và msg socket.

Nếu bạn muốn thực hiện điều này bằng một ổ cắm, bạn có thể đặt các loại thông điệp khác nhau vào hàng đợi khác nhau và với chuỗi thứ ba tiêu thụ hàng đợi và gửi chúng qua ổ cắm duy nhất.

Bằng cách này, bạn có thể kiểm soát thông điệp nhắn tin nhịp tim với thông điệp dữ liệu.

+1

Đọc trên một chuỗi và gửi từ một chủ đề khác là chuỗi an toàn? – Colateral

0

Tôi không biết cách ưu tiên ở cấp độ Python.

Vì vậy, tôi khuyên bạn nên sử dụng 2 quy trình chứ không phải đề tài và ưu tiên ở cấp hệ điều hành. Trên Unix bạn có thể sử dụng os.nice() để làm điều đó.

Bạn sẽ cần sử dụng 2 ổ cắm sau đó và sự cố chia sẻ của bạn sẽ được giải quyết cùng một lúc.

0

Nếu cả hai luồng đều là chủ đề của khách hàng, bạn nên mở hai ổ cắm máy khách đến máy chủ để tìm nhịp tim và một cho giao tiếp.

8

Cách tốt hơn thay vì sử dụng chuỗi thứ ba là sử dụng threading.Lock() để bảo vệ tài nguyên socket vì điều này sẽ loại bỏ nhu cầu của chuỗi thứ ba. Bạn có chi phí thấp hơn và độ trễ thấp hơn nếu bạn có chuỗi thứ ba.

import threading 

lock = threading.Lock() 

def sendfunction(sock, data): 
    with lock: 
     sock.send(data) 

Bạn có thể gọi từ một trong hai chủ đề của bạn nhưng chỉ một chuỗi mỗi lần được phép gọi sock.send. Khi một sợi đạt đến khóa đã bị khoá bởi một luồng khác, nó sẽ ngủ cho đến khi luồng khác giải phóng khóa, sau đó nó sẽ lấy khóa và quá trình lặp lại.

Các mô-đun threading chứa Lock, RLockCondition mà tất cả đều rất hữu ích khi giao dịch với nhiều chủ đề và bạn sẽ thấy nó cũng có giá trị thời gian của bạn để làm quen với họ và sử dụng của họ.

Bạn có thể kết hợp nhịp tim vào việc xử lý tin nhắn bằng cách kiểm tra thời gian hiện tại với lần cuối bạn gửi nhịp tim trước khi xử lý từng thư và điều đó sẽ không bị tràn ngập các thư gây ra nhịp tim không được gửi. Vấn đề là nếu mã xử lý tin nhắn của bạn không chạy thì không có nhịp tim nào được gửi đi. Bạn có thể giảm bớt điều này bằng cách xử lý tin nhắn của bạn có được một tin nhắn giả trên khoảng thời gian để cho phép nó để kiểm tra xem nó cần phải gửi một nhịp tim và chỉ cần bỏ qua thông điệp giả.

Bạn nên cố gắng sử dụng các chủ đề một cách tiết kiệm (nhằm mục đích cho một chuỗi) tuy nhiên trong trường hợp của bạn, một chuỗi có thể sẽ không sao vì nó sẽ dành phần lớn thời gian để ngủ. Tuy nhiên, bạn không nên sử dụng một chuỗi daemon vì chúng không tắt đúng cách. Mặc dù thiệt hại có thể là không tồn tại trong trường hợp của bạn nếu nó không tắt đúng cách nó vẫn có thể ném một số loại lỗi (thông báo lỗi) trông xấu.

Tôi không đồng ý với phương pháp nhiều ổ cắm vì tôi cho rằng nó sẽ thực sự làm phức tạp tình hình. Bạn sẽ tìm thấy nhiều loại dịch vụ mạng/ứng dụng trên mạng kết hợp nhịp tim và tin nhắn vào một luồng byte socket đơn.

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