gevent(py)wsgi graceful shutdown

时间:2013-08-16 15:32:46

标签: signals wsgi gevent

我知道的唯一方法(从搜索和检查gevent的源代码)到优雅地关闭gevent WSGI服务器是:

server = gevent.wsgi.WSGIServer(('', 80), someWSGIApp)
def shutdown():
  print('Shutting down ...')
  server.stop(timeout=60)
  exit(signal.SIGTERM)
gevent.signal(signal.SIGTERM, shutdown)
server.serve_forever()

现在, graceful 的意思是等待所有的greenlets自行终止。因此,例如,如果他们仍在提供请求,他们可以正确地完成它们。

问题是,使用上面的看似正确的代码,服务器确实等待最大值。 60秒,但所有TCP连接在收到SIGTERM后立即终止。然而,Greenlets继续做他们所做的事情(例如睡觉),直到他们完成或超时发生。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

docstring在服务器的stop方法中说(gevent.baseserver.BaseServer:stop)

Stop accepting the connections and close the listening socket.

If the server uses a pool to spawn the requests, then :meth:`stop` also 
for all the handlers to exit. 
If there are still handlers executing after *has expired (default 1 second), 
then the currently running handlers in the pool are killed.

我没有尝试这个,但如果文档是正确的,你应该能够用这样的东西得到优雅的停止:

from gevent.pool import Pool

pool_size = 8
worker_pool = Pool(pool_size)
gevent.wsgi.WSGIServer(('', 80), someWSGIApp, spawn=worker_pool)

答案 1 :(得分:0)

  

,但是所有TCP连接在收到SIGTERM后立即终止。

我遇到了类似但不完全相同的问题...

...我的问题是,即使连接仍在进行中,Python进程也会退出。我在header(Location: ../whatever)

之后添加了gevent.get_hub().join()解决了这个问题
server.serve_forever()

答案 2 :(得分:0)

您可以通过在一个线程中运行服务器并在另一个线程中关闭服务器来解决该问题。下面的代码在Python 3.7中运行。

from gevent.pywsgi import WSGIServer
import signal
import threading

# define your app here
app = ...

server_address = ("localhost", 4000)


class WebServer(threading.Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        global server
        server = WSGIServer(server_address, app)
        server.serve_forever()


def shutdown(num, info):
    print(f'Shutting down website server...\n'
          f'{num} {info}')
    server.stop()
    server.close()


if __name__ == "__main__":
    server = None
    WebServer().start()

    signal.signal(signal.SIGINT, shutdown)