戴 偉,馬明棟,王得玉
(1.南京郵電大學 通信與信息工程學院,江蘇 南京 210003;2.南京郵電大學 地理與生物信息學院,江蘇 南京 210003)
隨著計算機和智能手機的迅速發(fā)展,中國互聯(lián)網(wǎng)群體上網(wǎng)的方式愈發(fā)多樣,體量也逐漸巨大,這自然提高了Web服務(wù)器的設(shè)計要求。傳統(tǒng)的單臺服務(wù)器,很難承受大量用戶的并發(fā)請求,如若宕機則整個服務(wù)器就會崩潰,只有將多臺服務(wù)器協(xié)同起來作為一個集群,相互配合,才能持續(xù)穩(wěn)定地為用戶服務(wù),也會避免出現(xiàn)因某一個服務(wù)器崩潰,而導致整個服務(wù)無法繼續(xù)的情形。那么對一個集群的多個服務(wù)器之間的工作進行協(xié)調(diào),使它們都在其接受范圍內(nèi)發(fā)揮其最大性能是必須面對的問題。負載均衡技術(shù)便是用來將外部的請求,均勻地分配到集群的各個服務(wù)器中,進行單獨處理再回發(fā),以此快速處理數(shù)據(jù),在支持高并發(fā)請求的同時保持高效的服務(wù)。
Nginx作為一款高性能的Web服務(wù)器,采用多進程的基于事件驅(qū)動的架構(gòu),全異步的網(wǎng)絡(luò)I/O處理機制,以及極少的進程間切換設(shè)計,使得它能夠同時支持百萬級別的TCP連接[1]。同時其自帶的upstream模塊,除了可以沒有任何阻塞地實現(xiàn)Nginx與上游服務(wù)器的交互外,還實現(xiàn)了轉(zhuǎn)發(fā)上游應用層協(xié)議的響應包體到下游客戶端的功能。這些設(shè)計都確保Nginx可以作為一個優(yōu)秀的反向代理服務(wù)器,通過負載均衡將服務(wù)均衡協(xié)調(diào)地轉(zhuǎn)發(fā)給Apache`、Tomcat等上游服務(wù)器,順利完成高并發(fā)的HTTP請求和響應。
文中在當前負載均衡技術(shù)的基礎(chǔ)上,根據(jù)Nginx作為反向代理服務(wù)器的優(yōu)越性能,分析了Nginx自身所提供的負載均衡算法的不足,通過對負載均衡算法進行優(yōu)化改進,實現(xiàn)高可靠、高性能的服務(wù)器設(shè)計,以提高用戶的網(wǎng)絡(luò)體驗。
作為一款輕量級的Web服務(wù)器,Nginx可以在處理高并發(fā)請求的同時保持高效的性能,這也是其應用廣泛的關(guān)鍵[2]。傳統(tǒng)的Apache服務(wù)器每個進程一次只能處理一個請求,當面對大量的并發(fā)連接請求時,Apache只能增加更多的進程數(shù),這將導致服務(wù)器產(chǎn)生成百上千的進程,而進程之間的切換會帶來大量的系統(tǒng)資源消耗,從而降低了服務(wù)器處理速度。Nginx采用的是一個master進程管理多個worker進程的方法。master進程不處理用戶請求,而用來管理worker進程。當某個worker進程出現(xiàn)異常關(guān)閉后,會負責建立新的進程,以保證Nginx工作的穩(wěn)定性。work進程處理請求,多個worker進程間相互獨立,避免了在處理并發(fā)請求時同步鎖的設(shè)置,減少了資源消耗,提高了服務(wù)器性能。
通常將work進程數(shù)設(shè)置為服務(wù)器CPU核心數(shù),這樣減少了進程間無畏的切換,充分發(fā)揮了SMP多核CPU架構(gòu),真正實現(xiàn)了并發(fā)處理。在工作進程中,Nginx采用IO多路復用的事件驅(qū)動型設(shè)計,全異步的網(wǎng)絡(luò)IO處理機制,能夠單機處理十萬級的TCP并發(fā)連接。Nginx的工作模式如圖1所示。
Nginx對外表現(xiàn)為服務(wù)器,當接受到客戶端的HTTP請求時,并不產(chǎn)生響應,但也不同于Squid等其他服務(wù)器直接轉(zhuǎn)發(fā),而是會將用戶發(fā)來的請求緩存一份,然后再通過負載均衡算法將完整的請求緩存從它的上游集群服務(wù)器中選擇合適的進行轉(zhuǎn)發(fā),而上游服務(wù)器處理請求生成的響應會直接轉(zhuǎn)發(fā)給Nginx,此時Nginx會邊接受邊將響應轉(zhuǎn)發(fā)給客戶,而不是完整地緩存到響應再一并轉(zhuǎn)發(fā)。工作流程如圖2所示。
圖1 Nginx工作模式
圖2 Nginx反向代理示意
這正是Nginx作為反向代理服務(wù)器的優(yōu)勢所在,通??蛻舳伺c代理服務(wù)之間的網(wǎng)絡(luò)為公網(wǎng),其網(wǎng)絡(luò)環(huán)境更加復雜,請求處理的時間會持續(xù)很久才能完成。通過緩存完整的HTTP請求包,再進行轉(zhuǎn)發(fā)以減少上游服務(wù)器的處理時間及負擔;而代理服務(wù)器與上游服務(wù)器之間有專網(wǎng)專線相通,請求傳輸更加快速。這樣的邊處理邊轉(zhuǎn)發(fā)方式減少了上游服務(wù)器并發(fā)壓力,更好地處理了高并發(fā)請求下的服務(wù)器壓力問題。同時,這種設(shè)計還保護了上游服務(wù)器的安全。客戶端與代理服務(wù)器之間通過公網(wǎng)相連,保證正常的公網(wǎng)客戶的訪問需求。因為上游服務(wù)器存在于專有網(wǎng)絡(luò)中,連接必須通過反向代理器才可向上進行訪問。對于那些試圖對服務(wù)器進行惡意攻擊的連接,代理服務(wù)器會進行屏蔽,不將其轉(zhuǎn)發(fā)到上游,保證了連接的安全。
Nginx主要通過其所提供的upstream模塊,配置負載均衡的算法,實現(xiàn)客戶端IP到后端服務(wù)器的負載均衡[3]。
目前Nginx模塊所支持的調(diào)度算法主要有5類:
(1)輪詢及加權(quán)輪詢:每個請求按時間順序逐一分配到不同的后端服務(wù)器,如果某臺服務(wù)器宕機,則故障系統(tǒng)自動剔除,用戶訪問不受影響。加權(quán)值Weight越大,則分配的訪問幾率越高。主要是在后端的每個服務(wù)器的性能都相當?shù)那闆r下。
(2)ip_hash:每個請求按訪問IP的hash結(jié)果分配,這樣來自同一個IP的訪客可以固定到同一個后端服務(wù)器,有效地解決了動態(tài)網(wǎng)頁存在的session共享問題。
(3)url_hash:此方法按訪問的url的hash結(jié)果來分配請求,使固定的url定向到同一個后端服務(wù)器,可以進一步提高后端緩存服務(wù)器的效率[4]。Nginx自身不支持url_hash,需要安裝Nginx的hash軟件包。
(4)least_conn:最少連接數(shù)法,均衡器記錄目前所有活躍連接,把下一個新的請求發(fā)給當前含有最少連接數(shù)的節(jié)點。該算法針對TCP連接進行,但由于不同應用對系統(tǒng)資源的消耗可能差異很大,而連接數(shù)無法反映出真實的應用負載,因此在使用重型Web服務(wù)器作為集群節(jié)點服務(wù)時,該算法在均衡負載的效果上要打折扣。為了減少這種不利的影響,可以對每個節(jié)點設(shè)置最大的連接數(shù)上限,通常通過閾值設(shè)定體現(xiàn)。
(5)fair:該方法可以根據(jù)頁面大小和加載時間長短智能地進行負載均衡,也就是根據(jù)后端服務(wù)器的響應時間來分配請求,響應時間短的優(yōu)先分配。
上述算法中,輪詢和加權(quán)輪詢?yōu)殪o態(tài)算法,優(yōu)點在于設(shè)計簡單,運行快,同時不會給服務(wù)器帶來額外負擔,但是該算法是理想化的,沒有考慮服務(wù)器在實際運行時會遇到的特殊情況,實際可靠性較差[5]。最小連接算法和fair算法為動態(tài)算法,與靜態(tài)算法相比有性能提升。該類動態(tài)算法雖然考慮服務(wù)器的響應快慢、連接數(shù)大小等實時運行情況,但要么考慮因素過于單一,要么對于集群中的服務(wù)器性能以同樣化對待,沒有處理異構(gòu)情況,最后的性能提升自然也不夠明顯[6]。
進行標貫試驗24次,實測錘擊數(shù)N’=15.0~21.0擊,平均為17.5擊;經(jīng)桿長修正后N=10.5~16.1擊,平均為13.1擊。取樣8組,共8件進行統(tǒng)計分析。建議其承載力特征值的經(jīng)驗值為fak=280kPa。
所以,在進行負載均衡算法設(shè)計的過程中,需要考慮幾個基本點:
(1)在保證平衡的基礎(chǔ)上,算法盡量設(shè)計的簡單。若是為了能夠均衡分配,考慮的因素過多,只會適得其反,給服務(wù)器帶來額外的計算壓力[7]。
(2)考慮到集群中的各個服務(wù)器的性能不同,可以承受的并發(fā)量也不同。必須對異構(gòu)的服務(wù)集群設(shè)定不同的分配權(quán)重。
(3)在上述的基礎(chǔ)上,將其實時負載情況考慮在內(nèi),如:服務(wù)器當前資源使用率,響應時間,實時連接數(shù)等信息作為計算權(quán)重式的因子[8]。根據(jù)服務(wù)器當前的負載情況,進行請求分配。實現(xiàn)動態(tài)的兼有預測的實時負反饋算法。
針對Nginx自帶負載均衡算法的不足,基于最少連接算法,提出帶有動態(tài)反饋的新型改進算法。其思想主要是在分派任務(wù)前,先根據(jù)各個服務(wù)器的自身性能,設(shè)置權(quán)值優(yōu)先級[9];之后在每次負載均衡時,通過對當前服務(wù)器的負載率和連接數(shù)進行分析,動態(tài)地更新分配權(quán)值,每次擇優(yōu)分配,權(quán)值越高越優(yōu)先分配,實現(xiàn)性能優(yōu)化,負載均衡[10]。
考慮在一個集群中,服務(wù)器的集合為Si={S1,S2,…,Sn}(n>1),服務(wù)器的固有性能為Ci={C1,C2,…,Cn}(n>1)。則可以給每臺服務(wù)器設(shè)置的初始權(quán)值為:
(1)
針對服務(wù)器實時負載情況,主要考慮CPU使用率Uc(i)、內(nèi)存使用率Um(i)和IO使用率Ud(i),分別對服務(wù)器性能的影響比例為Kc、Km、Kd(總值為1)[11]。則服務(wù)器的負載消耗權(quán)重Wl(i)和剩余負載率Wr(i)分別為:
Wl(i)=(Kc×Uci+Km×Umi+Kd×Udi)×T
(2)
Wr(i)=(1-Wl(i))×Wi
(3)
再將連接數(shù)因素考慮進來,計算當前連接數(shù)權(quán)值Wn(i)。計算此時集群中的各個服務(wù)器的連接數(shù)目Ni={N1,N2,…,Nn},平均連接數(shù)avgN=(N1+N2+…+Nn)/n。則每個服務(wù)器節(jié)點的連接數(shù)負載權(quán)值為Wn(i)=Ni/avgN。
綜合考慮服務(wù)器實際硬件使用情況和正在處理的連接數(shù),動態(tài)適應的調(diào)節(jié)負載權(quán)值,最終的實時負載權(quán)值為We(i),計算公式如下:
We(i)=W(i)-Wl(i)-Wn(i)=
(1-Wl(i)-Wn(i))×Wi
(4)
測試實驗中主要考慮的因素為并發(fā)連接數(shù)和響應時間[12]。通過在不同量級連接數(shù)下,分別使用least_conn最少連接數(shù)法和基于連接數(shù)法經(jīng)過優(yōu)化過的自適應算法,測試對于響應的處理時間,來衡量優(yōu)化過的算法是否具有實際效果[13]。測試工具選用Httperf和webbench,Httperf能夠根據(jù)不同的負載,記錄性能結(jié)果并輸出在終端。而webbench是一款著名的網(wǎng)站壓力檢測軟件,能測試處在相同硬件上不同服務(wù)的性能以及不同硬件上同一個服務(wù)的運行狀況[14]。通過使用webbench分別模擬300,500,700和1 000個并發(fā)連接下,兩種算法的實際事件響應時間,結(jié)果如表1所示;同時表2記錄了每次實驗時實際機器處理的數(shù)目。
表1 算法的實際事件響應時間
表2 每次實驗時實際機器處理的數(shù)目
由表1可以看出,當并發(fā)數(shù)較低時(如300),Nginx自帶的最少連接算法并不比文中優(yōu)化過的算法慢,但是隨著連接數(shù)逐漸升高到500,700甚至1 000,經(jīng)過優(yōu)化過的動態(tài)算法,由于具有自適應的調(diào)節(jié)能力,響應時間優(yōu)于最少連接法。在表2中,least_conn算法能夠承受的連接將近500,高于500時出現(xiàn)明顯的處理丟失,而自適應算法在同樣的機器配置下明顯可以承受到700左右,表明經(jīng)過優(yōu)化的算法可以更好地面對高并發(fā)連接,滿足算法設(shè)計要求。
面對高并發(fā)連接下的請求處理,負載均衡技術(shù)尤為關(guān)鍵,通過將請求均衡地分配給服務(wù)器集群從而發(fā)揮整體集群的性能。在對Nginx的結(jié)構(gòu)進行分析后,理解其作為反向代理服務(wù)器的高效高穩(wěn)定的優(yōu)越性,進而對其自帶的負載均衡算法的不足進行分析??紤]集群間負載可能出現(xiàn)不均衡的情況,設(shè)計出一種自適應的動態(tài)調(diào)節(jié)算法,對服務(wù)器的實時性能使用率進行判斷,從而優(yōu)化連接的上游分配,實現(xiàn)集群性能優(yōu)化。