Python 之 WSGI、uWSGI 和 uwsgi 介紹
一、概述
WSGI 、uWSGI 和 uwsgi 是三個相關的概念,它們是在 Web 應用程序開發中使用的不同的工具和協議。下面是它們的詳細介紹:
- WSGI(Web Server Gateway Interface):WSGI 是一個 Python Web 應用程序與 Web 服務器之間的接口規范,它定義了應用程序和服務器之間的標準接口,使得應用程序可以在不同的 Web 服務器上運行。WSGI 規范規定了應用程序必須實現的接口方法和服務器需要支持的方法。WSGI 協議使得不同的 Python Web 框架(例如 Flask、Django 等)能夠在不同的 Web 服務器上運行,這些服務器可以是 Apache、Nginx 等。
- uWSGI:uWSGI 是一個 Web 服務器,它是一個用 C 語言編寫的 Web 應用程序容器,支持運行 Python、Ruby、Perl 等多種編程語言。uWSGI 服務器可以作為一個獨立的應用服務器,也可以與其他 Web 服務器(如 Nginx、Apache)一起使用,通過 WSGI 協議與 Python 應用程序通信。
- uwsgi:uwsgi 是一個與 uWSGI 服務器相關的協議。uwsgi 協議是一種二進制協議,它定義了 uWSGI 服務器與應用程序之間的通信協議。使用 uwsgi 協議,uWSGI 服務器可以與 Python 應用程序通信,而不需要像 CGI 那樣啟動一個新的進程來處理每個請求。uwsgi 協議允許 uWSGI 服務器與應用程序之間進行雙向通信,從而提高了性能。
因此,uWSGI 是一個 Web 服務器,可以通過 WSGI 協議與 Python 應用程序通信,并使用 uwsgi 協議進行通信。WSGI 是 Python Web 應用程序與 Web 服務器之間的接口規范,定義了應用程序和服務器之間的標準接口。而 uwsgi 則是 uWSGI 服務器與應用程序之間的二進制通信協議。
二、安裝 uwsgi 模塊
uWSGI 是一種 Web 服務器網關接口(Web Server Gateway Interface),它可以用于將 Python Web 應用程序與 Web 服務器(如 Nginx 或 Apache)集成在一起。
- 在使用uWSGI模塊時,需要安裝uwsgi模塊,并在Python Web應用程序中導入uwsgi模塊,并使用uwsgi模塊提供的函數來配置和管理Web應用程序的運行。常見的uwsgi模塊函數包括uwsgi.optin()、uwsgi.route()、uwsgi.applications()等。
- 另外,uWSGI模塊還提供了一些高級特性,如Master/Worker模式、進程管理、負載均衡、自動擴展等,使得Web應用程序可以更好地適應高并發和大流量的情況。
1)配置pip源
國內源地址:
- pypi 清華大學源:https://pypi.tuna.tsinghua.edu.cn/simple
- pypi 騰訊源:http://mirrors.cloud.tencent.com/pypi/simple
- pypi 阿里源:https://mirrors.aliyun.com/pypi/simple/
2)安裝 uwsgi 模塊
三、示例演示(uWSGI + Nginx 配置)
1)安裝 nginx
2)創建 app.py 文件
創建一個名為 app.py 的文件,添加以下代碼:
3)創建 uWSGI 配置文件
創建一個 uWSGI 配置文件,例如 uwsgi.ini,其中包含以下信息:
uwsgi.ini常用配置參數詳解:
- chdir=/xxx/xxx # 指定項目目錄, 這里寫上程序根目錄(即app.py文件所在目錄)對應上述目錄結構為src
- home=/xxx/xxx # 指定虛擬環境變量
- wsgi-file=xxx # 指定加載WSGI文件
- socket=xxx # 指定uwsgi的客戶端將要連接的socket的路徑(使用UNIX socket的情況)或者地址(使用網絡地址的情況)。#socket協議,用于和nginx通訊,端口可配置成別的端口;如果有nginx在uwsgi之前作為代理的話應該配socket 如:socket=0.0.0.0:5000。當然也可以使用http-socket #而如果客戶端請求不經過(不搭建)Nginx代理服務器,服務請求直接到uwsgi服務器的話那么就配http。如:http=0.0.0.0:5000;IP和端口與項目啟動文件app.py中一致; 127.0.0.1雖然是表示本地IP,但想要在網絡上訪問必須設置host=0.0.0.0才不受IP限制。
- callable=app # 這個 app 指的是 flask 項目啟動程序中定義的 flask name 的名字,我的啟動程序是 app.py , 里面定義的 flask 的名字是 app 。
- module = mysite.wsgi # 加載一個WSGI模塊,這里加載mysite/wsgi.py這個模塊
- `master=true # 指定啟動主進程
- `processes=4 # 設置工作進程的數量
- threads=2 # 設置每個工作進程的線程數
- vacuum=true # 當服務器退出時自動刪除unix socket文件和pid文件
- logfile-chmod=644 # 指定日志文件的權限
- daemonize=%(chdir)/xxx.log # 進程在后臺運行,并將日志打印到指定文件
- pidfile=%(chdir)/xxx.pid # 在失去權限前,將主進程pid寫到指定的文件
- uid=xxx # uWSGI服務器運行時的用戶id
- gid=xxx # uWSGI服務器運行時的用戶組id
- procname-prefix-spaced=xxx # 指定工作進程名稱的前綴
- chdir=/xxx/xxx # 指定項目目錄, 這里寫上程序根目錄(即app.py文件所在目錄)對應上述目錄結構為/opt/uwsgi/
- listen = 120 # 設置socket的監聽隊列大小(默認:100)
4)啟動 uWSGI
在命令行中啟動 uWSGI:
【溫馨提示】其實也可以通過一條命令帶上對應的參數即可啟動,但是不推薦,測試可以。一般使用配置文件的方式啟動服務。
使用http協議啟動uwsgi的命令為:
- --http 指定用5800端口啟動http協議
- --ini 指定上述的啟動配置文件
- -d 指定uwsgi的log,方便我們調試
- --pidfile 將啟動的進程號寫到uwsgi.pid文件中,方便我們在需要停止服務器時kill掉。
5)配置 Web 服務器
將 Web 服務器配置為反向代理 uWSGI,例如,在 Nginx 中,可以使用以下配置文件:
其中,uwsgi_params 文件包含以下內容:
【特別注意】uwsgi_params 在nginx conf文件夾下自帶,uwsgi_pass一定要跟uwsgi_conf.ini中寫的地址完全一致。
6)重啟 Web 服務器
重啟 Web 服務器以使配置生效。
訪問(瀏覽器訪問,curl訪問也行)
7)Nginx upstream 負載均衡
Nginx上游(upstream)是指一組后端服務器,Nginx可以與其通信并將客戶端請求轉發到這些服務器。換句話說,上游服務器是N?ginx代理請求的后端服務器。
Nginx的upstream支持5種 分配方式,其中 輪詢(默認)、權重、IP散列這三種為Nginx原生支持的分配方式,fair 和 url_hash 為第三方支持的分配方式。
1、輪詢(默認)
輪詢是upstream的默認分配方式,即每個請求按照時間順序輪流分配到不同的后端服務器,如果某個后端服務器 down 掉后,能自動剔除。
2、權重(weight)
輪詢的加強版,既可以指定輪詢比率,weight 和訪問幾率成正比,主要應用于后端服務器異質的場景下。
3、IP散列(ip_hash)
每個請求按照訪問 Ip(即Nginx的前置服務器或客戶端IP)的 hash結果分配,這樣每個訪客會固定訪問一個后端服務器,可以解決 session 一致問題。
先在另外一個節點上再起一個uWSGI服務,將上面示例配置修改:
192.168.182.110 節點 app.py
192.168.182.111 節點 app.py
驗證
從上圖可知,請求輪詢調度,這才是企業一般想要的效果,負載均衡。
8)http、http-socket 和 socket 區別
- http和http-socket的區別在于,如果我們想直接將uwsgi用作服務器(例如Apache和nginx那樣)直接暴露在公網那么就使用http;
- 如果有單獨的服務器(例如Apache或者nginx),由服務器將請求轉發給uwsgi處理,并且使用http協議,那么此時使用http-socket。
- http: 自己會產生一個http進程(可以認為與nginx同一層)負責路由http請求給worker, http進程和worker之間使用的是uwsgi協議。
- http-socket: 不會產生http進程, 一般用于在前端webserver不支持uwsgi而僅支持http時使用, 他產生的worker使用的是http協議。
- 因此, http 一般是作為獨立部署的選項; http-socket 在前端webserver不支持uwsgi時使用, 如果前端webserver支持uwsgi, 則直接使用socket即可(tcp or unix)。
【1】socket 示例(uwsgi.ini):
nginx配置
【2】http 示例(uwsgi.ini):
nginx配置
【3】http-socket 示例(uwsgi.ini):
nginx配置
9)TCP 與 uinx 區別
TCP和Unix套接字(Unix domain socket)是兩種不同類型的套接字。
- TCP套接字是基于TCP/IP協議的網絡套接字,用于在網絡上進行進程間通信。TCP套接字需要指定IP地址和端口號,以便其他進程可以連接到該套接字進行通信。TCP套接字是一種跨網絡邊界的套接字,可以在不同的計算機之間進行通信。TCP套接字常用于客戶端/服務器架構中,如Web服務器、數據庫服務器等。
- Unix套接字是基于Unix域套接字(Unix domain socket)的本地套接字,用于在同一臺計算機上進行進程間通信。Unix套接字只需要指定一個文件路徑,而不需要使用IP地址和端口號。Unix套接字是一種進程間通信(IPC)機制,它提供了高效、可靠和安全的進程間通信方式。Unix套接字通常用于本地服務器和本地客戶端之間的通信,例如X Window系統中的客戶端和服務器。
因此,TCP套接字用于在網絡上進行通信,而Unix套接字用于在同一臺計算機上進行通信。雖然TCP套接字可以通過網絡連接到不同的計算機,但是Unix套接字提供了更高效的進程間通信機制,并且更適合于需要在同一臺計算機上運行的進程間通信。
【TCP 示例】常用uwsgi.ini:
【unix 示例】僅限于本機通信,很少使用。uwsgi.ini:
nginx配置
Python 中 web開發中的 WSGI、uWSGI 和 uwsgi 三者介紹就先到這里了