[轉(zhuǎn)載]Python/WSGI應(yīng)用快速入門

轉(zhuǎn)載自Python/WSGI應(yīng)用快速入門

本文將介紹如何部署簡(jiǎn)單的WSGI應(yīng)用和常見的web框架。

安裝uWSGI以及Python支持

uWSGI是一個(gè)(大的)C應(yīng)用窜锯,因此需要一個(gè)C編譯器 (例如gcc或者clang)以及Python開發(fā)頭文件。

在基于Debian的發(fā)行版上,apt-get install build-essential python-dev

多種方式為Python安裝uWSGI:

1) via pip:pip install uwsgi

2) 網(wǎng)絡(luò)安裝器:curl http://uwsgi.it/install | bash -s default /tmp/uwsgi (把uWSGI二進(jìn)制安裝到/tmp/uwsgi ,可隨意修改)悲幅。

3) 下載源tarball文件捕虽,然后執(zhí)行”make”命令

wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz

tar zxvf uwsgi-latest.tar.gz

cd <dir>

make

第一個(gè)WSGI應(yīng)用

讓我們從一個(gè)簡(jiǎn)單的”Hello World”開始:

def application(env, start_response):

? ? start_response('200 OK', [('Content-Type','text/html')])

? ? return [b"Hello World"]

(將其保存為 foobar.py)。

由一個(gè)簡(jiǎn)單的Python函數(shù)組成诫肠。之所以稱之為 “application”,因?yàn)樗莡WSGI Python加載器將會(huì)搜索的默認(rèn)函數(shù)欺缘。

將其部署在HTTP端口9090栋豫,啟動(dòng)uWSGI來運(yùn)行一個(gè)HTTP服務(wù)器/路由器,它會(huì)傳遞請(qǐng)求到你的WSGI應(yīng)用:uwsgi --http :9090 --wsgi-file foobar.py

注解:當(dāng)你有一個(gè)前端web服務(wù)器谚殊,或者你正進(jìn)行某些形式的基準(zhǔn)時(shí)丧鸯,不要使用 --http ,使用 --http-socket嫩絮。

添加并發(fā)和監(jiān)控

默認(rèn)情況下丛肢,uWSGI啟動(dòng)一個(gè)單一的進(jìn)程和一個(gè)單一的線程。你想進(jìn)行的第一個(gè)調(diào)整可能是增加并發(fā)性剿干》湓酰可以用--processes選項(xiàng)添加更多的進(jìn)程,或者使用--threads選項(xiàng)添加更多的線程 (或者同時(shí)添加)置尔。

uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2

這將會(huì)生成4個(gè)進(jìn)程 (每個(gè)進(jìn)程有2個(gè)線程)杠步,一個(gè)master進(jìn)程 (在Inc死掉的時(shí)候會(huì)生成它們) 和HTTP路由器。

一個(gè)重要的任務(wù)是監(jiān)控榜轿。在生產(chǎn)部署上幽歼,了解正在發(fā)生的事情至關(guān)重要的。stats子系統(tǒng)將uWSGI的內(nèi)部統(tǒng)計(jì)數(shù)據(jù)作為JSON導(dǎo)出:

uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

對(duì)你的應(yīng)用進(jìn)行幾次請(qǐng)求谬盐,然后telnet到端口9191甸私,你會(huì)獲得大量有趣的信息。你可能想要使用”uwsgitop” (僅需 pip install 來安裝它)飞傀,這是一個(gè)類似于top的工具颠蕴,用來監(jiān)控實(shí)例泣刹。

將它放在一個(gè)完整的web服務(wù)器之后

即使uWSGI HTTP路由器是穩(wěn)定并且高性能的,但是你或許想要將你的應(yīng)用放在一個(gè)全功能的web服務(wù)器之后犀被。

uWSGI原生支持HTTP, FastCGI, SCGI及其特定的名為”uwsgi”的協(xié)議椅您。最好的協(xié)議顯然是uwsgi,nginx和Cherokee已經(jīng)支持它了 (雖然有各種Apache模塊可用)寡键。

一個(gè)常用的nginx配置如下:

location / {

? ? include uwsgi_params;

? ? uwsgi_pass 127.0.0.1:3031;

}

這表示“傳遞每一個(gè)請(qǐng)求給綁定到3031端口并使用uwsgi協(xié)議的服務(wù)器”掀泳。

現(xiàn)在我們可以生成uWSGI來本地使用uwsgi協(xié)議:

uwsgi --socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

運(yùn)行ps aux ,你會(huì)看到一個(gè)進(jìn)程已經(jīng)移除了HTTP路由器西轩,因?yàn)槲覀兊摹皐orker” (被分配給uWSGI的進(jìn)程) 本地使用uwsgi協(xié)議员舵。

如果你的代理/web服務(wù)器/路由器使用HTTP,那么你必須告訴uWSGI本地使用http協(xié)議 (這與會(huì)自己生成一個(gè)代理的–http不同):

uwsgi --http-socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

部署Django

Django大概是最常使用的Python web框架了藕畔。部署它是相當(dāng)容易的 (我們繼續(xù)配置4個(gè)進(jìn)程马僻,每個(gè)進(jìn)程有2個(gè)線程)。

假設(shè)Django工程/home/foobar/myproject

uwsgi --socket 127.0.0.1:3031 --chdir? /home/foobar/myproject/? --wsgi-file? myproject/wsgi.py --master --processes 4? ? --threads 2 --stats 127.0.0.1:9191

使用 --chdir 注服,移到指定的目錄下韭邓。在Django中,需要使用它來正確加載模塊溶弟。

處理這樣長(zhǎng)的命令行并不實(shí)際女淑,并且愚蠢而易于犯錯(cuò)。uWSGI用.ini文件支持多種配置辜御。

[uwsgi]

socket = 127.0.0.1:3031

chdir = /home/foobar/myproject/

wsgi-file = myproject/wsgi.py

processes = 4

threads = 2

stats = 127.0.0.1:9191

僅需運(yùn)行: uwsgi yourfile.ini

如果文件myproject/wsgi.py (或者任何你的工程的名字) 并不存在鸭你,那么很有可能使用的是Django的一個(gè)老(< 1.4)版本。在這種情況下擒权,需要多一點(diǎn)配置:

uwsgi --socket 127.0.0.1:3031 --chdir? /home/foobar/myproject/? --pythonpath ..? ? --env? DJANGO_SETTINGS_MODULE= myproject.settings? --module? "django.core.handlers.wsgi:WSGIHandler()" --processes 4 --threads 2 --stats 127.0.0.1:9191

或者使用.ini文件:

[uwsgi]

socket = 127.0.0.1:3031

chdir = /home/foobar/myproject/

pythonpath = ..

env = DJANGO_SETTINGS_MODULE=myproject.settings

module = django.core.handlers.wsgi:WSGIHandler()

processes = 4

threads = 2

stats = 127.0.0.1:9191

更老的(< 1.4)Django發(fā)布版本需要設(shè)置 env, module 和 pythonpath (.. 允許我們?cè)L問 myproject.settings 模塊)袱巨。

部署Flask

Flask是一個(gè)流行的Python web微框架。

將下面例子保存為 myflaskapp.py

from flask import Flask

app = Flask(__name__)

@app.route('/')

def index():

? ? return "<span style='color:red'>I am app? 1</span>"

Flask將其WSGI函數(shù) (第一個(gè)WSGI應(yīng)用中碳抄,有個(gè)函數(shù)稱為”application”)導(dǎo)出為”app”愉老,因此需要指示uWSGI使用它。仍然使用4個(gè)進(jìn)程/2個(gè)線程纳鼎,以及uwsgi socket:

uwsgi --socket 127.0.0.1:3031 --wsgi-file? myflaskapp.py --callable app --processes? 4 --threads 2 --stats 127.0.0.1:9191

(唯一添加的是 --callable 選項(xiàng))。

部署web2py

解壓縮web2py源發(fā)布版本到所選的目錄下裳凸,然后編寫一個(gè)uWSGI配置文件:

[uwsgi]

http = :9090

chdir = path_to_web2py

module = wsgihandler

master = true

processes = 8

注解:在近期的web2py發(fā)布版本中贱鄙,可能需要將wsgihandler.py腳本拷貝到handlers目錄。

使用HTTP路由器姨谷,僅需在瀏覽器中訪問端口9090逗宁,你就能看到web2py歡迎頁(yè)面。

點(diǎn)擊管理員界面梦湘,然后……哎喲瞎颗,不能用件甥,因?yàn)樾枰狧TTPS。不要擔(dān)心哼拔,uWSGI路由器是可以使用HTTPS的 (確保有OpenSSL開發(fā)頭文件:安裝它們引有,然后重新構(gòu)建uWSGI,構(gòu)建系統(tǒng)將會(huì)自動(dòng)檢測(cè)到它)倦逐。

首先譬正,生成密鑰和證書:

openssl genrsa -out foobar.key 2048

openssl req -new -key foobar.key -out foobar.csr

openssl x509 -req -days 365 -in foobar.csr -signkey foobar.key -out foobar.crt

然后修改uWSGI配置:

[uwsgi]

https = :9090,foobar.crt,foobar.key

chdir = path_to_web2py

module = wsgihandler

master = true

processes = 8

重新運(yùn)行uWSGI,并且在瀏覽器中使用 https:// 訪問9090端口檬姥。

開機(jī)自動(dòng)啟動(dòng)uWSGI

如果你想打開vi曾我,然后寫一個(gè)init.d腳本來生成uWSGI,那么請(qǐng)坐下(并且冷靜下來)健民,先確保你的系統(tǒng)沒有提供一個(gè)更好(更現(xiàn)代)的方法抒巢。

每個(gè)發(fā)行版本都選擇了一個(gè)啟動(dòng)系統(tǒng)? (Upstart, Systemd...) ,并且有大量可用的進(jìn)程管理器 (supervisord, god, monit,? circus...)秉犹。

uWSGI會(huì)跟它們都很好地集成 (我們希望是這樣的)蛉谜,但如果你計(jì)劃部署大量的應(yīng)用,那么看看uWSGI Emperor - 它或多或少是每個(gè)devops工程師的夢(mèng)想凤优。

安全性和可用性

總是 避免以root用戶運(yùn)行你的uWSGI實(shí)例悦陋。你可以使用 uid 和 gid 選項(xiàng)來去除權(quán)限:

[uwsgi]

https = :9090,foobar.crt,foobar.key

uid = foo

gid = bar

chdir = path_to_web2py

module = wsgihandler

master = true

processes = 8

如果你需要綁定到特許端口 (例如用于HTTPS的443),那么使用共享socket筑辨。它們?cè)谌コ龣?quán)限之前創(chuàng)建俺驶,并且可以通過 =N 語(yǔ)法引用注簿,其中票从,N是socket號(hào) (從0開始):

[uwsgi]

shared-socket = :443

https = =0,foobar.crt,foobar.key

uid = foo

gid = bar

chdir = path_to_web2py

module = wsgihandler

master = true

processes = 8

web應(yīng)用部署的一個(gè)常見問題是“卡住的請(qǐng)求”。你所有的線程/worker都卡住了 (請(qǐng)求阻塞) 铐望,而你的應(yīng)用無法接收更多的請(qǐng)求楚昭。要避免這個(gè)問題栖袋,你可以設(shè)置一個(gè) harakiri 定時(shí)器。它是一個(gè)監(jiān)控器 (由master進(jìn)程管理)抚太,會(huì)摧毀那些卡住超過指定秒數(shù)的進(jìn)程 (小心選擇 harakiri 值)塘幅。例如,你也許想要摧毀那些阻塞超過30秒的worker:

[uwsgi]

shared-socket = :443

https = =0,foobar.crt,foobar.key

uid = foo

gid = bar

chdir = path_to_web2py

module = wsgihandler

master = true

processes = 8

harakiri = 30

除此之外尿贫,自u(píng)WSGI 1.9起电媳,stats服務(wù)器導(dǎo)出了全部請(qǐng)求變量,你可以(實(shí)時(shí))看到你的實(shí)例正在做什么 (對(duì)于每個(gè)worker, thread 或者異步核)庆亡。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匾乓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子又谋,更是在濱河造成了極大的恐慌拼缝,老刑警劉巖娱局,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異咧七,居然都是意外死亡衰齐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門猪叙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娇斩,“玉大人,你說我怎么就攤上這事穴翩∪冢” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵芒帕,是天一觀的道長(zhǎng)歉嗓。 經(jīng)常有香客問我,道長(zhǎng)背蟆,這世上最難降的妖魔是什么鉴分? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮带膀,結(jié)果婚禮上志珍,老公的妹妹穿的比我還像新娘。我一直安慰自己垛叨,他們只是感情好伦糯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嗽元,像睡著了一般敛纲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剂癌,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天淤翔,我揣著相機(jī)與錄音,去河邊找鬼佩谷。 笑死旁壮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谐檀。 我是一名探鬼主播抡谐,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼稚补!你這毒婦竟也來了童叠?” 一聲冷哼從身側(cè)響起框喳,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤课幕,失蹤者是張志新(化名)和其女友劉穎厦坛,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乍惊,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杜秸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了润绎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撬碟。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖莉撇,靈堂內(nèi)的尸體忽然破棺而出呢蛤,到底是詐尸還是另有隱情,我是刑警寧澤棍郎,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布其障,位于F島的核電站,受9級(jí)特大地震影響涂佃,放射性物質(zhì)發(fā)生泄漏励翼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一辜荠、第九天 我趴在偏房一處隱蔽的房頂上張望汽抚。 院中可真熱鬧,春花似錦伯病、人聲如沸造烁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)膨蛮。三九已至,卻和暖如春季研,著一層夾襖步出監(jiān)牢的瞬間敞葛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工与涡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惹谐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓驼卖,卻偏偏與公主長(zhǎng)得像氨肌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子酌畜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容