zoukankan      html  css  js  c++  java
  • [web部署] gunicorn+supervisor

    gunicorn+supervisor

     

    1.gunicorn

    安装:

    pip3 install gunicorn

    配置:

    两种方式:命令和文件,因为配置项比较多,所以放在文件里,启动时指明配置文件即可

    命令:

    如:gunicorn –w 4 –b 0.0.0.0:5000 –c config.py manager:app

    -b 绑定应用的ip和端口

    -w work的数量,官方说可以有:核心数*+1个

    -c 指定配置文件

    manager 入口程序文件,即manager.py

    app manager中的flask对象

    配置文件config.py:

    import multiprocessing
    import os

    # 如果没有日志目录,创建一个;在当前gunicorn运行目录
    if not os.path.exists('log'):
         os.mkdir('log')

    debug = True

    bind = '0.0.0.0:5000'

    # pid文件为文本文件,内容只有一行, 记录了该进程的ID;

    # 防止进程启动多个副本。只有获得pid文件(固定路径固定文件名)写入权限(F_WRLCK)的进程才能正常启动并把自身的PID写入该文件中。其它同一个程序的多余进程则自动退出。
    pidfile = 'log/gunicorn.pid'   

    loglevel = 'debug'    # 日志等级,与accesslog相关
    logfile = 'log/gunicorn_debug.log'    # debug日志?实际没有生成
    errorlog = 'log/gunicorn_error.log'    # 运行产生的具体日志信息
    accesslog = 'log/gunicorn_access.log'    # 只有请求日志,每个请求一条,包括请求的时间,大小,路径

    access_log_format = '%(h)s %(l)s %(p)s %(u)s %(t)s %(r)s %(s)s %(b)s %(f)s %(a)s %(D)s'
    reload = True

    # 启动的进程数
    workers = multiprocessing.cpu_count()

    # 以何种方式处理请求

    # (同步:sync),(异步:gevent/eventlet),(asyncIO:gthread/ gaiohttp),(tornado:tornado)
    worker_class = 'gunicorn.workers.ggevent.GeventWorker'

    x_forwarded_for_header = 'X-FORWARDED-FOR'

    配置好后通过gunicorn –c config.py manager:app启动

    将flask日志整合进gunicorn

    这样就不需要单独存储flask的日志,最终只需要查看gunicorn记录的flask日志即可

    if __name__ != '__main__':
         # 如果不是直接运行,则将日志输出到 gunicorn 中

        # 会读取gunicorn的日志配置,如存放目录、格式等
         gunicorn_logger = logging.getLogger('gunicorn.error')
         app.logger.handlers = gunicorn_logger.handlers
         app.logger.setLevel(gunicorn_logger.level)

    TODO

    gunicorn各种模式的性能对比

    2.supervisor

    用于管理gunicorn,将其当作自己的子进程启动;当gunicorn由于异常等停止运行后,supervisor可以自动重启gunicorn

    为c/s架构supervisord 是服务端,supervisorctl 是客户端

    supervisord启动成功后,可以通过supervisorctl客户端控制进程,启动、停止、重启

    安装:

    pip3 install supervisor

    生成配置文件:

    python3不支持生成配置的命令,所以需要再额外安装python2的supervisor

    然后在python3环境下使用python2生成的配置文件

    sudo echo_supervisord_conf > /etc/supervisor/supervisord.conf

    supervisord.conf即为supervisor的配置文件

    更改配置文件:(;表示注释)

    [unix_http_server]

    ;file=/tmp/supervisor.sock ;修改为 /var/run 目录,避免被系统删除

    file=/var/run/supervisor.sock 

    ;socket文件的路径,supervisorctl用XML_RPC和supervisord通信就是通过它进行的。如果不设置的话,supervisorctl也就不能用了

    ;chmod=0700,上面的socket文件的权限设置为0700

    [supervisord]

    loglevel=debug ; 设置日志等级,默认info,其他: critical, error, warn, info, debug, trace, or blather

    ;logfile=/tmp/supervisord.log  ;修改为 /var/log 目录,避免被系统删除

    logfile= /home/user/python/flask_app/log/supervisord.log ; 
    ; 这个是supervisord自身的日志路径,和子进程的日志无关

    logfile_maxbytes=50MB ;日志文件大小,默认50M

    logfile_backups=10 ;当日志文件大于50M,会再创建一个,最多创建10个

    ;pidfile=/tmp/supervisord.pid ;修改为 /var/run 目录,避免被系统删除

    pidfile=/var/run/supervisord.pid

    ;nodaemon=false  ; 如果是true,supervisord进程将在前台运行,默认为false,也就是后台以守护进程运行

    ;设置可以管理supervisord的用户,可以设置一个非root用户,当以root用户启动supervisord之后,所设置的这个用户也可以对supervisord进行管理

    ;user=chrism

    [supervisorctl]

    serverurl=unix:///var/run/supervisor.sock  ; 必须和[unix_http_server]里面的file设定匹配

    ;[inet_http_server] ; 用web 管理界面来显示子进程运行情况
    ;port=127.0.0.1:9001 ; Web 管理后台运行的 IP 和端口,如果开放到公网,需要注意安全性
    ;username=user ; 登录管理后台的用户名
    ;password=123 ; 登录管理后台的密码

    [include]

    files = /etc/supervisor/conf.d/*.conf   

    ;设置各进程的配置,使得每个进程有自己单独的配置文件,即conf.d目录下可以有多个conf文件,每个对应一个应用

    更详细的参考:https://www.cnblogs.com/justuntil/p/9843011.html

    supervisor子进程(flask应用)配置

    program:flask_app]

    ;如果有多个命令,之间用&&分隔
    command=/home/user/python/python_virtual/flask_app/bin/gunicorn -c /home/user/python/flask_app/config_g.py manager:app


    directory=/home/user/python/flask_app ; 程序(gunicorn)的启动目录,即manger.py所在目录

    ;redirect_stderr=true的时候,stderr也会写进这个日志文件
    stdout_logfile=/home/user/python/flask_app/log/supervisor_stdout.log ; 记录控制台的输出,很有用,因为gunicorn的日志无法记录控制台的输出


    stderr_logfile=/home/user/python/flask_app/log/supervisor_stderr.log

    ; 程序中配置的日志,但实际只有warning以上级别的才会记录,所以没什么用;子进程中没有不能设置日志等级


    autostart=true ;如果是true,子进程将在supervisord启动后被自动启动,默认就是true
    autorestart=true

    ;这个是设置子进程挂掉后自动重启的情况,有三个选项,false,true和unexpected。如果为false,无论什么情况下,都不会被重新启动;如果为true,只要子进程挂掉,将会被无条件重启;如果为unexpected,只有子进程异常中断时才会重新启动。
    startsecs=10 ; 子进程启动多少秒之后,此时状态如果是running,则认为启动成功了
    priority=997 ;值越大优先级越低

    更详细的参考:https://www.cnblogs.com/zhoujinyi/p/6073705.html

    子进程管理:

    运行supervisorctl命令,不加参数,会进入supervisor客户端的交互终端

    status  --查看所有子进程状态

    start/stop/restart 子进程名  --开启或停止子进程,都不会载入最新的配置文件

    reload  --重启supervisord服务,载入最新的子进程配置文件

    reread  --读取有更新(增加)的配置文件,不会启动新添加的子进程

    update  --重启配置文件修改过的子进程

    reread/reload/update官方解释:

    supervisorctl help reread:Reload the daemon's configuration files without add/remove

    supervisorctl help reload:Restart the remote supervisord

    supervisorctl help update:Reload config and add/remove as necessary, and will restart affected programs

    总结:reload重启所有,而update仅重启更新了配置的,reread好像没什么用(因为仅更新不重启)

     注意事项:

    command用bash -c 启动 python xx.py一定要设置如下为true,否则stop不了真正的python/java进程,因为bash命令进程和真正的python进程不是同一个。    如果是command=python xx.py这样,并且程序里面没有使用多进程,则无需设置以下。
    stopasgroup = true
    killasgroup = true
    参考:https://www.cnblogs.com/ydf0509/p/9592088.html

    TODO 

    有些应用supervisor接管不了的情况

    大致流程:

    解包

    创建虚拟环境,安装gunicorn,supervisor;在python2中安装supervisor

    安装依赖:

    下载离线包,放到目标机器上直接安装

    (不可行,因为默认下载的是当前平台的包,windows与linux不兼容,不过部署到windows上是可以的)

    在目标机器移动过来的site-packages目录下执行:pip install --no-index --find-links=./ -r requirements.txt

    更改supervisor中的gunicorn启动路径

    更改路径:supervisor配置和supervisor子进程配置

    日志文件:

    gunicorn配置中的路径不用更改,gunicorn.conf在哪log文件就在哪

    更改supervisord.conf配置:

    [supervisord]

    logfile= “…/log/supervisord.log”

    更改supervisor的子进程配置:

    command = gunicorn命令目录 –c gunicorn配置目录

    directory = 应用入口文件所在目录

    stdout_logfile = 控制台日志保存位置

    stderr_logfile = log日志保存位置

    单独启动gunicorn会生成access.log/error.log,error.log不记录控制台信息

    最后的日志信息还是gunicorn的errorlog和accesslog,日志等级由gunicorn控制

    supervisor的stderr_logfile中无内容,stdout_logfile暂时也没内容

    # TODO

    stdout_logfile中没有控制台信息

    supervisor主进程被异常关闭(kill),gunicorn还是在运行,配置了stopasgroup=true,killasgroup=true还是不起作用

  • 相关阅读:
    分布式理论基础(三)时间、时钟和事件顺序
    分布式理论基础(二)选举、多数派和租约
    分布式理论基础(一)一致性及解决一致性的两种方式:2PC和3PC
    spark入门(三)键值对操作
    spark入门(二)RDD基础操作
    Python的Flask框架入门-Ubuntu
    Python __str__(self)和__unicode__(self)
    Windows下安装和使用MongoDB
    Virtualenv介绍
    python的import与from…import的区别
  • 原文地址:https://www.cnblogs.com/justaman/p/11888392.html
Copyright © 2011-2022 走看看