1. 程式人生 > 實用技巧 >使用gunicorn部署flask專案

使用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服務程序已全部殺掉。