[英]uwsgi: Send http response and continue execution
来自 uwsgi 文档:
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]
是否可以响应 http 请求(关闭 http 连接)并继续执行流程(不使用任何线程/队列/外部服务等)? 像这样:
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
end_response(b"Hello World")
#HTTP connection is closed
#continue execution..
不幸的是,您在返回响应后无法继续执行代码。 如果使用多线程,会容易得多,但如果不使用多线程,则可以通过在HTML响应中添加AJAX调用来解决该问题,该调用将向服务器额外路由之一发送POST请求,该路由的处理函数将是您想要的执行代码返回响应后。 这是使用Flask的一种可能的方法:
myflaskapp.py
from flask import Flask, render_template_string
import time
app = Flask(__name__)
@app.route('/run', methods=['POST'])
def run():
# this is where you put your "continue execution..." code
# below code is used to test if it runs after HTTP connection close
time.sleep(8)
print('Do something')
return ''
@app.route('/')
def index():
return render_template_string('''
Hello World!
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(function() {
$.ajax({
type: "POST",
url: "{{ url_for('run') }}"
});
})
</script>
''')
if __name__ == "__main__":
app.run(host='0.0.0.0')
您可以使用以下命令在端口9091上运行服务器:
uwsgi --http 127.0.0.1:9091 --wsgi-file myflaskapp.py --callable app
要测试它是否正常工作,可以转到地址localhost:9091
。 如果一切正常,您应该看到页面立即被加载,而终端仅打印输出Do something
经过8 seconds have passed
后Do something
,表明该函数run
在HTTP连接关闭后执行。
TL;DR - 如果您使用的是 Django,您可以跳到答案的末尾。
是的,有办法做到这一点。 您可以连接到application
可调用返回的 object 的.close()
方法(或者,通过 env 返回的wsgi.file_wrapper 。
检查 PEP333,特别是服务器端规范部分: https://peps.python.org/pep-0333/#the-server-gateway-side :
result = application(environ, start_response)
try:
for data in result:
if data: # don't send headers until body appears
write(data)
if not headers_sent:
write('') # send headers now if body was empty
finally:
if hasattr(result, 'close'):
result.close()
如您所见, result.close()
将在最后被调用,此时数据已经发送。
当然,这只是一些参考代码,它不处理上游和在继续执行之前终止连接。 但是表现良好的 wsgi 服务器,例如uwsgi
和(大概) gunicorn
,可以。 他们将通过关闭套接字(或上游协议要求的任何内容)向上游发出请求已完成发送的信号,然后调用.close()
。
如果你使用的是 Django,你已经设置好了,因为它有request_finished信号。 这是它的工作原理,它与.close()
挂钩,如上所述:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.