Go和Python Web服務(wù)器性能對比
我通常使用Python來構(gòu)建Web 應(yīng)用。一年前,在興趣的驅(qū)使下,我開始學(xué)習(xí)Go。 在此期間,我重寫了一些原本由C 開發(fā)的CGI 應(yīng)用,包括運行于 chroot 環(huán)境下的同 thttpd 服務(wù)器一起的應(yīng)用。我開始尋找可以開發(fā)易于 chroot、且內(nèi)置 Web 服務(wù)器的獨立 Web 應(yīng)用的工具。那時,我開始玩 web.go 框架、mustache.go 模板、Go 原生 http 包和 GoMySQL 數(shù)據(jù)庫 API。我發(fā)現(xiàn),有 http、mustache.go GoMySQL 包的 Go 可以是我用來工作的不錯的工具組合。因此,我決定使用Go編寫我的應(yīng)用。(Go編程語言也可以用來編寫Web應(yīng)用?)
在工作過程中發(fā)現(xiàn),我需要比 mustache.go 更加靈活,比 GoMySQL 更加成熟、沒有那么多 Bug 的東西。最終,我使用 Kasia.go 模板和 MyMySQL (為我的應(yīng)用定制開發(fā)的包,不過我將其貢獻給了 Go 社區(qū))。重寫的應(yīng)用即便是在比以前的負載更高的運營環(huán)境下,也工作得很好。我開始思考這個問題:用 Go 實現(xiàn)獨立 Web 應(yīng)用比 Python 到底快了(或者是慢了)多少。我決定做一些各種框架和服務(wù)器不同的用途的測試。為了比較,我選擇了下面的 Go 包:
◆ 原始的 Go http包;
◆ web.go 框架(它使用運行于獨立模式[standalone mode] 的 http 包);
◆ twister 框架 (它同樣使用 http 包)。
和下面的 Python Web服務(wù)器/框架:
◆ 使用 CherryPy WSGI 服務(wù)器的 web.py 框架;
◆ 使用 flup FastCGI 做 nginx 服務(wù)器的后臺處理的 web.py 框架;
◆ tornado 異步服務(wù)器/框架;
◆ nginx 做負載均衡的 tornado。
每一個用例,我都編寫了一個小應(yīng)用,略微復(fù)雜一些的、傳統(tǒng)的 Hello World 例子。任何應(yīng)用都包括:
◆ 使用正則表達式通過 URL 路徑傳遞參數(shù);
◆ 使用語句創(chuàng)建多行輸出;
◆ 使用 printf 形式的格式化函數(shù)/表達式格式化輸出。
我想,這些都是在 Web 應(yīng)用中常見的操作,所以應(yīng)當包含在任何簡易的性能對比測試中。所有測試應(yīng)用的代碼在下面的鏈接中:
◆ Go http
◆ web.go
◆ twister
◆ web.py
測試環(huán)境
測試環(huán)境包括兩臺 使用千兆以太網(wǎng)鏈接的PC (請求發(fā)起者和應(yīng)用服務(wù)器)。
◆ 請求發(fā)起者:2 x Xeon 2.6 GHz with hyperthreading, Debian SID, kernel: 2.6.33.7.2-rt30-1-686 #1 SMP PREEMPT RT;
◆ 服務(wù)器: MSI Netbook with two core Intel U4100 1.30GHz, AC power connected, 64-bit Ubuntu 10.10, kernel: 2.6.35-25-generic #44-Ubuntu SMP, Python 2.6.6-2ubuntu2, web.py 0.34-2, flup 1.0.2-1, tornado 0.2-1, nginx 0.7.67-3ubuntu1;
為了產(chǎn)生 HTTP 請求并且評估測試應(yīng)用的性能,我使用 siege 性能測試工具。Siege 可以用多線程模擬多個用戶。我使用了下面的命令產(chǎn)生請求:
siege -c 200 -t 20s http: //SERVER_ADDR :8080 /Hello/100
或者多個類似的命令,減少參數(shù) -c 的量(在這個測試中,我同時運行了多個 Python 腳本)。它模擬了 200 用戶的請求,并持續(xù) 20 秒。這個 URL 使得 Web 應(yīng)用對每個請求都輸出 100 行。Go 應(yīng)用使用 Go 發(fā)布版 2011-02-01.1。
結(jié)果
GOMAXPROCS=1, 一個 Python 進程:
框架 | 請求速率 [1/sec] |
Go http | 1350 |
Twister | 1324 |
Web.go | 1141 |
Tornado | 882 |
Tornado+nginx | 862 |
Web.py+CheryPy | 169 |
Web.py+nginx | 114 |
GOMAXPROCS=2, 兩個 Python 并發(fā)進程:
GOMAXPROCS=4, 四個 Python 并發(fā)進程:
Web.py+nginx 工作的 flup FastCGI 選項:multiplexed=False, multithreaded=False。如果 multiplexed=True 它會運行得慢一些。如果 multithreaded=True 而只有一個進程服務(wù)于 nginx 服務(wù)器,會報下面的錯誤:
結(jié)論
你可以看到 Go 贏得了幾乎所有的測試用例。web.go 框架的那個不太理想的結(jié)果可能是由于它先嘗試用指定的 URL 尋找靜態(tài)頁面,然后才會執(zhí)行處理方法。讓我驚訝的是 tornado Python 框架如此之高的性能,尤其是跟 web.py 框架相比而言。我同樣對 CherryPy 服務(wù)器比 nginx+flup 快感到驚訝 (我使用 web.py+flup+nginx 跑幾乎所有的 Python Web 應(yīng)用)。
原文:http://www.oschina.net/question/25940_19172
【編輯推薦】