上一篇文章有些同學感覺不夠詳細了解起來有些困難,我再來簡單解釋一下。
我們在開發的情況下:
浏覽器請求→ python manage.py runserver(比如8000) → 到應用代碼(Django,Flask等等)
部署到線上的情況:
域名請求→ DNS解析→ 伺服器IP→ Nginx(80端口)→ 代理轉發 127.0.0.1:8000(IP不一定是127.0.0.1)→ 到項目應用代碼邏輯。
在整個部署過程中,我們加了一層docker來進行隔離部署,不僅解決了開發(dev)測試(test)線上(prod)多個環境不一緻的問題,也達到了一次封裝,處處運作的目的,我們日常使用virtualenv進行Python包環境隔離都不需要了,這在多人開發模式下面非常友善。
我其實在docker入門篇Docker 容器化部署實踐--入門已經講過了。至于新手的話如果覺得一開始覺得不太容易上手,可以考慮去掉docker這個中間環節,直接把服務跑在Linux機器上面。
解釋完上面,接下來進入我們今天的主題:
Django + Nginx + Gunicorn 部署
Gunicorn
Gunicorn,是「Green Unicorn」,最初來于Ruby社群的Unicorn,是用于Unix的Python WSGI HTTP伺服器,Gunicorn與各種Web架構廣泛相容,簡單輕便。
我們之是以使用使用uWSGI或Gunicorn原因就是Flask,Django自帶的WSGI服務性能不夠好,一般用在測試開發環境用,線上主要使用更為高性能的WSGI服務。
作為介紹我這裡引用一個官方例子:
$ pip install gunicorn
$ cat myapp.py
def app(environ, start_response):
data = b"Hello, World!\n"
start_response("200 OK", [
("Content-Type", "text/plain"),
("Content-Length", str(len(data)))
])
return iter([data])
$ gunicorn -w 4 myapp:app
[2014-09-10 10:22:28 +0000] [30869] [INFO] Listening at: http://127.0.0.1:8000 (30869)
[2014-09-10 10:22:28 +0000] [30869] [INFO] Using worker: sync
[2014-09-10 10:22:28 +0000] [30874] [INFO] Booting worker with pid: 30874
[2014-09-10 10:22:28 +0000] [30875] [INFO] Booting worker with pid: 30875
[2014-09-10 10:22:28 +0000] [30876] [INFO] Booting worker with pid: 30876
[2014-09-10 10:22:28 +0000] [30877] [INFO] Booting worker with pid: 30877
裝好gunicorn之後,我們可以通過
gunicorn -h
進行檢視配置,通常情況下為了友善,我們都是把gunicorn放在配置檔案中。
這裡提一點,gunicorn中有一個
--statsd-host
這個使得可以用另外一種方式來跟蹤請求,我之前在監控一文說到過statsd,大家可以參看我之前寫的部落格「使用Statsd+Graphite+Grafana搭建web監控系統」,點選閱讀原文。
同uWSGI一樣我給一個簡單的supervisor例子:
# gunicorn.conf.py
import multiprocessing
import socket
bind = '0.0.0.0:9527'
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = 'gevent' # 搭配gevent運作
daemon = False
proc_name = 'yourproject'
pidfile = '/data/run/gunicorn.pid'
loglevel = 'error'
accesslog = '/data/yourproject/supervisor/gunicorn.access.log'
errorlog = '/data/yourproject/supervisor/gunicorn.error.log'
max_requests = 200000
# StatsD integration
# StatsD host is omitted here, please append `--statsd-host` to gunicorn
# statsd_host = 'localhost:8125'
statsd_prefix = socket.gethostname()
上面說下為什麼worker數目是CPU核數*2+1,這個沒有太多科學依據,主要是根據一個work進行讀寫操作,另一個work處理請求,具體可以根據自己情況進行配置。更多特殊配置,大家可以進行自行查閱文檔。
supervisor & nginx & docker-compose
supervisor同上篇文章使用Docker容器化部署實踐之Django應用部署(一)一樣,唯一變化的就是我們command從uUWSGI變為了gunicorn,這裡我就不多列出來supervisor完整配置了。
[program:gunicorn]
command=/path/to/gunicorn main:application -c /path/to/gunicorn.conf.py
directory=/path/to/project
user=nobody
autostart=true
autorestart=true
redirect_stderr=true
Nginx同上篇文章一樣,我這裡列一個簡單的樣例:
server {
listen 80;
server_name example.org;
access_log /var/log/nginx/example.log;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
docker-compose配置同之前文章一樣,内容較多,就不列出來了。可以參考上篇文章使用Docker容器化部署實踐之Django應用部署(一)的配置。
說到最後
今天我們主要闡述了Django部署使用的第二種方式,實際上這個過程和沒有docker幾乎差不多的,你可以剝離掉docker,對你整個過程沒有太大影響。