Django學習筆記之uWSGI詳解


 

WSGI是什么?

WSGI,全稱 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是為 Python 語言定義的 Web 服務器和 Web 應用程序或框架之間的一種簡單而通用的接口。自從 WSGI 被開發出來以后,許多其它語言中也出現了類似接口。

WSGI 的官方定義是,the Python Web Server Gateway Interface。從名字就可以看出來,這東西是一個Gateway,也就是網關。網關的作用就是在協議之間進行轉換。

WSGI 是作為 Web 服務器與 Web 應用程序或應用框架之間的一種低級別的接口,以提升可移植 Web 應用開發的共同點。WSGI 是基於現存的 CGI 標准而設計的。

很多框架都自帶了 WSGI server ,比如 Flask,webpy,Django、CherryPy等等。當然性能都不好,自帶的 web server 更多的是測試用途,發布時則使用生產環境的 WSGI server或者是聯合 nginx 做 uwsgi 。

也就是說,WSGI就像是一座橋梁,一邊連着web服務器,另一邊連着用戶的應用。但是呢,這個橋的功能很弱,有時候還需要別的橋來幫忙才能進行處理。WSGI 的作用如圖所示:

 

WSGI的作用

WSGI有兩方:“服務器”或“網關”一方,以及“應用程序”或“應用框架”一方。服務方調用應用方,提供環境信息,以及一個回調函數(提供給應用程序用來將消息頭傳遞給服務器方),並接收Web內容作為返回值。

所謂的 WSGI中間件同時實現了API的兩方,因此可以在WSGI服務和WSGI應用之間起調解作用:從WSGI服務器的角度來說,中間件扮演應用程序,而從應用程序的角度來說,中間件扮演服務器。“中間件”組件可以執行以下功能:

  • 重寫環境變量后,根據目標URL,將請求消息路由到不同的應用對象。
  • 允許在一個進程中同時運行多個應用程序或應用框架。
  • 負載均衡和遠程處理,通過在網絡上轉發請求和響應消息。
  • 進行內容后處理,例如應用XSLT樣式表。

  WSGI 的設計確實參考了 Java 的 servlet

 

uWSGI

uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http等協議。Nginx中HttpUwsgiModule的作用是與uWSGI服務器進行交換。

要注意 WSGI / uwsgi / uWSGI 這三個概念的區分。

  • WSGI看過前面小節的同學很清楚了,是一種通信協議。
  • uwsgi同WSGI一樣是一種通信協議。
  • 而uWSGI是實現了uwsgi和WSGI兩種協議的Web服務器。

uwsgi協議是一個uWSGI服務器自有的協議,它用於定義傳輸信息的類型(type of information),每一個uwsgi packet前4byte為傳輸信息類型描述,它與WSGI相比是兩樣東西。

為什么有了uWSGI為什么還需要nginx?因為nginx具備優秀的靜態內容處理能力,然后將動態內容轉發給uWSGI服務器,這樣可以達到很好的客戶端響應。

接下來,我們要看看 uWSGI 的安裝配置與使用。

 

安裝

uWSGI 的安裝很簡單:

pip install uwsgi

現在我們試下將 Django 跑起來。我們先在 virtualenv 創建一個 Django Project:

[root@nowamagic ~]# cd nowamagic_venv
[root@nowamagic nowamagic_venv]# source bin/activate
(nowamagic_venv)[root@nowamagic nowamagic_venv]# django-admin.py startproject nowamagic_pj

virtualenv 的路徑與目錄文件如下:

Django Project 的路徑與目錄文件如下:

 

測試uwsgi

在你的服務器上寫一個test.py:

# test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return "Hello World"

我的 test.py 的路徑是 /root/nowamagic_venv/nowamagic_pj/test.py,執行以下命令:

[root@nowamagic ~]# cd nowamagic_venv
[root@nowamagic nowamagic_venv]# source bin/activate
(nowamagic_venv)[root@nowamagic nowamagic_venv]# uwsgi --http :8001 --wsgi-file /root/nowamagic_venv/nowamagic_pj/test.py

訪問網頁 http://115.28.0.89:8001/,OK,顯示 Hello World,說明 uwsgi 安裝成功。

測試你的 Django 項目

前面我們用 django-admin.py startproject nowamagic_pj 創建了一個項目,現在我們用 Django 自帶的 Web 服務器看看我們的項目有沒出問題。還是進入我們虛擬環境:

[root@nowamagic ~]# cd nowamagic_venv
[root@nowamagic nowamagic_venv]# source bin/activate
(nowamagic_venv)[root@nowamagic nowamagic_venv]# python2.7 /root/nowamagic_venv/nowamagic_pj/manage.py runserver 0.0.0.0:8002

執行這個命令報錯:No module named django.core.management,原因應該是裝了多個版本的Python導致的。命令指定文件路徑就行,丑是丑些了

(nowamagic_venv)[root@nowamagic nowamagic_venv]# /usr/local/bin/python2.7 /root/nowamagic_venv/nowamagic_pj/manage.py runserver 0.0.0.0:8002

OK,啟動 Django 自帶的服務器了,我們再訪問 http://115.28.0.89:8002/,成功顯示:

說明 Djanggo 項目也沒問題。

 

連接Django和uwsgi

最后一步了,我們要把uwsgi與Django連接起來。

編寫django_wsgi.py文件,將其放在與文件manage.py同一個目錄下。我的放在 /root/nowamagic_venv/nowamagic_pj/ 下:

#!/usr/bin/env python
# coding: utf-8
import os
import sys
# 將系統的編碼設置為UTF8
reload(sys)
sys.setdefaultencoding('utf8')
os.environ.setdefault("DJANGO_SETTINGS_MODULE","nowamagic_pj.settings")
from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()

注意不要直接 copy,有個地方要改:注意到語句os.environ.setdefault。比如我的項目為nowamagic_pj,則語句應該是 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nowamagic_pj.settings")

OK,進入虛擬環境執行指令:

[root@nowamagic ~]# cd nowamagic_venv
[root@nowamagic nowamagic_venv]# source bin/activate
(nowamagic_venv)[root@nowamagic nowamagic_venv]# uwsgi --http :8000 --chdir /root/nowamagic_venv/nowamagic_pj/ --module django_wsgi

成功顯示 Django It Works 頁面。

這樣,你就可以在瀏覽器中訪問你的Django程序了。所有的請求都是經過uwsgi傳遞給Django程序的。

這里我們介紹了如何把uwsgi與Django連接起來,在下一篇將繼續介紹如何將uwsgi與Nginx連接。

 

上一篇介紹了 uWSGI 來部署 Django 程序,但在在生產環境中單單只有 uWSGI 是不夠的,Nginx是必不可少的工具。

先安裝 Nginx,可以參照前面的小節:使用RPM安裝Nginx。

 

Nginx 配置

在 nginx.conf 上加入/修改,我的 server 配置如下(一切從簡……):

server {
    listen       80;
    server_name  115.28.0.89;
    #server_name localhost;
    access_log /home/nowamagic/logs/access.log;
    error_log /home/nowamagic/logs/error.log;
    #root         /root/nowamagic_venv/nowamagic_pj;
    location / {
        uwsgi_pass 127.0.0.1:8077;
        #include uwsgi_params;
        include /etc/nginx/uwsgi_params;
        #uwsgi_pass 127.0.0.1:8077;
        #uwsgi_param UWSGI_SCRIPT index;
        #uwsgi_param UWSGI_PYHOME $document_root;
        #uwsgi_param UWSGI_CHDIR  $document_root;
   }
   access_log off;
}

注意保證配置里寫的目錄 /home/nowamagic/logs/ 和 /home/nowamagic/logs/ 存在,接下來就沒啥問題了,Nginx 配置很簡單。

 

uWSGI 配置

前面我們是直接使用命令行來啟動 uWSGI,在實際部署環境中,我們常用的是配置文件的方式,而非命令行的方式。

我的 Django 程序目錄:/root/nowamagic_venv/nowamagic_pj/

這里讓 Nginx 采用 8077 端口與 uWSGI 通訊,請確保此端口沒有被其它程序采用。

uWSGI 支持多種配置文件格式,比如 xml,ini,json 等等都可以。

1. xml 配置

請確定你在上一節中的django_wsgi.py文件已經存在了。新建一個XML文件:nowamagic_pj.xml,將它放在 /root/nowamagic_venv/nowamagic_pj 目錄下

<uwsgi>
 <socket>127.0.0.1:8077</socket>
 <listen>80</listen>
 <master>true</master>
 <pythonpath>/root/nowamagic_venv/nowamagic_pj</pythonpath>
 <processes>1</processes>
 <logdate>true</logdate>
 <daemonize>/var/log/uwsgi.log</daemonize>
 <plugins>python</plugins>
</uwsgi>

然后執行命令:

uwsgi -x /root/nowamagic_venv/nowamagic_pj/nowamagic_pj.xml
or
/usr/local/bin/uwsgi -x /root/nowamagic_venv/nowamagic_pj/nowamagic_pj.xml

加載指定的xml配置文件。當使用命令行參數時,可以使用簡化命令“-x”。當然也可以不簡寫:

uwsgi --xml /etc/nowamagic.xml

甚至如果在命令行的最后一個參數以“.xml”結尾,那么就隱含將加載該xml文件作為配置。

uwsgi /etc/nowamagic.xml

有時候因各種環境問題,-x --xml 命令識別不了,可以使用下面的 ini 配置方式:

2. ini 配置

[uwsgi]
vhost = false
plugins = python
socket = 127.0.0.1:8077
master = true
enable-threads = true
workers = 1
wsgi-file = /root/nowamagic_venv/nowamagic_pj/nowamagic_pj/wsgi.py
virtualenv = /root/nowamagic_venv
chdir = /root/nowamagic_venv/nowamagic_pj

然后執行命令:

uwsgi --ini /root/nowamagic_venv/nowamagic_pj.ini&

uwsgi 這樣就啟動起來了。如果無意外的話,就能在網上訪問你的 Python 項目了。

 

小插曲

我在配置完 Nginx 和 uWSGI 之后,訪問時顯示 502 錯誤。查看 uWSGI 啟動信息,發現這么一條:ImportError: No module named django.core.wsgi。

然后推斷,我的 CentOS 上的 Python 版本是 2.4.3,然后進入 virtualenv,執行:

python
<<< import django
<<< from django.core.wsgi import get_wsgi_application
<<<

則沒報錯,因為我的虛擬環境里的 Python 版本是 2.7.5。推斷成立,但是虛擬環境里的 Django 會默認調用外部環境的 Python。解決方法:在虛擬環境里 pip install django。

OK,問題解決,一切正常。

 

一些我在配置時用到的命令,省得你去搜索:

1. 關閉 uWSGI:

killall  -9 uwsgi
killall -s HUP /var/www/uwsgi 
killall -s HUP /usr/local/bin/uwsgi

2. 列出端口占用情況:

netstat -lpnt

 

參考 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM