【问题标题】:gevent (py)wsgi graceful shutdowngevent (py)wsgi 优雅关闭
【发布时间】:2013-08-19 01:55:53
【问题描述】:

我知道(通过搜索和检查 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 的意思是等待所有 greenlet 自行终止。因此,例如,如果他们仍在处理请求,他们可以正确地完成它们。

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

有什么想法吗?

【问题讨论】:

  • 你找到方法了吗?

标签: signals wsgi gevent


【解决方案1】:

您可以通过在一个线程中运行服务器并在另一个线程中关闭它来解决问题。下面的代码在 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)

【讨论】:

  • 这部分工作。如果在发送 SIGINT 之前队列中有多个请求,则在发送 SIGINT 之后只有一个完成,其余的都被重置(TCP 连接重置)。
【解决方案2】:

正如文档字符串在服务器的停止方法中所说的 (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)

【讨论】:

    【解决方案3】:

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

    我有一个类似但不相同的问题...

    ...我的问题是即使连接仍在进行中,Python 进程也会退出。我通过在server.serve_forever() 之后添加gevent.get_hub().join() 解决了这个问题

    server = gevent.wsgi.WSGIServer(('', 80), someWSGIApp)
    gevent.signal(signal.SIGTERM, server.stop)
    server.serve_forever()
    gevent.get_hub().join()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-26
      • 2014-02-05
      • 2019-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多