104, 'Conexão redefinida pelo peer' erro de socket, ou quando se fechando resultado tomada em um RST ao invés de FIN?

StackOverflow https://stackoverflow.com/questions/383738

Pergunta

Estamos a desenvolver um serviço web Python e um web site do cliente em paralelo. Quando fazemos uma solicitação HTTP do cliente para o serviço, uma chamada levanta consistentemente um socket.error em socket.py, na leitura:

(104, 'Connection reset by peer')

Quando eu escuto com Wireshark, o "bom" e "maus" respostas muito semelhantes:

  • Devido ao tamanho do cabeçalho OAuth, o pedido é dividido em dois pacotes. Os responde serviço para ambos com ACK
  • O serviço envia a resposta, um pacote por cabeçalho (HTTP / 1.0 200 OK, então o cabeçalho de data, etc.). Os responde cliente para cada um com ACK.
  • (Boa pedido) o servidor envia um FIN, ACK. O cliente responde com um FIN, ACK. O servidor responde ACK.
  • (pedido Bad), o servidor envia um RST, ACK, o cliente não enviar uma resposta TCP, o socket.error é levantada no lado do cliente.

Tanto o serviço web eo cliente estiver executando em uma caixa x86-64 Gentoo Linux rodando glibc-2.6.1. Estamos usando Python 2.5.2 dentro da mesma virtual_env.

O cliente é um 1.0.2 aplicação Django que está chamando httplib2 0.4.0 aos pedidos make. Estamos solicitações de assinatura com o algoritmo de assinatura OAuth, com o símbolo OAuth sempre definido como uma cadeia vazia.

O serviço está sendo executado Werkzeug 0.3.1, que está usando wsgiref.simple_server do Python. Corri o aplicativo WSGI através wsgiref.validator sem problemas.

Parece que este deve ser fácil de depurar, mas quando eu rastrear através de um bom pedido no lado do serviço, ele se parece com o mau pedido, na função socket._socketobject.close (), transformando os métodos de delegado em manequim métodos. Quando o envio ou sendto (não lembro qual) método é desligado, o FIN ou RST é enviado, e os começos do cliente processamento.

"Conexão redefinida pelo mesmo nível" parece colocar a culpa sobre o serviço, mas eu não confio httplib2 quer. O cliente pode ser a culpa?

** depuração adicionais - parece que servidor em Linux **

Eu tenho um MacBook, então eu tentei executar o serviço em um e no site do cliente, de outro. O cliente Linux chama o servidor OS X sem a bug (FIN ACK). O cliente OS X chama o serviço Linux com o bug (RST ACK, e um (54, 'Conexão redefinida pelo peer')). Assim, parece que é o serviço rodando em Linux. É x86_64? Um mau glibc? wsgiref? Ainda à procura ...

** mais testes - olhares wsgiref escamosa **

Temos ido para a produção com Apache e mod_wsgi, e as redefinições de conexão desapareceram. Veja minha resposta abaixo, mas meu conselho é para registrar a redefinição de conexão e tente novamente. Isso permitirá que sua corrida OK servidor no modo de desenvolvimento, e solidamente na produção.

Foi útil?

Solução

Eu tive esse problema. Consulte O Python "Connection reset by peer" Problema .

Você tem (mais provável) entrar em conflito com questões pequenas cronometria na Interpreter Bloqueio Python global.

Você pode (às vezes) corrigir isso com um time.sleep(0.01) estrategicamente colocadas.

"Onde?" você pergunta. Me bate. A idéia é fornecer algum melhor concorrência no segmento e em torno das solicitações do cliente. Tente colocar isso só antes você faz o pedido para que o GIL é reposto e o interpretador Python pode limpar todos os tópicos pendentes.

Outras dicas

Não use wsgiref para a produção. Use Apache e mod_wsgi, ou algo mais.

Nós continuamos a ver esses redefine de conexão, por vezes, com frequência, com wsgiref (back-end usado pelo servidor de teste werkzeug e, possivelmente, outros, como o servidor de teste Django). Nossa solução foi registrar o erro, tentar novamente a chamada em um loop, e dar-se após falhas dez. httplib2 tenta duas vezes, mas precisávamos de um mais alguns. Eles parecem vir em grupos, bem como -. Adicionando um um segundo de sono pode limpar a questão

Nós nunca vimos uma redefinição de conexão durante a execução através do Apache e mod_wsgi. Eu não sei o que eles fazem de forma diferente, (talvez eles simplesmente mascará-los), mas eles não aparecem.

Quando perguntamos a comunidade dev local para obter ajuda, alguém confirmaram que ver um monte de resets de conexão com wsgiref que ir embora no servidor de produção. Há um bug lá, mas vai ser difícil encontrá-lo.

Eu sei que você está usando python, mas eu encontrei este artigo Java para ser útil.

http: //java.sun. com / JavaSE / 6 / docs / technotes / guias / net / artigos / connection_release.html

Normalmente, você terá um RST se você fizer um close que não se detém (ou seja, em que os dados podem ser descartados pela pilha se não foi enviado e ACK'd) e um FIN normal se permitir que o próximo a ficar (isto é, as esperas perto para os dados em trânsito para ser ACK'd).

Talvez tudo que você precisa fazer é definir o soquete para linger para que você remova a condição de corrida entre um não demorando perto feito sobre o soquete e os ACKs chegando?

Eu tive o mesmo problema no entanto em fazer um upload de um arquivo muito grande usando um cliente postagem python-solicitações a um nginx + uwsgi backend.

O que acabou sendo a causa foi o backend tinha um limite para o tamanho máximo de arquivo para uploads mais baixo do que o que o cliente estava tentando enviar.

O erro nunca apareceu em nossos registros uwsgi uma vez que este limite era realmente um imposto por nginx.

o aumento do limite em nginx removido o erro.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top