zoukankan      html  css  js  c++  java
  • 转载——gunicorn的实践经验

    gunicorn的实践经验

    mania_yan 2020-03-08 21:42:31 783 收藏 3
    分类专栏: python
    版权
    为什么要上gunicorn?
    flask自带的web容器不满足生产环境的要求。生产环境不能直接采用flask自带的web容器。

    gunicorn是目前应用较广的支持WSGI的web容器。

    gunicorn能否替代flask自带的web容器进行开发调试?
    可以,加入- -reload,则代码变更后,gunicorn会自动重启。

    gunicorn的worker选择gevent时的注意事项
    当没有指定worker类型时,默认为同步类型,线程为native类型。

    异步worker gevent有很强的并发性能

    当worker指定为gevent或evenlet类型时,线程变成基于greentlet的task(伪线程),这时,线程数量的参数是无效的。

    采用gevent worker时,默认并发数量是1000,有很强的并发能力。

    gevent的兼容性问题

    但是,使用gevent时,系统会使用monkey patch。系统的部分函数会被修改。

    有些库的使用要选择兼容gevent的类型。

    例如,任务调度的库apscheduler,web socket需要socketio的库等,需要专门选择gevent的函数。

    而有些库则直接无法使用,例如多进程multiprocess。

    例如,在一个api请求中,如果需要使用多核cpu资源,采用multiprocess进行多进程计算。则会出现卡死的问题。gevent中,不能使用multiprocess库

    gunicorn的timeout参数
    gunicorn默认的timeout时间是30秒,这是满足web应用的典型参数。

    但是,我们是深度学习的领域,任务的执行需要的时间很长,所以,timeout参数是一个常用的参数。

    gunicorn的管理进程如果在timeout时间内,没有收到worker进程的消息心跳,则会认为worker进程出现了死亡,从而重启相应的worker进程。

    会导致worker进程正在执行的任务被中断。

    worker进程处于阻塞或高CPU计算时,会出现不能及时发送心跳给管理进程的问题。

    因此,对于深度学习领域,timeout要根据业务场景有余量的进行设置,才能保证时间较久的任务不被管理进程中断。

    gunicorn什么时候使用- -preload参数
    preload

    Load application code before the worker processes are forked

    默认情况下,gunicorn的每个进程,会将代码重新加载一次,以保障进程之间是互相隔离的。这样可以做到更好的兼容性。

    但是,有些情况,需要多个进程共享同一个资源时,或多个进程只能开启1个任务时,则需要使用- -preload

    使用preload后,API函数之外的初始化代码,只会出现在gunicorn的管理进程中,以共享的方式让worker进程访问

    (这个需要大家自己写demo代码好好体验一下,尤其是初始化变量打印进程号,感知一下preload的差异

    可以参考示例:https://testerhome.com/topics/18306)

    思考:gunicorn每个进程在执行log的rotate时的问题。

    gunicorn如何集成进程序,不通过命令行进行启动
    目前算法采用pyinstaller进行打包,只有一个自启动的执行文件,无法采用传统的gunicorn命令行加载内部代码变量的方式启动。

    制作基于gunicorn自启动执行文件,可以参考:http://docs.gunicorn.org/en/latest/custom.html

    gunicorn的日志问题
    我们平时的日志,只记录业务代码的日志。

    第三方库的日志和gunicorn自身的日志没有被正常记录在日志文件中,必须在docker的日志里去查看,这样不方便也容易导致丢失或管理不统一。

    简单示例代码:

    加入gunicorn日志

    去掉默认的,防止内容和gunicorn重复

    logger.removeHandler(default_handler)

    加入gunicorn的handler

    logger.handlers.extend(logging.getLogger('gunicorn.error').handlers)

    详细使用参考gunicorn的日志配置部分

    或者业务代码的log不变,gunicorn通过配置让其日志单独输出一个文件

    web socket的场景
    web socket是一个长连接方案,gunicorn默认的同步方式是不支持长连接的。

    当使用web socket时,建议独立一个程序,使用异步worker。否则,将它集成到主程序中,会强迫主程序的worker从同步改为异步。

    在ops模块中,主程序需要将最新信息推送到web时,可以通过消息队列(ops模块使用的是zeromq)实现进程间的通信,然后通过web socket的独立程序将消息发送到浏览器。

    未来,可以尝试ASGI的框架,ASGI是兼容WSGI,同时支持长连接的web socket和http2的推送机制,进一步简化设计。

    另外,web socket独立一个程序之后,需要关注其监控问题。

    默认的docker启动gunicorn服务,gunicorn服务死亡,docker服务会自动重启。

    但是,web socket采用另一个独立的后台进程服务,它的死亡不会导致docker重启。因此,如果web socket进程意外死亡是不会被自动重启的。需要加入监控软件。

    官方推荐了很多,目前项目已经使用的有supervisor,使用非常简单。

    其他问题
    为什么ocr server中,要加入nginx,有什么作用?

    正常来说,无需nginx,gunicorn可以正常提供服务。

    但是,C++的插件在发送图片给ocr server时,经常会出现witch的错误(目前未知什么原因)。

    加入nginx后,无此问题。

    (官方推荐使用nginx:Although there are many HTTP proxies available, we strongly advise that you use Nginx.)

    原文连接:https://blog.csdn.net/yyw794/article/details/104741340/

  • 相关阅读:
    Good Bye 2014 B. New Year Permutation(floyd )
    hdu 5147 Sequence II (树状数组 求逆序数)
    POJ 1696 Space Ant (极角排序)
    POJ 2398 Toy Storage (叉积判断点和线段的关系)
    hdu 2897 邂逅明下 (简单巴什博弈)
    poj 1410 Intersection (判断线段与矩形相交 判线段相交)
    HDU 3400 Line belt (三分嵌套)
    Codeforces Round #279 (Div. 2) C. Hacking Cypher (大数取余)
    Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings (容斥原理)
    hdu 1576 A/B (求逆元)
  • 原文地址:https://www.cnblogs.com/pythonwl/p/14270517.html
Copyright © 2011-2022 走看看