104, 'Connection reset by peer' 套接字错误,或何时关闭套接字会导致 RST 而不是 FIN? [英] 104, 'Connection reset by peer' socket error, or When does closing a socket result in a RST rather than FIN?

查看:190
本文介绍了104, 'Connection reset by peer' 套接字错误,或何时关闭套接字会导致 RST 而不是 FIN?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在并行开发 Python 网络服务和客户端网站.当我们从客户端向服务发出 HTTP 请求时,一次调用始终在 socket.py 中引发 socket.error,在读取中:

We're developing a Python web service and a client web site in parallel. When we make an HTTP request from the client to the service, one call consistently raises a socket.error in socket.py, in read:

(104, 'Connection reset by peer')

当我用wireshark收听时,好"和坏"的反应看起来非常相似:

When I listen in with wireshark, the "good" and "bad" responses look very similar:

  • 由于 OAuth 标头的大小,请求被拆分为两个数据包.服务以 ACK 响应两者
  • 服务发送响应,每个标头一个数据包(HTTP/1.0 200 OK,然后是日期标头等).客户端使用 ACK 响应每个请求.
  • (好的请求)服务器发送一个 FIN、ACK.客户端以 FIN、ACK 响应.服务器响应 ACK.
  • (错误请求)服务器发送 RST、ACK,客户端不发送 TCP 响应,在客户端引发 socket.error.

Web 服务和客户端都在运行 glibc-2.6.1 的 Gentoo Linux x86-64 机器上运行.我们在同一个 virtual_env 中使用 Python 2.5.2.

Both the web service and the client are running on a Gentoo Linux x86-64 box running glibc-2.6.1. We're using Python 2.5.2 inside the same virtual_env.

客户端是一个 Django 1.0.2 应用程序,它调用 httplib2 0.4.0 来发出请求.我们使用 OAuth 签名算法对请求进行签名,OAuth 令牌始终设置为空字符串.

The client is a Django 1.0.2 app that is calling httplib2 0.4.0 to make requests. We're signing requests with the OAuth signing algorithm, with the OAuth token always set to an empty string.

该服务正在运行 Werkzeug 0.3.1,它使用 Python 的 wsgiref.simple_server.我通过 wsgiref.validator 运行了 WSGI 应用程序,没有任何问题.

The service is running Werkzeug 0.3.1, which is using Python's wsgiref.simple_server. I ran the WSGI app through wsgiref.validator with no issues.

这看起来应该很容易调试,但是当我在服务端跟踪一个好的请求时,它看起来就像是坏的请求,在 socket._socketobject.close() 函数中,将委​​托方法变成了 dummy方法.当send或sendto(不记得是哪个)方法关闭时,发送FIN或RST,客户端开始处理.

It seems like this should be easy to debug, but when I trace through a good request on the service side, it looks just like the bad request, in the socket._socketobject.close() function, turning delegate methods into dummy methods. When the send or sendto (can't remember which) method is switched off, the FIN or RST is sent, and the client starts processing.

对等连接重置"似乎将责任归咎于服务,但我也不信任 httplib2.客户有错吗?

"Connection reset by peer" seems to place blame on the service, but I don't trust httplib2 either. Can the client be at fault?

** 进一步调试 - 看起来像 Linux 上的服务器 **

** Further debugging - Looks like server on Linux **

我有一台 MacBook,所以我尝试在其中一台上运行服务,在另一台上运行客户端网站.Linux 客户端调用 OS X 服务器而没有错误 (FIN ACK).OS X 客户端调用带有错误的 Linux 服务(RST ACK 和 a (54, 'Connection reset by peer')).所以,看起来它是在 Linux 上运行的服务.是 x86_64 吗?一个糟糕的 glibc?wsgiref?还在找……

I have a MacBook, so I tried running the service on one and the client website on the other. The Linux client calls the OS X server without the bug (FIN ACK). The OS X client calls the Linux service with the bug (RST ACK, and a (54, 'Connection reset by peer')). So, it looks like it's the service running on Linux. Is it x86_64? A bad glibc? wsgiref? Still looking...

** 进一步测试 - wsgiref 看起来很不稳定 **

** Further testing - wsgiref looks flaky **

我们已经使用 Apache 和 mod_wsgi 进行生产,并且连接重置已经消失.请参阅下面的答案,但我的建议是记录连接重置并重试.这将使您的服务器在开发模式下正常运行,并在生产中稳定运行.

We've gone to production with Apache and mod_wsgi, and the connection resets have gone away. See my answer below, but my advice is to log the connection reset and retry. This will let your server run OK in development mode, and solidly in production.

推荐答案

我遇到了这个问题.请参阅Python对等方重置连接"问题.

I've had this problem. See The Python "Connection Reset By Peer" Problem.

您(很可能)遇到了基于 Python Global Interpreter Lock 的小计时问题.

You have (most likely) run afoul of small timing issues based on the Python Global Interpreter Lock.

您(有时)可以通过策略性地放置 time.sleep(0.01) 来纠正此问题.

You can (sometimes) correct this with a time.sleep(0.01) placed strategically.

在哪里?"你问.难倒我了.这个想法是在客户端请求中和周围提供一些更好的线程并发性.尝试将它放在之前您发出请求,以便重置 GIL 并且 Python 解释器可以清除任何挂起的线程.

"Where?" you ask. Beats me. The idea is to provide some better thread concurrency in and around the client requests. Try putting it just before you make the request so that the GIL is reset and the Python interpreter can clear out any pending threads.

这篇关于104, 'Connection reset by peer' 套接字错误,或何时关闭套接字会导致 RST 而不是 FIN?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆