uwsgi reload拒绝传入连接

2024-04-23 10:41:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试安装一个uwsgi托管的应用程序,这样我就可以很好地重新加载uwsgi——重新加载,但我显然失败了。这是我的测试uwsgi设置:

[admin2-prod]
http = 127.0.0.1:9090
pyargv = $* --db=prod --base-path=/admin/
max-requests = 3
listen=1000
http-keepalive = 1
pidfile2 =admin.pid
add-header=Connection: keep-alive
workers = 1
master = true
chdir = .
plugins = python,http,router_static,router_uwsgi,router_http
buffer-size = 8192
pythonpath = admin2
file = admin2/app.py
static-map=/admin/static/=admin2/static/
static-map=/admin/v3/build/=admin2/client/build/
disable-logging = false
http-timeout = 100

(请注意,我运行的是sysctlnet.core.somaxconn=1000之前)

下面是我的测试python脚本:

^{pr2}$

上述客户端在--reload期间失败:

sending...  920
Traceback (most recent call last):
  File "./test.py", line 15, in <module>
    connection.connect()
  File "/usr/lib64/python2.7/httplib.py", line 836, in connect
    self.timeout, self.source_address)
  File "/usr/lib64/python2.7/socket.py", line 575, in create_connection
    raise err
socket.error: [Errno 111] Connection refused

从tcpdump来看,uwsgi确实在接受第二个传入的TCP请求,该请求发生在--reload时,客户机正在发送GET,服务器正在对其进行TCP确认,但是在发送回HTTP响应之前,服务器最终对连接进行了RSTed。那么,在服务器准备好处理这个传入的连接并获得真正优雅的重新加载之前,我还缺少什么呢?在


Tags: inpybuild服务器httpmapadminline
2条回答

您在同一个uWSGI实例中同时管理应用程序和代理,因此当您重新加载堆栈时,您也会杀死前端web服务器(以“http”选项开头的服务器)。在

您必须在另一个uWSGI实例中拆分http路由器,或者使用nginx/haproxy或类似工具。一旦有了两个不同的堆栈,就可以在不关闭套接字的情况下重新加载应用程序

当uwsgi进程显然不能接受连接时,就会发生异常。。。所以,您的进程必须等到服务器重新启动——您可以在except块中使用带超时的循环来正确处理这种情况。试试这个:

import httplib
import socket
import time

connection = httplib.HTTPConnection('127.0.0.1', 8000)
# connection moved below... connection.connect()

for i in range(0, 1000):
    print 'sending... ', i    
    try:
        connection.request('GET', '/x', '', {'Connection' : ' keep-alive'})
        response = connection.getresponse()
        d = response.read()       
        print '    ', response.status
    except KeyboardInterrupt: 
        break
    except socket.error:    
        while True:
            try:
                connection = httplib.HTTPConnection('127.0.0.1', 8000)
                connection.connect()
            except socket.error:
                print 'cant connect, will try again in a second...'
                time.sleep(1)  
            else:
                break

重新启动前:

^{pr2}$

正在重新启动服务器:

cant connect, will try again in a second...
cant connect, will try again in a second...
cant connect, will try again in a second...
cant connect, will try again in a second...

服务器重新启动:

sending...  223
     404
sending...  224
     404
sending...  225
     404

更新您的评论:

Obviously, in the real world, you can't rewrite the code of all the http clients that connect to your server. My question is: what can I do to get a graceful reload (no failures) for arbitrary clients.

我认为这是一个通用的解决方案,我认为它可以处理客户端和服务器之间的简单代理问题。使用代理,您可以独立于客户端重新启动服务器(意味着代理始终处于打开状态)。 事实上,这是常用的-502(坏网关)错误来自web应用程序前端代理-完全相同的情况-客户端收到来自代理的错误,而应用程序服务器关闭!试试nginx、varnish或类似的东西。在


顺便说一句,uwsgi内置了“代理/负载平衡器/路由器”插件:

The uWSGI FastRouter

For advanced setups uWSGI includes the “fastrouter” plugin, a proxy/load-balancer/router speaking the uwsgi protocol. It is built in by default. You can put it between your webserver and real uWSGI instances to have more control over the routing of HTTP requests to your application servers.

此处有文档:http://uwsgi-docs.readthedocs.io/en/latest/Fastrouter.html

相关问题 更多 >