使用gunicorn部署flask项目

1、WSGI协议

Web框架致力于如何生成HTML代码,而Web服务器用于处理和响应HTTP请求。Web框架和Web服务器之间的通信,需要一套双方都遵守的接口协议。WSGI协议就是用来统一这两者的接口的。

2、WSGI容器

常用的WSGI容器有Gunicorn和uWSGI,但Gunicorn直接用命令启动,不需要编写配置文件,相对uWSGI要容易很多,所以这里我也选择用Gunicorn作为容器。

3、gunicorn介绍

gunicorn是一个python Wsgi http server,只支持在Unix系统上运行,来源于Ruby的unicorn项目。Gunicorn使用prefork master-worker模型(在gunicorn中,master被称为arbiter),能够与各种wsgi web框架协作。

4、gunicorn安装

gunicorn安装非常简单,使用命令pip install gunicorn即可。一般使用它,主要是为使用其异步的worker模型,还需要安装对应的异步模块。

$ pip install greenlet # 使用异步必须安装
$ pip install eventlet # 使用eventlet workers
$ pip install gevent   # 使用gevent workers

5、gunicorn使用

这里使用gunicorn来部署一个flask项目举例,此处flask框架的使用不过多阐述,不是本文的重点。

如下例子,保存为app.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

通过gunicorn -h可以看到gunicorn有非常多的配置项,因此通常会写成一个config.py文件来进行配置。

# config.py
import os
import gevent.monkey
gevent.monkey.patch_all()

import multiprocessing

# debug = True
loglevel = 'debug'
bind = "0.0.0.0:7001"
pidfile = "log/gunicorn.pid"
accesslog = "log/access.log"
errorlog = "log/debug.log"
daemon = True

# 启动的进程数
workers = multiprocessing.cpu_count()
worker_class = 'gevent'
x_forwarded_for_header = 'X-FORWARDED-FOR'

1. debug = True

生产环境不需要这个配置项,但调试的时候还是挺好用的。而且,开启debug项后,在启动gunicorn的时候可以看到所有可配置项的配置,如下所示。
之前在被上一篇博主欺骗的时候,仔细看了调试信息,发现accesslogerrorlog都没有被配置,所以导致启动以后看不到任何日志。
config.py中只需要配置需要修改的项的,大部分采用默认配置即可。默认配置的具体配置内容可以通过gunicorn -h来查询。
# Debug Info

[2018-01-18 17:38:47 +0000] [16015] [DEBUG] Current configuration:
  proxy_protocol: False
  worker_connections: 1000
  statsd_host: None
  max_requests_jitter: 0
  post_fork: <function post_fork at 0x21037d0>
  errorlog: -
  enable_stdio_inheritance: False
  worker_class: gunicorn.workers.ggevent.GeventWorker
  ssl_version: 2
  suppress_ragged_eofs: True
  syslog: False
  syslog_facility: user
  when_ready: <function when_ready at 0x2103500>
  pre_fork: <function pre_fork at 0x2103668>
  cert_reqs: 0
  preload_app: False
  keepalive: 2
  accesslog: log/debug.log
  group: 1001
  graceful_timeout: 30
  do_handshake_on_connect: False
  spew: False
  workers: 2
  proc_name: None
  sendfile: None
  pidfile: log/gunicorn.pid
  umask: 0
  on_reload: <function on_reload at 0x2103398>
  pre_exec: <function pre_exec at 0x2103d70>
  worker_tmp_dir: None
  limit_request_fields: 100
  pythonpath: None
  on_exit: <function on_exit at 0x21065f0>
  config: gunicorn_conf.py
  logconfig: None
  check_config: False
  statsd_prefix:
  secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
  reload_engine: auto
  proxy_allow_ips: ['127.0.0.1']
  pre_request: <function pre_request at 0x2103ed8>
  post_request: <function post_request at 0x2106050>
  forwarded_allow_ips: ['127.0.0.1']
  worker_int: <function worker_int at 0x2103aa0>
  raw_paste_global_conf: []
  threads: 1
  max_requests: 0
  chdir: /home/hzyangxiao2014/POPORobot/QASP
  daemon: False
  user: 1028
  limit_request_line: 4094
  access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
  certfile: None
  on_starting: <function on_starting at 0x2103230>
  post_worker_init: <function post_worker_init at 0x2103938>
  child_exit: <function child_exit at 0x21061b8>
  worker_exit: <function worker_exit at 0x2106320>
  paste: None
  default_proc_name: run:app
  syslog_addr: udp://localhost:514
  syslog_prefix: None
  ciphers: TLSv1
  worker_abort: <function worker_abort at 0x2103c08>
  loglevel: debug
  bind: ['0.0.0.0:7001']
  raw_env: []
  initgroups: False
  capture_output: False
  reload: False
  limit_request_field_size: 8190
  nworkers_changed: <function nworkers_changed at 0x2106488>
  timeout: 30
  keyfile: None
  ca_certs: None
  tmp_upload_dir: None
  backlog: 2048
  logger_class: gunicorn.glogging.Logger

2. 日志

# config.py
accesslog = "log/access.log"
errorlog = "log/debug.log"
loglevel = "debug"
  • 需要log目录存在。如果不存在,启动会报错
  • accesslog是访问日志,可以通过access_log_format设置访问日志格式。详细的方法可以见参考文章[2]
  • loglevel用于控制errorlog的信息级别,可以设置为debug、info、warning、error、critical。

3. workers

worker_class是指开启的每个工作进程的模式类型,默认为sync模式,也可使用gevent模式。

workers是工作进程数量,在上述config.py中,取的是CPU的数量。需要注意部署机器的性能,不能无限制多开。多篇文章中推荐了multiprocessing.cpu_count() * 2 + 1这个数量,考虑到我会在一个机器上部署两个服务,因此数量减半。

4. daemon

daemon = True意味着开启后台运行,默认为False

gunicorn通常使用的参数如下:

-c CONFIG, --config=CONFIG
# 设定配置文件。
-b BIND, --bind=BIND
# 设定服务需要绑定的端口。建议使用HOST:PORT。
-w WORKERS, --workers=WORKERS
# 设置工作进程数。建议服务器每一个核心可以设置2-4个。
-k MODULE
# 选定异步工作方式使用的模块。

在shell中输入你的启动配置,比如:

$ gunicorn -w 3 -b 127.0.0.1:8080 app:app
# 此处app:app中,第一个app为flask项目实例所在的包,第二个app为生成的flask项目实例

这样运行正常就可以启动服务器了。

6、绑定端口

linux通常会禁止绑定使用1024以下的端口,除非在root用户权限。很多人在使用gunicorn时试图将其绑定到80或者443端口,发现无效。如果想绑定到这些端口,常见的有如下的几种方法:

    • 使用Nginx代理转发。
    • sudo启动gunicorn。
    • 安装额外的程序。

7、结束gunicorn服务进程

使用ps -ef | grep gunicorn命令找出gunicorn所有进程。

[root@VM_0_12_centos ~]# ps -ef | grep gunicorn
root     16843 23035  0 Oct14 ?        00:00:02 /root/Envs/myflask/bin/python3.6 /root/Envs/myflask/bin/gunicorn -w 3 -b 172.17.0.12:80 app:app
root     22445 23035  0 Oct04 ?        00:00:15 /root/Envs/myflask/bin/python3.6 /root/Envs/myflask/bin/gunicorn -w 3 -b 172.17.0.12:80 app:app
root     22581 23035  0 Oct11 ?        00:00:05 /root/Envs/myflask/bin/python3.6 /root/Envs/myflask/bin/gunicorn -w 3 -b 172.17.0.12:80 app:app
root     23035     1  0 Sep27 ?        00:04:11 /root/Envs/myflask/bin/python3.6 /root/Envs/myflask/bin/gunicorn -w 3 -b 172.17.0.12:80 app:app

然后使用 kill -9 进程ID 命令来杀掉进程,注意,我们找到主进程杀掉即可,子进程会随之结束,在上例中,主进程号为23035.

[root@VM_0_12_centos ~]# kill -9 23035
[root@VM_0_12_centos ~]# ps -ef | grep gunicorn

杀掉进程后,稍等几秒,再使用ps -ef | grep gunicorn查看,发现gunicorn服务进程已全部杀掉。

 

posted @ 2020-08-17 20:08  Tracydzf  阅读(700)  评论(0编辑  收藏  举报