WSGI 全名 python web server gateway interface, 可以視為 python 網站框架(如:odoo, flask, django) 和網頁伺服器(如:nginx)的接口, uWSGI 實作了協議跟規範.
本篇會分享我對 wsgi 的認識過程, 以及設定和排除遇到的問題, 在我接觸odoo 之前我是一名 .net 軟體工程師, 在 web application 寫好通常都部署在 IIS (web server ) 上面, 但我接觸 python 寫網路應用程式後, 發現例如 Odoo, Flask, Django 框架後都是一行指令就可起來了
# django
% python manage.py runserver
# odoo
% python odoo-bin -c odoo.conf
當我就在想用這些 網頁框架寫的 web app 都不用 deploy 到 Web Server 就能 run 並處理動態網站 ? 後來我發現這些網站框架都會自帶web server, 例如: flask 和 odoo 網頁框架就是用 werkzeug python lib 來實作 http server ,每當執行 python odoo-bin -c odoo.conf 都可以看到
2022-08-24 14:58:34,255 60042 INFO ? odoo.service.server: HTTP service (werkzeug) running on MacBook-Air.local:8069
又在另一個機會下, 我看到一張處理異質性資料庫搜尋的網路拓墣圖, 那張圖在 application 前方寫著 CGI, 因為不了解 CGI 於是開始著手研究進而發現 uwsgi 協定, wsgi 協定跟 uWSGI server , 這時我發現, 疑?有 web server 啊, 經過幾天的 survey 與整理, 大概了解 flask , odoo 或是 django 這些網路框架自帶的 http server 通常用於開發階段, 發變偵錯, 到 production 環境還是建議使用 uWSGI 或是 Generic 之類的 Web Server
本篇介紹, 安裝 uWSGI 以及設定 , 之後再來試試看 Generic Web Server, 這邊也有看到一些文章在比較各個不同的 python web server 針對 100k 處理的反應時間跟 CPU 使用百分比, 以及等等相關比較, 之後如果我有時間也可以一起來做個實驗.
本次開發環境在
作業系統 : MacOS (Monterey)
web 框架 : Odoo
因為 flask 跟 django 很多人寫, odoo 的文章不多
Step 1.
激活你的 python 虛擬環境, 並在虛擬環境安裝 uwsgi
$ source env/bin/activate
(env) $ sudo pip install uwsgi // (失敗一直執行不起來)
在執行階段一直遇到
!!! No internal routing support, rebuild with pcre support !!!
Chdir() to /xxx/xxxx/xxx/xxx
查詢了一些文章很快找到答案, 在處理這個問題, 刪除安裝有先後順序這邊要留一下
Step 1. 先刪除已安裝的 uwsgi
% sudo pip uninstall uwsgi
Step 2. 安裝 pcre 支援庫
% brew install pcre
Step 3. 安裝 uwsgi, 不走pip 緩存 (如果有安裝 Xcode 就不用 CC=gcc)
% sudo CC=gcc pip install --no-cache-dir uwsgi
Or
% xcode-select --install
% sudo pip install --no-cache-dir uwsgi
Suggested Read :
Error while installing uWSGI on Mac
!!! No internel routing support, rebuild with pcre support !!!
P.S. 錯誤補充:之前有看到一篇文章 他是用 liunx 環境, 且採用 apt 套件管理安裝在系統上
Ex. Sudo apt install uwsgi uwsgi-plugin-python build-essential python-dev libpcre3 libpcre3-dev
在執行有遇到 unrecongized option '--uwsgi-file' , 處理方式就是在 --module, --wsgi-file, --callable 需要在前面增加 --plugin python 來讓這些未識別的選項告知 uWSGI 我正在使用 python 插件, 請使用 python 插件去解析
(env) % uwsgi --version
在安裝好後可以看看安裝的版號同時也可以看看是安裝成功
這邊測試看看 uWSGI web server 是否能正常運作
建立一個 wsgi.py 檔案
在安裝好後可以看看安裝的版號同時也可以看看是安裝成功
這邊測試看看 uWSGI web server 是否能正常運作
建立一個 wsgi.py 檔案
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]
(env) % uwsgi --http :8081 --wsgi-file wsgi.py
瀏覽器上執行 localhost:8081
除了可以利用 command line 來操作, 我們也可以把常用的指令參數打成 ini 檔案.
[uwsgi]
# -------------
# Settings:
# key = value
# Comments >> #
# -------------
# socket = [addr:port]
http = 127.0.0.1:8081
# Base application directory
# chdir = /full/path
chdir = /opt/odoo/odoo14
# WSGI module and callable
# module = [wsgi_module_name]:[application_callable_name]
module = wsgi:application
# master = [master process (true of false)]
master = true
# processes = [number of processes]
processes = 5
利用 uwsgi 執行剛剛建立好的 uwsgi.ini
(env) % uwsgi uwsgi.ini
測試完沒有問題. 可以直接進入主題
===================================================================
上面我們確保了我們的 uwsgi server 如期正常運作
接著我們也寫一份 odoo-wsgi.py (可以複製 setup 資料夾中的 odoo-wsgi.example.py 來改)
我的目錄路徑為 /opt/odoo/odoo14/odoo
在要使用的目錄下增加 odoo-wsgi.py
import odoo
#----------------------------------------------------------
# Common
#----------------------------------------------------------
odoo.multi_process = True # Nah!
# Equivalent of --load command-line option
odoo.conf.server_wide_modules = ['base', 'web']
conf = odoo.tools.config
# Path to the Open ERP Addons repository (comma-separated for
# multiple locations)
conf['addons_path'] = '/opt/odoo/odoo14/odoo/odoo/addons,/opt/odoo/odoo14/odoo/addons'
conf['proxy_mode'] = 'True'
conf['debug_mode'] = 'False'
# Optional database config if not using local socket
# conf['db_name'] = 'odoo14'
conf['db_host'] = 'localhost'
conf['db_user'] = 'odoo14'
conf['db_port'] = 5432
conf['db_password'] = 'odoo14'
application = odoo.service.wsgi_server.application
odoo.modules.initialize_sys_path()
odoo.service.server.load_server_wide_modules()
補充:
這邊我騎靜態資源一直出現 404 我不斷地追Code 和上網找答案, 以及修改參數嘗試修改這問題, 最後解法如下:
odoo-wsgi.py 倒數第二行 odoo.modules.initialize_sys_path() 這段如果是採用上面敘述兩個的官方的 addons_path 其實不用加, 這是要給放在其他地方的 addons_path 把路徑加到 __path__ 這個全域變數, 讓靜態資源可以被載入 ,這邊我產生了一個疑惑, 因為我看許多文章通常在 production 環境中, nginx + uWSGI Server 來做infra, 但是如果每個靜態資料夾我都要對應 static-map (如下圖 uwsgi.ini), 或是我需要把靜態資料夾集中打包在同一個資料夾(也許是個不錯的解決方式, 利用硬連結或是mount 等方式)做一個 static-map 對應[單純覺得可行]
總之 odoo.modules.initialize_sys_path() 和 static-map 至少要擇一使用否則會有靜態資源找不到的問題
例如 module 放在 static 圖片, 或是由odoo js framwork ajax.loadXML 路徑都會變成 404
當然除了 --wsgi-file 指令的方式啟用 uwsgi, 我們也可以用設定欓的方式啟用
在要使用的目錄下增加 uwsgi.ini
[uwsgi]
# deploy it on HTTP port 9000
http = :9000
# enable-threads = true
wsgi-file = odoo-wsgi.py
virtualenv = /opt/odoo/odoo14/env
static-gzip-all=true
static-expires-type=application/font-woff=31536000
static-expires-type=application/javascript=31536000
static-expires-type=application/vnd.ms-fontobject=31536000
static-expires-type=application/x-font-ttf=31536000
static-expires-type=application/xml=604800
#static-map = /modeul_name01/static=/opt/odoo/odoo14/odoo/other_Path/modeul_name01/static/
#static-map = /modeul_name02/static=/opt/odoo/odoo14/odoo/other_Path/modeul_name02/static/
#static-map = /modeul_name03/static=/opt/odoo/odoo14/odoo/other_Path/modeul_name03/static/
pulgin=python
master=True
vacuum=True
max-requests=5000
buffer-size=32768
chmod-socket = 660
(env) % uwsgi uwsgi.ini
瀏覽器上執行 localhost:9000
Suggested Read :
Setting up uWSGI with Nginx on MacOS for Python web-apps
最後根據官方 odoo deploy 的文章
Cron Workers
排程作業似乎只能透過 odoo-bin 去執行同時, 關閉 http 協定
看來還有一個 odoo-gevent 要來研究
其他解法 :
在 odoo-wsgi.py 中加入 ThreadedServer 可以運行 corn
Suggested Read :
那麼odoo 部署到 uWSGI Server 設定分享就到這邊 , 期待下一篇 Nginx + uWSGI Server + odoo 的部署
留言列表