zoukankan      html  css  js  c++  java
  • 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中。

  • 相关阅读:
    第三方驱动备份与还原
    Greenplum 解决 gpstop -u 指令报错
    yum安装(卸载)本地rpm包的方法(卸载本地安装的greenplum 5.19.rpm)
    Java JUC(java.util.concurrent工具包)
    netty 详解(八)基于 Netty 模拟实现 RPC
    netty 详解(七)netty 自定义协议解决 TCP 粘包和拆包
    netty 详解(六)netty 自定义编码解码器
    netty 详解(五)netty 使用 protobuf 序列化
    netty 详解(四)netty 开发 WebSocket 长连接程序
    netty 详解(三)netty 心跳检测机制案例
  • 原文地址:https://www.cnblogs.com/lit10050528/p/14179951.html
Copyright © 2011-2022 走看看