Nginx與HAProxy在web應用中的比較

這幾天我對Nginx和HAProxy做了比較,得出了令人吃驚的結果。

首先,介紹一些背景情況。在很長的一段時間裏,我們在Bengler把Nginx作爲我們項目的主要web服務器,就像在Mongrel下代理Rails運行一樣。Nginx是一個非常好的小開源軟件,它佔用空間小、有合理的配置語言、功能先進而且速度快。然而,我們卻很快發現nginx中代理的負載均衡特性卻不盡如人意。

這其中最核心的問題是代理負載均衡算法。Nginx僅僅自帶輪循和源ip哈希兩種負載均衡器;而只有前者是我們感興趣的,因爲我們的對象是將負載均勻地分散到一羣Mongrel後端服務器上。輪循負載均衡(round-robin)在這種情況下是可以被接受的:如果每個請求都是在幾毫秒之內結束,那麼沒問題。

但是,如果一個頁面在加載時花費時間稍長,Nginx將會把請求發送至正在處理請求的後端服務器中--這將導致,一些後端服務器會排隊處理請求,而另一些服務器卻仍處於空閒狀態。也就是說,你得到的負載沒有被均勻分配,而這種不平均會隨着負載的增加而加劇。

所以當Gzegorz Nosek在 EngineYard的支持下聲明他公平的負載平衡器模塊時,我們自然會抨擊它。Gzegorz的模塊將請求分發至擁有最少未處理請求的後端服務器上,這種做法很大程度上提高的性能。

不幸的是,Gzegorz的補丁不完全穩定,而且成爲我們穩定性問題的主要來源。而且有時它會在後端服務器空閒的狀態下停止分發請求,並且堆積請求,或者更糟,會變的混亂還會拒絕服務請求;而對於這種情況唯一的解救方案是重啓Nginx。然而,即使實在正常情況下,該模塊也會經常會將多個請求發送到同一臺後端服務器上,儘管其他有些服務器還是空閒的,因爲我們每臺後端服務器都沒有限制可接收連接數的數量。

自從閱讀了HAProxy後,我急切的想親自嘗試下這個產品。HAProxy有一些非常吸引人的特性:

  1. 它是一個代理--而且只是一個代理。它不能提供文件,例如:代理就是它唯一做的事情。

  2. 它可以代理任何基於TCP的東西--而不僅僅是HTTP。

  3. 非常多的負載均衡算法,包括“最少連接數(least connections)”策略,將後端服務器和最少連接數關聯起來;而這,也正是我們想要的。

  4. 後端可以通過URL被只能的做有效性檢測用來避免將請求發送至有問題的後端服務器上。(它甚至可以調整檢查時機以避開峯值。)

  5. 提供專用的狀態頁來告訴你後端服務器的狀態、運行時間以及很多齊全的指標。還有一個方法是從Unix域套接字讀取指標。

  6. 請求可以通過各種各樣的東西發送:cookies、URL字符串、客戶端IP,等等。

我非常喜歡HAProxy如此專一的方法。經驗告訴我,簡單、專一,在複雜的專用應用程序是可取的,靈活的放之四海而皆準的應用程序;Varnish 和Memcached就是兩個很好的例子。

爲了確定HAProxy是否達標,我不得不做一個簡單的壓力測試。它們不一定非常科學,但是我覺得這已經夠用了。

安裝:專門的測試機器(四核AMD64 2.4GHz, 4GB內存),3個mongrel每個下面跑一個真實的基於Rails1.2的app。我使用Apache ab作爲壓力測試工具(許多人更傾向於httperf,但我們從未見過心有靈犀),而且我在各種併發情況下各跑1000個請求;被測試的頁面是通過一個小的控制器action來做一個數據庫調用、一次Memcached查找以及渲染一個空頁面;這總共話花費20ms左右。

我已經在Nginx下配置了Gzegorz的公平負載均衡補丁。這個配置除了爲Mongrel提供代理外不會做任何事情。

同是我配置HAProxy爲“最小連接數(leastconns)”算法,而且每個Mongrel的最大連接數(maxconn)爲1。這是故意配置的不公平--但我們的對象不是比較HAProxy和Nginx在每個配置相同時的情況;相反,我想觀察的是通過HAProxy的小嚐試可以獲得什麼樣的性能情況。

“maxconns”配置是非常有意義的--由於Mongrel在同一時刻只能處理一個單獨的請求,這意味着等待客戶端請求在HAProxy內部空閒--而不是在Mongrel中。隨後,當一個後端空閒下來時,下一個請求將排成線被分配到空閒的後端。當然,沒有這個限制的話,請求將被分發到繁忙中的Mongrel,而且即使有可能有其他後端處於空閒狀態也仍然會在這臺後端服務器中等待。

Nginx使用公平負載均衡補丁,行爲將相同,但是偶爾會重複請求,因爲它沒有限制每個後端可以接收的連接數量。

因此,一下這些數據、圖展示了每個請求的響應時間。

圖1:nginx--併發數3

 

圖2:HAProxy--併發數3

 

圖3:nginx--併發數10

 

圖4:HAProxy--併發數10

 

圖5:nginx--併發數30

 

圖6:HAproxy--併發數30

 

HAproxy得出以上的請求數/每秒--在併發連接數爲30時,我們得到218請求/秒,而nginx爲162請求/秒--但是,這裏最主要的不同是在響應時間上的分佈。

在併發數爲3是,nginx開處理每個請求有點慢,而HAProxy在併發數爲10時仍會控制95%的請求在最快的請求時間內被處理。與此同時,Nginx的性能雖然表現的仍然和HAProxy相當;不幸的是,這種平衡的轉折點發生在返回的一小部分連接花費時間上極其緩慢。

我不確定HAProxy是否對請求隊列做了強制排序;由於後端往往是滿的,也許一些請求會等待很長時間而沒有被分配處理。這點也解釋了圖上的標記:在一個測試會話中我有一個請求花了47秒。

我認爲這些結果顯示HAProxy對我們來說是一個更好的選擇。而且它的附加功能和細粒度的代理控制也非常受歡迎。而HAProxy缺乏對共享靜態文件支持意味着我們仍然會在HAProxy之後架設Nginx來應對路由進來的請求。

 

 

1. 本文由程序員學架構摘

2. 本文譯自Affection Code文章Comparing Nginx and HAProxy for web applications

3. 轉載請務必註明本文出自程序員學架構(微信號:archleaner )

4. 更多文章請掃碼:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章