天天看點

Python WSGI 高性能伺服器 - Gunicorn 簡介

作者:獨一無二的Python君

一、簡介

Gunicorn 意即 Green Unicorn,綠色獨角獸。它是一個被廣泛使用的高性能的 Python WSGI UNIX HTTP伺服器,移植自Ruby的獨角獸(Unicorn )項目。

它具有如下特性:

  • 原生支援 WSGI、Django 和 Paster
  • 自動工作程序管理
  • 簡單的 Python 配置
  • 多個 worker 配置
  • 多種可擴充性伺服器挂鈎
  • 相容 Python 3.x >= 3.5

二、安裝

$ pip install gunicorn
複制代碼           

或者從源碼安裝:

$ pip install git+https://github.com/benoitc/gunicorn.git
複制代碼           

如果你需要使用異步 workers,你還需要安裝:

$ pip install greenlet            # Required for both
$ pip install eventlet            # For eventlet workers
$ pip install gunicorn[eventlet]  # Or, using extra
$ pip install gevent              # For gevent workers
$ pip install gunicorn[gevent]    # Or, using extra
複制代碼           

三、使用

假如你有以下應用:

def app(environ, start_response):
    """Simplest possible application object"""
    data = b'Hello, World!\n'
    status = '200 OK'
    response_headers = [
        ('Content-type', 'text/plain'),
        ('Content-Length', str(len(data)))
    ]
    start_response(status, response_headers)
    return iter([data])
複制代碼           

指令行啟動:

$ gunicorn --workers=2 test:app
複制代碼           

也可以使用工廠模式:

def create_app():
    app = FrameworkApp()
    ...
    return app
複制代碼           
$ gunicorn --workers=2 'test:create_app()'
複制代碼           

四、配置

Gunicorn從5個地方依次讀取配置:

  1. 環境變量
  2. 架構配置
  3. gunicorn.conf.py 配置檔案
  4. 環境變量中的 GUNICORN_CMD_ARGS
  5. 指令行

常見配置項:

  • --config 配置檔案
  • --reload 代碼更改時重新啟動
  • --access-logfile 要寫入的通路日志檔案
  • --error-logfile 要寫入的錯誤日志檔案
  • --log-level 錯誤輸出級别
  • --certfile SSL證書檔案
  • --bind 綁定socket
  • --workers 處理請求的工作程序數
  • --threads 用于處理請求的工作線程數

五、伺服器鈎子

  • on_starting 在主程序初始化之前調用
  • on_reload 重新加載期間調用
  • when_ready 在伺服器啟動後立即調用
  • pre_fork 在fork之前調用
  • post_fork 在fork之後調用
  • post_worker_init 在work初始化之後調用
  • worker_int 在worker 退出 SIGINT 或 SIGQUIT 後立即調用
  • worker_abort 在worker 收到SIGABRT 信号時調用
  • pre_exec 新的主程序之前調用
  • pre_request 處理請求之前調用
  • post_request 處理請求後調用
  • child_exit 在主程序中退出工作程式後立即調用
  • worker_exit worker退出後調用
  • nworkers_changed 在_num_workers_更改後_立即_調用
  • on_exit 在退出 Gunicorn 之前調用

六、部署

官方強烈建議在代理伺服器後面使用 Gunicorn。

Nginx:

盡管有許多可用的 HTTP 代理,但官方建議您使用 Nginx。

Nginx配置檔案示例:

worker_processes 1;

user nobody nogroup;
# 'user nobody nobody;' for systems with 'nobody' as a group instead
error_log  /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
  worker_connections 1024; # increase if you have lots of clients
  accept_mutex off; # set to 'on' if nginx worker_processes > 1
  # 'use epoll;' to enable for Linux 2.6+
  # 'use kqueue;' to enable for FreeBSD, OSX
}

http {
  include mime.types;
  # fallback in case we can't determine a type
  default_type application/octet-stream;
  access_log /var/log/nginx/access.log combined;
  sendfile on;

  upstream app_server {
    # fail_timeout=0 means we always retry an upstream even if it failed
    # to return a good HTTP response

    # for UNIX domain socket setups
    server unix:/tmp/gunicorn.sock fail_timeout=0;

    # for a TCP configuration
    # server 192.168.0.7:8000 fail_timeout=0;
  }

  server {
    # if no Host match, close the connection to prevent host spoofing
    listen 80 default_server;
    return 444;
  }

  server {
    # use 'listen 80 deferred;' for Linux
    # use 'listen 80 accept_filter=httpready;' for FreeBSD
    listen 80;
    client_max_body_size 4G;

    # set the correct host(s) for your site
    server_name example.com www.example.com;

    keepalive_timeout 5;

    # path for static files
    root /path/to/app/current/public;

    location / {
      # checks for static file, if not found proxy to app
      try_files $uri @proxy_to_app;
    }

    location @proxy_to_app {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      # we don't want nginx trying to do something clever with
      # redirects, we set the Host: header above already.
      proxy_redirect off;
      proxy_pass http://app_server;
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /path/to/app/current/public;
    }
  }
}
複制代碼           

如果您希望能夠處理流請求/響應或其他功能,如 Comet、長輪詢或 Web sockets,您需要關閉代理緩沖。**執行此操作時,**您必須使用異步worker 。

要關閉緩沖,您隻需要設定:proxy_buffering off;

...
location @proxy_to_app {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_buffering off;

    proxy_pass http://app_server;
}
... 
複制代碼           

建議将協定資訊傳遞給 Gunicorn。許多 Web 架構使用此資訊來生成 URL。如果沒有此資訊,應用程式可能會錯誤地在“https”響應中生成“http”URL,進而導緻混合内容警告或應用程式損壞,設定proxy_set_header 即可:

...
proxy_set_header X-Forwarded-Proto $scheme;
...
複制代碼           

如果您在不同的主機上運作 Nginx,您需要告訴 Gunicorn 信任X-Forwarded-*。預設情況下,Gunicorn 隻會信任 localhost 的這些标頭。這是為了防止用戶端惡意僞造這些标頭:

gunicorn -w 3 --forwarded-allow-ips="10.170.3.217,10.170.3.220" test:app