2010-04-01 21 views
12

Tôi có một chương trình sử dụng urllib định kỳ lấy một url, và tôi thấy không liên tục lỗi như:I/O lỗi (lỗi socket): [Errno 111] Kết nối từ chối

I/O lỗi (lỗi ổ cắm): [Errno 111] Kết nối bị từ chối.

Nó hoạt động 90% thời gian, nhưng không vượt quá 10% thời gian. Nếu thử lại tìm nạp ngay sau khi nó không thành công, nó sẽ thành công. Tôi không thể tìm ra lý do tại sao điều này là như vậy. Tôi đã cố gắng để xem nếu có bất kỳ cổng nào, và họ đang có. Bất kỳ ý tưởng gỡ lỗi nào?

Đối với thông tin bổ sung, stack trace là:

File "/usr/lib/python2.6/urllib.py", line 203, in open 
    return getattr(self, name)(url) 

File "/usr/lib/python2.6/urllib.py", line 342, in open_http 
    h.endheaders() 

File "/usr/lib/python2.6/httplib.py", line 868, in endheaders 
    self._send_output() 

File "/usr/lib/python2.6/httplib.py", line 740, in _send_output 
    self.send(msg) 

File "/usr/lib/python2.6/httplib.py", line 699, in send 
    self.connect() 

File "/usr/lib/python2.6/httplib.py", line 683, in connect 
    self.timeout) 

File "/usr/lib/python2.6/socket.py", line 512, in create_connection 
    raise error, msg 

Edit - Một tìm kiếm google không phải là rất hữu ích, những gì tôi đã ra khỏi nó là máy chủ Tôi lấy từ đôi khi từ chối kết nối , làm thế nào tôi có thể xác minh nó không phải là một lỗi trong mã của tôi và điều này thực sự là trường hợp?

+3

gì "Tôi đã cố gắng để xem bất kỳ cổng nào có sẵn, và chúng có sẵn. " nghĩa là? Nếu bạn đang nhận được một ECONNREFUSED đó là một phản ứng khẳng định - ở lớp socket thô - từ máy chủ từ xa nói "Tôi nghe bạn gõ nhưng không ai đang nghe"; điều này thường là kết quả từ một máy chủ bị quá tải. Thử lại của bạn cho biết rằng đây là tạm thời cũng như tỷ lệ 90/10% của bạn. Cách chứng minh đó không phải là mã của bạn? Telnet đến cổng máy chủ. Viết một thói quen lớp socket python để thử kết nối và cung cấp cho bạn tỷ lệ nhấn/từ chối. – msw

Trả lời

36

Sử dụng gói sniffer như Wireshark để xem điều gì xảy ra. Bạn cần phải xem gói tin được gắn cờ SYN, một lần gửi cờ SYN + được gắn cờ ACK và sau đó gửi đi bằng cờ ACK. Sau đó, cảng được coi là mở ở phía địa phương.

Nếu bạn chỉ thấy gói đầu tiên và thông báo lỗi xuất hiện sau vài giây chờ đợi, phía bên kia không trả lời (như: cáp chưa cắm, máy chủ quá tải, gói bị lỗi) và mạng cục bộ của bạn hủy bỏ nỗ lực kết nối. Nếu bạn thấy các gói RST, máy chủ thực sự từ chối kết nối. Nếu bạn thấy "Cổng ICMP không thể truy cập" hoặc lưu trữ các gói không thể truy cập được, tường lửa hoặc máy chủ lưu trữ đích sẽ thông báo cho bạn về cổng thực sự bị đóng.

Tất nhiên bạn không thể mong đợi dịch vụ có sẵn mọi lúc (xem xét tất cả các điểm thất bại giữa bạn và dữ liệu), vì vậy bạn nên thử lại sau.

2

Tôi không chắc chắn chính xác nguyên nhân gây ra điều này. Bạn có thể thử tìm trong socket.py (của tôi là một phiên bản khác, vì vậy các số dòng từ dấu vết không khớp, và tôi sợ một số chi tiết khác có thể không khớp với nhau).

Dù sao, có vẻ như thực tiễn tốt để đặt mã tìm nạp url của bạn trong khối try: ... except: ... và xử lý điều này với một khoảng dừng ngắn và thử lại. URL bạn đang cố tìm nạp có thể bị hỏng hoặc quá tải và đó là thứ bạn sẽ chỉ có thể xử lý bằng thử lại.

10

Nhận thông báo lỗi ECONNREFUSED có nghĩa là hạt nhân của bạn đã bị từ chối kết nối ở đầu bên kia, vì vậy nếu đó là lỗi, nó nằm trong hạt nhân của bạn hoặc ở đầu bên kia. Những gì bạn có thể làm là để bẫy các lỗi trong một cách rất cụ thể và thử lại trong một thời gian ngắn, vì điều này dường như làm việc:

# This is Python > 2.5 code 
import errno, time 

for attempt in range(MAXIMUM_NUMBER_OF_ATTEMPTS): 
    try: 
     # your urllib call here 
    except EnvironmentError as exc: # replace " as " with ", " for Python<2.6 
     if exc.errno == errno.ECONNREFUSED: 
      time.sleep(A_COUPLE_OF_SECONDS) 
     else: 
      raise # re-raise otherwise 
    else: # we tried, and we had no failure, so 
     break 
else: # we never broke out of the for loop 
    raise RuntimeError("maximum number of unsuccessful attempts reached") 

Thay thế hai all-mũ hằng với những con số yêu thích của bạn.

3

Trước đây tôi đã gặp sự cố này với cá thể EC2 của mình (tôi đang phục vụ couchdb để phân phối tài nguyên - đang xem xét S3 của Amazon cho tương lai).

Một điều cần kiểm tra (giả sử Ec2) là cổng couchdb được thêm vào cổng mở của bạn trong chính sách bảo mật của bạn.

Tôi đặc biệt gặp

"[Errno 111] Kết nối từ chối"

trên EC2 khi dụ được dừng lại và bắt đầu. Vấn đề dường như là một cuộc đua pidfile. Các giải pháp đối với tôi là giết couchdb (hoàn toàn và đúng cách) thông qua:

pkill -f couchdb 

và sau đó khởi động lại với:

/etc/init.d/couchdb restart 
0

của nó dường như máy chủ đó không hoạt động đúng cách để đảm bảo rằng với thiết bị đầu cuối của

telnet ip port 

ví dụ

telnet localhost 8069 

Nó sẽ trở lại kết nối với localhost nên nó chỉ ra rằng không có vấn đề với kết nối khác nó sẽ trở lại kết nối từ chối nó chỉ ra rằng có vấn đề với kết nối