• gevent WSGIServer实现优雅退出


    一、背景

    项目中其中一个服务原来是基于tornado开发的,虽然tornado是一个异步框架,但是由于业务逻辑中存在大量的同步操作,例如:查数据、查es等;导致服务性能很低,于是经过调研最终决定将底层框架切换到gevent,但是该优化上线后发现每次更新时耗时很长需要十几秒,因此抽时间排查了一下这里的问题做了一个优化。

    二、代码

    2.1、优化前

    def sig_handler(signum, frame):
        MyLogger().getlogger().info('ENTRANCE: signum:%s, frame:%s', signum, frame)
        tornado.ioloop.IOLoop.instance().add_callback(grace_shutdown)
        MyLogger().getlogger().info('add callback finish')
    
    signal.signal(signal.SIGINT, sig_handler)
    signal.signal(signal.SIGTERM, sig_handler)
    

    2.2、优化后

    def sig_handler(signum, frame):
        MyLogger().getlogger().info('stop service')
        g_wsgi_server.stop()
    
    gevent.signal.signal(signal.SIGTERM, sig_handler)
    gevent.signal.signal(signal.SIGINT, sig_handler)
    

    这里是由于底层框架切换到gevent之后,服务启动之后的循环其实已经是由gevent在负责了,因此在sig_handler中调用tornado的add_callback是不会被调度到的。

    三、效果

    优化前重启服务:

    优化后重启服务:

    3.1、结论

    从前端对比可以很明确的看到停止服务的速度从平均10s减少到不到1s。

    四、supervisor的机制

    虽然问题解决了,但是这里有一个疑问,当我手动使用kill -s TERM pid给进程发送信号时进程一直运行着,但是supervisor是如何使进程强制关闭的呢?
    翻了一下supervisor的官方文档,并没有关于stop机制的实现介绍。
    但是却意外从supervisor的日志中翻到一下这些记录:

    从这个日志推测,supervisor停止服务的应该是:

    1. 发送SIGTERM信号到进程。
    2. 每隔2秒查询一下进程是否还在。
    3. 如果等待超过10s,则发送SIGKILL信号强制关闭服务进程。
    4. 再次查询进程是否还在,此时进程应该肯定被关闭了,毕竟SIGKILL无法被捕获。

    到此就理清了supervisor停止服务的机制,也和效果对比中的实验相呼应:为什么优化前停止服务需要将近10s中。

  • 相关阅读:
    layui的table中日期格式转换
    动态数据网站
    卷积的微分以及积分性质
    傅里叶变换时域积分性质
    矩阵导数的一些笔记
    3层模式下长时间调用的进度条提示方案
    有限区域内的孤立点(极点,有限阶0点)数量有限。
    关于复变函数积分--原函数法
    android 获取文本框回车输入
    企业网络搭建
  • 原文地址:https://www.cnblogs.com/lit10050528/p/14179951.html
Copyright © 2020-2023  润新知