我看到一个奇怪的情况,Nginx或者uwsgi似乎正在build立一个长长的传入请求队列,并在客户端连接超时后尝试处理它们。 我想了解并制止这种行为。 以下是更多信息:
我的设置
我的服务器使用Nginx通过Unix文件套接字将HTTPS POST请求传递给uWSGI和Flask。 我基本上都是默认configuration。
我有一个Python客户端每秒发送3个请求到该服务器。
问题
运行客户端大约4小时后,客户端机器开始报告所有连接超时。 (它使用Python请求库,超时时间为7秒)大约10分钟后,行为发生了变化:连接开始失败,出现502 Bad Gateway。
我关掉了客户端。 但是在closures客户端电源大约10分钟后,服务器端uWSGI日志显示uWSGI试图回应来自该客户端的请求! top
显示uWSGI使用100%的CPU(每个工人25%)。
在这10分钟内,每个uwsgi.log
条目看起来像这样:
Thu May 25 07:36:37 2017 - SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request /api/polldata (ip 98.210.18.212) !!! Thu May 25 07:36:37 2017 - uwsgi_response_writev_headers_and_body_do(): Broken pipe [core/writer.c line 296] during POST /api/polldata (98.210.18.212) IOError: write error [pid: 34|app: 0|req: 645/12472] 98.210.18.212 () {42 vars in 588 bytes} [Thu May 25 07:36:08 2017] POST /api/polldata => generated 0 bytes in 28345 msecs (HTTP/1.1 200) 2 headers in 0 bytes (0 switches on core 0)
而Nginx的error.log
显示了很多这样的:
2017/05/25 08:10:29 [error] 36#36: *35037 connect() to unix:/srv/my_server/myproject.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 98.210.18.212, server: example.com, request: "POST /api/polldata HTTP/1.1", upstream: "uwsgi://unix:/srv/my_server/myproject.sock:", host: "example.com:5000"
大约10分钟后,uWSGI活动停止。 当我重新打开客户端时,Nginx很高兴地接受POST请求,但是uWSGI在每个请求中都给出了“写入一个closures的pipe道”的错误,就好像它永久地被破坏了一样。 重新启动Web服务器的docker容器不能解决问题,但重新启动主机修复它。
理论
在默认的Nginx – > socket – > uWSGIconfiguration中,有没有超时请求的长队列? 我查看了uWSGI文档,看到了一些可configuration的超时时间,但是所有的默认时间都在60秒左右,所以我不明白我是如何处理10分钟的请求的。 我没有改变任何默认的超时设置。
该应用程序几乎所有的1GB RAM在我的小开发服务器,所以我认为资源限制可能会触发行为。
无论哪种方式,我想改变我的configuration,使得> 30秒的请求被删除500错误,而不是由uWSGI处理。 我会很感激有关如何做到这一点的任何build议,以及有关发生的事情的理论。
这似乎是uWSGI方面下游的一个问题。
这听起来像你的后端代码可能是错误的,因为它需要太长的时间来处理请求,没有实现任何类型的速率限制的请求,并没有正确捕获,如果任何底层连接已经终止(因此,你收到代码尝试写入封闭管道的错误,甚至可能在底层连接终止很久之后开始处理新的请求。
根据http://lists.unbit.it/pipermail/uwsgi/2013-February/005362.html , if not uwsgi.is_connected(uwsgi.connection_fd())
,您可能想在您的后端中止处理。
您可能需要探索https://uwsgi-docs.readthedocs.io/en/latest/Options.html#harakiri 。
作为最后的手段,按照Re:了解“proxy_ignore_client_abort”功能(2014) ,您可能希望将uwsgi_ignore_client_abort
从off
更改为on
,以便不丢弃正在传递给上游的正在进行的uWSGI连接(即使客户端然后断开连接),以便不接收来自uWSGI的封闭的管道错误,并且在nginx本身内强制执行任何可能的并发连接限制(否则,如果客户端断开连接,则uWSGI的连接将被nginx丢弃,并且nginx将不会提示在uWSGI中有多少个请求正在排队以供后续处理)。
似乎对Nginx uWSGI的DoS攻击使用Nginx 502,504,500返回100%的CPU使用率.IP欺骗在DoS攻击中很常见。 排除通过检查日志。