2008-12-20 31 views
28

Chúng tôi đang phát triển song song dịch vụ web Python và trang web ứng dụng khách. Khi chúng tôi thực hiện một yêu cầu HTTP từ máy khách đến dịch vụ này, một cuộc gọi liên tục đặt ra một socket.error trong socket.py, ở chế độ đọc:104, Lỗi kết nối do lỗi ngang hàng thiết lập kết nối hoặc khi nào đóng kết quả ổ cắm trong RST thay vì FIN?

(104, 'Connection reset by peer')

Khi tôi nghe với Wireshark là "tốt" và "xấu "phản hồi trông rất giống nhau:

  • Do kích thước của tiêu đề OAuth, yêu cầu được chia thành hai gói. Dịch vụ phản hồi cả hai với ACK
  • Dịch vụ gửi phản hồi, một gói cho mỗi tiêu đề (HTTP/1.0 200 OK, sau đó là tiêu đề Ngày, v.v.). Máy khách phản hồi với ACK.
  • (Yêu cầu tốt) máy chủ gửi FIN, ACK. Máy khách trả lời bằng FIN, ACK. Máy chủ phản hồi ACK.
  • (Yêu cầu không hợp lệ) máy chủ gửi RST, ACK, máy khách không gửi phản hồi TCP, socket.error được đặt ở phía máy khách.

Cả dịch vụ web và ứng dụng khách đang chạy trên hộp x86-64 Gentoo Linux chạy glibc-2.6.1. Chúng tôi đang sử dụng Python 2.5.2 bên trong cùng virtual_env.

Ứng dụng khách là ứng dụng Django 1.0.2 đang gọi httplib2 0.4.0 để thực hiện yêu cầu. Chúng tôi đang ký yêu cầu với thuật toán ký OAuth, với mã thông báo OAuth luôn được đặt thành một chuỗi trống.

Dịch vụ đang chạy Werkzeug 0.3.1, đang sử dụng wsgiref.simple_server của Python. Tôi đã chạy ứng dụng WSGI thông qua wsgiref.validator mà không có vấn đề gì. Có vẻ như điều này sẽ dễ dàng để gỡ lỗi, nhưng khi tôi theo dõi qua một yêu cầu tốt về phía dịch vụ, nó trông giống như yêu cầu xấu, trong hàm socket._socketobject.close(), chuyển phương thức ủy nhiệm thành phương pháp giả. Khi gửi hoặc sendto (không thể nhớ được) phương pháp được tắt, FIN hoặc RST được gửi đi, và khách hàng bắt đầu xử lý.

"Đặt lại kết nối theo đồng đẳng" dường như đổ lỗi cho dịch vụ, nhưng tôi cũng không tin tưởng httplib2. Khách hàng có bị lỗi không?

** gỡ lỗi Hơn nữa - Hình như máy chủ trên Linux **

Tôi có một MacBook, vì vậy tôi cố gắng chạy dịch vụ trên một và trang web của khách hàng về việc khác. Máy khách Linux gọi máy chủ OS X mà không có lỗi (FIN ACK). Trình khách OS X gọi dịch vụ Linux bằng lỗi (RST ACK và một (54, 'Kết nối lại bằng peer')). Vì vậy, có vẻ như đó là dịch vụ đang chạy trên Linux. Có phải là x86_64 không? Một glibc xấu? wsgiref? Vẫn đang tìm kiếm ...

** Tiếp tục thử nghiệm - wsgiref trông flaky **

Chúng tôi đã đi vào sản xuất với Apache và mod_wsgi, và reset kết nối đã biến mất. Xem câu trả lời của tôi dưới đây, nhưng lời khuyên của tôi là để đăng nhập thiết lập lại kết nối và thử lại. Điều này sẽ cho phép máy chủ của bạn chạy OK trong chế độ phát triển và vững chắc trong sản xuất.

+0

Câu hỏi thực sự là lý do máy chủ gửi yêu cầu RST. Khách hàng phải đặt lại kết nối và thông báo cho thông báo 'Kết nối lại bằng máy ngang hàng'. Vì vậy, tôi nghĩ rằng bạn đang đi đúng hướng –

Trả lời

15

Tôi đã gặp sự cố này. Xem The Python "Connection Reset By Peer" Problem.

Bạn có (rất có thể) chạy các vấn đề về thời gian nhỏ dựa trên Khóa thông dịch toàn cầu của Python.

Bạn có thể (đôi khi) sửa lỗi này với số time.sleep(0.01) được đặt chiến lược.

"Ở đâu?" bạn hỏi. Đánh tôi. Ý tưởng là cung cấp một số chủ đề đồng thời tốt hơn trong và xung quanh các yêu cầu của khách hàng. Hãy thử đặt nó chỉ trước khi bạn thực hiện yêu cầu để GIL được đặt lại và trình thông dịch Python có thể xóa bất kỳ chuỗi đang chờ xử lý nào.

+1

Trong liên kết có vẻ như vấn đề là chạy máy chủ và máy khách trong cùng một quá trình. Do đó chúng phải chịu gil. –

+0

Có, nhưng ... Bạn đang nhìn thấy những gì trông giống như thiết lập lại kết nối giống nhau ngay cả trong máy chủ khách hàng riêng biệt-máy chủ. Tôi vẫn nghĩ rằng bạn nên lộn xộn với giấc ngủ ở đây và ở đó để xem liệu thay đổi lập lịch trình có giúp ích hay không. –

+0

Có vẻ như liên kết của bạn đã chết. Dịch vụ Http/1.1 Unavailable – Bunyk

1

Thông thường, bạn sẽ nhận được RST nếu bạn đóng cửa mà không nán lại (ví dụ: trong đó dữ liệu có thể bị loại bỏ bởi ngăn xếp nếu nó chưa được gửi và ACK) và FIN bình thường nếu bạn cho phép đóng để nán lại (tức là gần chờ đợi cho các dữ liệu quá cảnh để được ACK'd).

Có lẽ tất cả những gì bạn cần làm là đặt ổ cắm của bạn để nán lại để bạn loại bỏ tình trạng cuộc đua giữa việc đóng không kéo dài trên ổ cắm và ACK đến?

8

Không sử dụng wsgiref để sản xuất. Sử dụng Apache và mod_wsgi, hoặc cái gì khác.

Chúng tôi tiếp tục xem các cài đặt lại kết nối này, đôi khi thường xuyên, với wsgiref (chương trình phụ trợ được máy chủ thử nghiệm werkzeug sử dụng và những người khác có thể như máy chủ thử nghiệm Django). Giải pháp của chúng tôi là ghi lại lỗi, thử lại cuộc gọi trong vòng lặp và từ bỏ sau mười lần thất bại. httplib2 cố gắng hai lần, nhưng chúng tôi cần thêm một vài thứ nữa. Họ dường như đi theo bó cũng - thêm một giấc ngủ 1 giây có thể xóa vấn đề.

Chúng tôi chưa bao giờ thấy kết nối được đặt lại khi chạy qua Apache và mod_wsgi. Tôi không biết họ làm gì khác, (có lẽ họ chỉ che giấu chúng), nhưng chúng không xuất hiện.

Khi chúng tôi yêu cầu cộng đồng dev địa phương trợ giúp, ai đó đã xác nhận rằng họ thấy rất nhiều lần kết nối lại với wsgiref biến mất trên máy chủ sản xuất. Có một lỗi ở đó, nhưng sẽ rất khó để tìm ra nó.

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