2010-04-01 23 views
12

tengo un programa que utiliza urllib a buscar periódicamente una dirección URL, y veo intermitentes errores como: errorerror I/O (error de socket): [Errno 111] Conexión rechazada

I/O (error de socket): [Errno 111] Conexión rechazada.

Funciona el 90% del tiempo, pero el otro r10% falla. Si vuelve a intentar la recuperación inmediatamente después de que falla, tiene éxito. No puedo entender por qué esto es así. Traté de ver si hay puertos disponibles, y lo están. ¿Alguna idea de depuración?

Para información adicional, el seguimiento de la pila es:

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 

Editar - Una búsqueda en Google no es muy útil, lo que tengo de ella es que el servidor estoy ir a buscar a veces se niega conexiones , ¿cómo puedo verificar que no es un error en mi código y este es realmente el caso?

+3

¿Qué significa "Traté de ver si todos los puertos están disponibles, y lo son ". ¿media? Si obtiene un ECONNREFUSED que es una respuesta afirmativa (en la capa de socket sin procesar) del host remoto que dice "Te escucho tocar pero nadie está escuchando"; esto generalmente resulta de un servidor sobrecargado. Su reintento indica que esto es transitorio, al igual que su proporción de 90/10%. ¿Cómo demostrar que no es su código? Telnet al puerto del servidor. Escribe una rutina de capa de socket python para probar las conexiones y darte la proporción hit/refused. – msw

Respuesta

36

Utilice un sniffer de paquetes como Wireshark para ver qué pasa. Necesita ver un paquete saliente SYN marcado, un mensaje entrante marcado SYN + y luego un mensaje saliente marcado por ACK. Después de eso, el puerto se considera abierto en el lado local.

Si solo ve el primer paquete y el mensaje de error aparece después de varios segundos de espera, el otro lado no responde (como en: cable desenchufado, servidor sobrecargado, paquete descartado se descartó) y su pila de red local aborta el intento de conexión. Si ve paquetes RST, el host realmente niega la conexión. Si ve "Puerto ICMP inalcanzable" o no encuentra los paquetes inalcanzables, un cortafuegos o el host de destino le informan que el puerto se está cerrando realmente.

Por supuesto, no puede esperar que el servicio esté disponible en todo momento (tenga en cuenta todos los puntos de falla entre usted y los datos), por lo que debe intentarlo más tarde.

2

No estoy exactamente seguro de lo que está causando esto. Puedes intentar buscar en tu socket.py (el mío es una versión diferente, por lo que los números de línea del rastreo no coinciden, y me temo que otros detalles pueden no coincidir también).

De todos modos, parece una buena práctica poner su código de recuperación de URL en un bloque try: ... except: ..., y manejar esto con una breve pausa y un nuevo intento. La URL que intentas recuperar puede estar caída o demasiado cargada, y eso es solo lo que podrás manejar con un intento de todos modos.

10

Obtener un ECONNREFUSED errno significa que su núcleo se rechazó una conexión en el otro extremo, por lo que si se trata de un error, es en su kernel o en el otro extremo. Lo que puede hacer es interceptar el error de una manera muy específica y vuelve a intentarlo dentro de un rato, ya que esto parece funcionar:

# 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") 

Reemplazar las dos constantes en mayúsculas con sus números favoritos.

3

Anteriormente tuve este problema con mi instancia de EC2 (estaba sirviendo a couchdb para servir recursos, estoy considerando el S3 de Amazon para el futuro).

Una cosa para comprobar (suponiendo que Ec2) es que el puerto couchdb se agrega a sus puertos abiertos dentro de su política de seguridad.

me encontré específicamente

"[Errno 111] Conexión rechazada"

sobre EC2 cuando la instancia se detiene y se inicia. El problema parece ser una carrera pidfile. La solución para mí estaba matando couchdb (por completo y correctamente) a través de:

pkill -f couchdb 

y reiniciando con:

/etc/init.d/couchdb restart 
0

Sus parece que el servidor no está funcionando correctamente para asegurar que con el terminal por

telnet ip port 

ejemplo

telnet localhost 8069 

Se volverá conectado a localhost lo que indica que no hay ningún problema con la conexión de lo contrario volverá Conexión rechazada indica que hay un problema con la conexión

Cuestiones relacionadas