2009年12月29日 星期二

各種Ruby on Rails部署方案 的性能比較表

前後端搭配的測試

各種前端的,我在這裡要測試的性能主要是對於動態請求的響應速度,所以本案中的某些配置既沒有考慮使用Rewrite或其他方式對靜態文件進行單獨處理 (除了Passenger和Swiftiply默認配置便實現了這個功能),也不考慮測試到前端的KeepAlive請求。主要測試以下的組合:
  • Apache + Passenger
  • Nginx + Mongrel
  • Nginx + Evented Mongrel
  • Nginx + Thin
  • Swiftiply + Swiftiplied Mongrel
  • Swiftiply + Thin
  • HAproxy + Mongrel
  • HAproxy + Thin
  • Lighttpd + Mongrel
  • Lighttpd + Thin
  • Lighttpd + FastCGI/Socket
  • Lighttpd + FastCGI/TCP
做服務器的被測試機器為ThinkPad T43,Intel Pentium M 1.86G,1.5G RAM,系統為Ubuntu 8.04。發送請求的是無線局域網中的另外一台筆記本,運行Vista。兩台機器通過TP-Link WR340G+ 801.11g 54MB的無線局域網相連。
前端和後端處於同一台機器上,所有的後端都設為10個進程,綁定於30000-30009端口,Passenger設置為最大生成10個進程,Swiftiply則是綁定於4000端口監聽。FastCGI的socket路徑為/tmp/rails[0-9].sock。


各種部署方式的性能排個名次,以下是後各種方案在並發量>=10的情況下的平均值(去掉出現0值的情況):

前端
後端
平均每秒響應數 最大鏈接限制
Lighttpd
FastCGI/TCP
215.33
64
Lighttpd
FastCGI/Socket
214.65
64
Lighttpd
Thin
196.16
64
Swiftiply
Swiftiplied Mongrel
191.33
N/A
HAproxy
Thin
188.73
10
Swiftiply
Thin(Swiftiplied)
178.96
N/A
Apache2.2/Prefork
Passenger
173.02
N/A
HAproxy
Mongrel
170.4
1
Apache2.2/Worker
Passenger
163.9
N/A
Lighttpd
Mongrel
149.85
64
Nginx
Evented Mongrel
149.78
N/A
Nginx
Thin
143.88
N/A
Nginx
Mongrel
138.86
N/A

在這個表中,Lighttpd的三種方案佔據了前三位,Lighttpd+FastCGI是性能最高的部署方式。這種方式比另一種流行方案Nginx+Mongrel的方式性能提升了高達50%!
FastCGI的好處在此體現出來:
  • 二進制協議,無需HTTP的解析
  • 與前端可以建立持久鏈接
  • 沒有鎖和上下文切換的開銷
另外Lighttpd相對於Nginx的優勢在於請求和響應的接收緩衝區很大,省去多次接收和發送的開銷。
Lighttpd+Thin的方式的性能列第三位,這點似乎出乎意料之外,但實際上是因為Lighttpd 1.5支持對HTTP後端建立HTTP KeepAlive鏈接。在第一部分對後端單獨的測試中,小並發下的Thin的KeepAlive測試性能並不比FastCGI差,同時Thin實現了非 阻塞IO,而FastCGI則是阻塞式的。相反,HAproxy和Nginx則都不支持HTTP KeepAlive。
而Swiftiply的方式也顯示出了強勁的性能,應該是得益於它的「讓後端主動連接到Swiftiply」的這種特殊的結構。
當前備受關注的Passenger的部署方式在本案中並沒有顯示出特別的性能上的優勢,不過如果將並發鏈接數放在300以內,則 Apache2.2/Prefork + Passenger的部署方式的平均每秒響應數上升為204.03,這樣看來,倘若為Apache進行一些優化配置,依然不失為一種高效的部署方案。而同 時Passenger又是最容易配置的一種方案,能達到這種效果已經非常令人滿意。
HAproxy + Mongrel並限制鏈接數為1,則是一種穩定、保守的部署方式,雖然在這裡性能不出眾,但是穩定性非常好。
最後,與Nginx相關的三種方案都排在了該榜的末尾,由於Nginx的反向代理負載均衡缺少一些高級的特性以及Rails本身的特性而導致其不適合單獨應用在Rails程序的部署上:
  • 缺少到後台服務器端的鏈接數限制的能力,這導致了Mongrel在接受大量請求時將時間消耗在上下文切換和鎖的爭用上。
  • 缺乏建立到後台服務器端的持久鏈接的能力,這導致了在鏈接的打開、建立、關閉上花費了額外的開銷。
更詳細的分析過程和資料請看浅析Ruby on Rails部署方案