[英]How to run a background timer in Flask
我正在尝试编写一个Flask应用程序,该应用程序在Kubernetes中运行时尤其是在正常关机时运行正常 。
因此,我需要代码:
到目前为止,我所得到的是:
from flask import Flask, abort
import signal
import time
app = Flask(__name__)
shuttingDown = False
def exit_gracefully(self, signum):
app.logger.error('Received shutdown signal. Exiting gracefully')
global shuttingDown
shuttingDown = True
# TODO: wait for some time here to ensure we are not receiving any more
# traffic
time.sleep(20)
exit(0)
signal.signal(signal.SIGTERM, exit_gracefully)
@app.route("/")
def hello():
return "Hello World!"
@app.route("/_status/liveness")
def liveness():
return "I am alive"
@app.route("/_status/readiness")
def readiness():
if not shuttingDown:
return "I am ready"
else:
abort(500, 'not ready anymore')
除了我发送“ shutdown”信号后,上述“工作”正常,对“ /”的常规请求均未响应,即使我们仍处于关闭“宽限期”(上述代码中为20秒)内。
似乎对“ time.sleep()”的调用是同步的。
有谁知道使这种“异步”的方法吗? 这样,该应用就可以继续处理请求,直到时间到了为止。
猜测您正在使用内置的Flask开发服务器。 Flask和Django中的此类内置开发服务器,或标准库中基于Web服务器或WSGI服务器的任何内容,均不适用于生产系统,并且通常无法正确处理信号的关闭。
因此,您实际上应该使用适当的生产级WSGI服务器,例如Apache / mod_wsgi(mod_wsgi-express),gunicorn或uWSGI。 这些都正确地处理了信号,并且开发服务器没有问题,它们忽略了导致容器关闭延迟的信号,当关闭超时发生时,它最终被Kubernetes杀死。
这适用于内部服务器。 需要注意的是,有一个/ _shutdown URL可以关闭服务器,这对恶意关闭很开放。 如果这不是你想要的,然后取出requests.post()
并取消os._exit()
当然, @app.route("/_shutdown")
删除@app.route("/_shutdown")
和该函数。
from flask import Flask, abort, request
import signal
import threading
import time
import os
import requests
app = Flask(__name__)
shuttingDown = False
def exit_call():
time.sleep(20)
requests.post("http://localhost:5420/_shutdown")
# os._exit(0)
def exit_gracefully(self, signum):
app.logger.error('Received shutdown signal. Exiting gracefully')
global shuttingDown
shuttingDown = True
# TODO: wait for some time here to ensure we are not receiving any more
# traffic
_et = threading.Thread(target=exit_call)
_et.daemon = True
_et.start()
signal.signal(signal.SIGTERM, exit_gracefully)
@app.route("/")
def hello():
return "Hello World!"
@app.route("/_status/liveness")
def liveness():
return "I am alive"
@app.route("/_shutdown", methods=["POST"])
def shutdown():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
return "Not a werkzeug server"
func()
return "shutdown"
@app.route("/_status/readiness")
def readiness():
if not shuttingDown:
return "I am ready"
else:
abort(500, 'not ready anymore')
app.run(port=5420)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.