nginx搭建基於python的web環境


前言:

 

在搭建開始前,我們先來梳理下web服務工作流程,先看下圖:

1、用戶(PC)向web服務器發起http請求

2、web服務器判斷用戶請求文件是否為靜態文件,是則直接讀取靜態文件並返回給用戶,不是則通過WSGI協議將請求丟給web框架(django)代碼處理

3、看web框架是否啟動django中間件,如果啟用,則依據中間件對請求進行修改,如果不啟用,則進入下一步

4、web框架中的路由程序將根據請求中的url文件名將請求路由至相應py文件

5、相應py文件收到請求后根據用戶提交的參數進行計算(期間可能會調用數據庫),然后返回計算后的結果和自定義頭部信息以及狀態碼返回

6、web框架將返回的數據打上通用標識符(頭部信息)后返回給web服務器

7、web服務器打上web服務器的通用標識符(頭部信息)后返回給用戶

8、用戶收到返回的數據

 

 

 

通過上面可以看到django框架基於WSGI協議和web服務器進行交互,那么WSGI協議又是什么呢? 咱們用代碼來說明(偽代碼。寫一個簡易的遵循WSGI協議的web服務器軟件和django程序):

 

WSGI服務器的程序:

class WSGI_WEB(object):
    def __init__(self):
        # 1. 創建套接字
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 2. 綁定
        self.tcp_server_socket.bind(("", 7890))
        # 3. 變為監聽套接字
        self.tcp_server_socket.listen(128)

    def set_response_header(self, status, headers):
        self.status = status
        self.headers = [("server", "WSGI_simple_web v1.0")]
        self.headers += headers

    def run(self):
        new_socket, client_addr = self.tcp_server_socket.accept()
        env = new_socket.recv(1024)
        body = application(env, set_response_header)    # env是web服務器接收到瀏覽器發送來的數據包;set_response_header為web服務器的一個方法地址,目的是讓django幫web服務器生成http頭部(不是以return的形式給web服務器);此外還有這里調用django里的應用還有一個最核心的任務,就是獲取返回數據的body!
        header = self.status + self.headers
        response = header + body             
        new_socket.send(response.encode("utf-8"))

 

django的app程序:

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

 

  

 

問題:

在生產環境中使用django提供的簡易web服務器性能太差,一般只用於調試。強大的nginx又不支持WSGI,那么怎么辦呢?

 

 

 

方案:

在nginx和python應用之間加一層支持WSGI協議的web服務器。以后靜態文件由nginx進行處理,動態文件丟給WSGI服務器,然后WSGI服務器再丟給web框架處理。最理想的支持WSGI協議的web服務器就是uWSGI。

 

 

下面來詳細介紹下搭建uWSGI服務器以及與nginx聯動的方法:

1、安裝uWSGI(支持WSGI的WEB服務器):

  centos下python3.6安裝uWSGI方法:

yum install -y gcc* pcre-devel openssl-devel python36-devel.x86_64

pip3.6 install uwsgi

 

2、開啟uWSGI服務

  方式一:

uwsgi --http 192.168.31.123:80 --file teacher/wsgi.py --static-map=/static=static

--http 監聽IP端口

--file 項目wsgi.py文件路徑

--static-map 靜態文件路徑

  注意:執行這條命令的時候:一定要在這個項目目錄中~ 

 

  方式二(使用配置文件):

vi uwsgi.ini:

[uwsgi]

# 監聽端口(nginx采用反向代理模式時必填)

http = 0.0.0.0:8888

# 項目目錄 chdir=/opt/test/test1/
# 啟動uwsgi的用戶名和用戶組 uid=root gid=root # 指定項目的application(我猜是這里的“test1.wsgi”拼接上面的項目目錄后,就將項目中的wsgi.py文件和uWSGI服務器關聯起來了) module=test1.wsgi:application # 指定sock的文件路徑(nginx采用本地模式時必填) socket=/opt/test/script/uwsgi.sock # 啟用主進程 master=true # 進程個數 workers=5 pidfile=/opt/test/script/uwsgi.pid # 自動移除unix Socket和pid文件當服務停止的時候 vacuum=true # 序列化接受的內容,如果可能的話 thunder-lock=true # 啟用線程 enable-threads=true # 設置自中斷時間 harakiri=30 # 設置緩沖 post-buffering=4096 # 設置日志目錄 daemonize=/opt/test/script/uwsgi.log # 設置隔多久加載一次項目代碼 py-autoreload=1 執行配置文件(注意:這里用什么賬戶執行的,以后滲透進來獲取到的就是什么賬戶。所以這一步切忌不要用root執行。):   uwsgi --ini uwsgi.ini

  彩蛋:

重啟uWSGI進程: uwsgi --reload uwsgi.pid         # 代碼做變更后uWSGI進程不會立即加載,此時可以重啟一下uWSGI進程讓它生效。。。是不是感覺有點坑,沒事,可以在配置文件中設置py-autoreload

關閉uWSGI進程: uwsgi --stop uwsgi.pid

 

 

3、配置nginx

方式一(反向代理模式):

upstream uwsgi{

    server 10.10.10.29:8888;

}

 

server {

    listen       80;

    server_name  localhost;

 

    #charset koi8-r;

    #access_log  /var/log/nginx/host.access.log  main;

 

    location / {

        proxy_pass http://uwsgi; # 通過反向代理和uWSGI服務器關聯

    }

}

 

方式二(本地模式):

server {

    listen       8080;

    server_name  localhost;

 

    #charset koi8-r;

    #access_log  /var/log/nginx/host.access.log  main;

 

    location / {

        include uwsgi_params; # 指定nginx和uWSGI服務器的通信方式

        uwsgi_connect_timeout 30;

        uwsgi_pass unix:/opt/test/script/uwsgi.sock;    # 通過sock文件和uWSGI服務器關聯! 因為nginx會去讀取.sock文件,所以需要關閉selinux才行!!!

    }

}

 

 

4、此時訪問django的admin管理后台時,靜態資源會調取失敗。這時可以將該項目所有靜態資源統一收集到一個文件夾下,然后由nginx統一去調取,真正做到動靜分離(動的給uWSGI,靜的由nginx直接調取):

在settings.py中加入:

TATIC_ROOT = os.path.join(BASE_DIR, 'static_file')

執行如下命令(搜集項目中所有靜態文件至'static_file'目錄):

python3.6 manage.py collectstatic --noinput

此時會在項目目錄下生成一個'static_file'文件夾,內含admin和所有app涉及的靜態文件

 

在nginx中配置靜態文件路徑(如果nginx和uWSGI不屬同一台服務器可以使用反向代理的方式來調取靜態文件):

location /static/ {

        alias   /opt/test/test1/static_file/;

}

 

 

 

此時就可以訪問基於python后台的web網站了


免責聲明!

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



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