天天看點

循序漸進講解負載均衡vivoGateway(VGW)

作者:閃念基因

在大規模業務場景中,已經不可能通過單機提供業務,這就衍生出了負載均衡的需求。為了滿足合适可靠的負載,本文将從簡單的基礎需求出發,一步步推進并解釋如何建立負載均衡平台。

一、怎麼保證你的業務可靠

想一個問題:假設你有10台伺服器對外提供相同的服務,你如何保證這10台伺服器能穩定處理外部請求?

這裡可能有很多種解決方案,但本質上都是處理下述兩個問題:

① 用戶端的請求應該配置設定去哪一台伺服器比較好?

② 萬一其中某些伺服器故障了,如何隔離掉故障伺服器?

問題① 處理不好,可能會導緻10台伺服器中的一部分伺服器處于饑餓狀态,沒有被配置設定用戶端請求或者是配置設定得很少;而另一部分則一直在處理大量的請求,導緻不堪負重。

問題② 處理不好,則CAP原則中的可用性(A)可能就沒法保證,除非系統不需要A。

要解決上述問題,你必須實作一套控制器,能排程業務請求和管理業務伺服器。很不幸的是,大多數情況下這個控制器往往就是整個系統的瓶頸。因為控制系統如果不深入到用戶端上,就必須依賴一個集中式的決策機構,這個機構必然要承載所有用戶端的請求。這時候你又得去考慮這個控制器的備援和故障隔離的問題,這就變得無休無止。

二、業務和控制隔離

那麼,如何解決上述問題?

那就是專業的事情交給專業平台去做,即,我們需要獨立的負載均衡提供上述2點的解決方案。

對于用戶端來說,每次請求一個站點,最終都會轉變成對某個IP發起請求。是以隻要能控制用戶端通路的IP位址,我們就能控制請求應該落到哪個後端伺服器上,進而達到排程效果,這是DNS在做的事情。或者,劫持用戶端所有請求流量,對流量重新配置設定請求到後端伺服器上。這個是Nginx、LVS等的處理方式。

循序漸進講解負載均衡vivoGateway(VGW)

圖1、通過DNS實作負載均衡的效果示意圖

循序漸進講解負載均衡vivoGateway(VGW)

圖2、通過LVS/Nginx實作負載均衡的效果示意圖

這兩個方式都能達到負載均衡的效果。但這裡面有個嚴重的問題,DNS、Nginx、LVS等服務在網際網路時代不可能單機就能提供業務,都是叢集式(也就是有N台伺服器組成),那這些叢集的可靠性和穩定性又該如何保證呢?

DNS主要負責域名解析,有一定的負載均衡效果,但往往負載效果很差,不作為主要考慮手段。Nginx提供7層負載均衡,主要靠域名來做業務區分和負載。LVS是4層負載均衡,主要靠TCP/UDP協定、IP位址、TCP/UDP端口來區分服務和負載。

為了解決Nginx、LVS這些負載均衡器叢集的負載均衡及可靠性,我們可以做下述簡單的方案:

  1. 業務伺服器的負載和可靠性由Nginx保障;
  2. Nginx的負載和可靠性由LVS保障。

上述方案是遵循了業務 <-- 7層負載 <-- 4層負載的邏輯,實際上是在網絡分層模型中的應用層 <-- 傳輸層的做兩級負載。可以看出,其實這個方案是用另一層負載均衡來解決目前層級的負載和可靠性的問題。但這個方案還是有問題,業務和Nginx叢集這兩層的負載和可靠性是有保障了,但LVS叢集這一層的可靠性怎麼辦?

既然我們在網絡分層模型中應用層 <-- 傳輸層做了兩級負載,那有沒有可能做到應用層 <-- 傳輸層 <-- 網絡層的三級負載?很幸運的是,基于IP路由的方式,網絡裝置(交換機、路由器)天然具備了網絡層負載均衡功能。

到此,我們可以實作整個負載均衡鍊條:業務 <-- 7層負載(Nginx) <-- 4層負載(LVS) <-- 3層負載(NetworkDevices);

從這裡可以看出,要確定整個負載均衡體系是有效可靠的,必須從網絡層開始構築。處于高層級的業務,可以為低層級的業務提供負載。相對于低層級,高層級的業務都可以認為是低層級業務的控制面,可以交給專業團隊去實作和管理,低層級業務側隻需要關注業務本身實作即可。

循序漸進講解負載均衡vivoGateway(VGW)

圖3、網絡7層模型和LVS、Nginx之間的對應關系

網絡7層分層模型說明:

7、應用層: 支援網絡應用,應用協定僅僅是網絡應用的一個組成部分,運作在不同主機上的程序則使用應用層協定進行通信。主要的協定有:HTTP、FTP、Telnet、SMTP、POP3等。

6、表示層: 資料的表示、安全、壓縮。(實際運用中該層已經合并到了應用層)

5、會話層: 建立、管理、終止會話。(實際運用中該層已經合并到了應用層)

4、傳輸層: 負責為信源和信宿提供應用程式程序間的資料傳輸服務,這一層上主要定義了兩個傳輸協定,傳輸控制協定即TCP和使用者資料報協定UDP。

3、網絡層: 負責将資料報獨立地從信源發送到信宿,主要解決路由選擇、擁塞控制和網絡互聯等問題。

2、資料鍊路層: 負責将IP資料報封裝成合适在實體網絡上傳輸的幀格式并傳輸,或将從實體網絡接收到的幀解封,取出IP資料報交給網絡層。

1、實體層: 負責将比特流在結點間傳輸,即負責實體傳輸。該層的協定既與鍊路有關也與傳輸媒體有關。

三、如何實作4層負載均衡

上面說過,3層負載由網絡裝置天然提供,但實際使用中是和4層負載緊耦合的,一般不獨立提供服務。4層負載可以直接為業務層提供服務,而不依賴7層負載(7層負載主要面向HTTP/HTTPS等業務),是以我們這裡主要針對4層負載來講。

3.1 如何轉發流量

實作負載均衡,言外之意就是實作流量重定向,那麼,首要解決的問題是如何轉發流量。

4個問題要解決:

① 如何把用戶端的流量吸引到負載均衡器上?

② 負載均衡器如何選擇合适的後端伺服器?

③ 負載均衡器如何将請求資料發送到後端伺服器上?

④ 後端伺服器如何響應請求資料?

對于①,

解決方案很簡單,給一批後端伺服器提供一個獨立的IP位址,我們稱之為Virtual IP(也即VIP)。所有用戶端不用直接通路後端IP位址,轉而通路VIP。對于用戶端來說,相當于屏蔽了後端的情況。

對于②,

考慮到處于低層級的負載均衡通用性,一般不做複雜的負載政策,類似RR(輪詢)、WRR(帶權重輪詢)的方案更合适,可以滿足絕大多數場景要求。

對于③,

這裡的選擇會往往會影響這④的選擇。理想情況下,我們期望是用戶端的請求資料應該原封不動的發送到後端,這樣能避免資料包被修改。前面提到的網絡七層分層模型中,資料鍊路層的轉發可以做到不影響更上層的資料包内容,是以可以滿足不修改用戶端請求資料的情況下轉發。這就是網絡常說的二層轉發(資料鍊路層,處在七層網絡模型中的第二層),依靠的是網卡的MAC位址尋址來轉發資料。

那麼,假設把用戶端的請求資料包當成一份應用資料打包送到後端伺服器是不是可行?該方式相當于負載均衡器和後端建立了一個隧道,在隧道中間傳輸用戶端的請求資料,是以也可以滿足需求。

上述兩種解決方案中,依賴資料鍊路層轉發的方案稱之為直接路由方式(Direct Route),即DR模式;另一種需要隧道的方案稱之為隧道(Tunnel)模式。DR模式有一個缺點,因為依賴MAC位址轉發,後端伺服器和負載均衡器必須在同一個子網中(可以不嚴謹認為是同一個網段内),這就導緻了隻有和負載均衡伺服器在同子網的伺服器能接入,不在同一個子網的這部分就沒有使用負載均衡的機會了,這顯然不可能滿足目前大規模的業務。Tunnel模式也有缺點:既然資料轉發依賴隧道,那就必須在後端伺服器和負載均衡器之間建立隧道。如何確定不同業務人員能正确在伺服器上配置隧道,并且能監控隧道正常運作,難度都很大,需要一套完成的管理平台,言外之意即管理成本過高。

循序漸進講解負載均衡vivoGateway(VGW)

圖4、DR模式的轉發示意圖,響應流量不會經過負載均衡器

循序漸進講解負載均衡vivoGateway(VGW)

圖5、Tunnel模式轉發示意圖,和DR一樣,響應流量不會經過負載均衡器

既然都不是很理想,那還有沒有其他方案?

我們期望的是後端伺服器不感覺前端有負載均衡存在,服務可以放在任何地方,且不做任何過多配置。既然做不到原封不動傳送用戶端的資料包,那就代理用戶端的請求。也就是對用戶端發出來的資料包的源IP和目的IP分别做一次IP位址轉換。

詳細來說,負載均衡器收到用戶端A的請求後,自己以用戶端的角色向後端伺服器發起相同的請求,請求所帶的payload來自于用戶端A的請求payload,這樣保證了請求資料一緻。

此時,負載均衡器相當于發起了一個新連接配接(不同于用戶端A發起的連接配接),建立的連接配接将會使用負載均衡器的IP位址(稱之為LocalIP)作為源位址直接和後端伺服器IP通信。

當後端傳回資料給負載均衡器時,再用用戶端A的連接配接将資料傳回給用戶端A。整個過程涉及了兩個連接配接,對應兩次IP位址轉換,

  • 請求時刻:CIP→VIP, 轉換成了LocalIP→後端伺服器IP,
  • 資料傳回時刻:後端伺服器IP→ LocalIP, 轉換成了VIP→ CIP。

用戶端該過程完全基于IP位址轉發資料,而不是MAC位址,隻要網絡可達,資料就可以順暢在用戶端和後端之間傳輸。

循序漸進講解負載均衡vivoGateway(VGW)

圖6、FULLNAT轉發模式

上述方案稱之為FULLNAT轉發模式,也就是實作了兩次位址轉換。顯然,這種方式足夠簡單,不需要後端伺服器做任何調整,也不限制後端部署在何處。但也有個明顯問題,那就是後端看到的請求全部來自于負載均衡器,真實的用戶端IP資訊完全看不到了,這就相當于屏蔽了真實用戶端的情況。幸運的是資料中心中絕大多數應用并不需要明确知道真實用戶端的IP位址資訊,即便是需要真實用戶端IP資訊,負載均衡器也可以将這部分資訊加載在TCP/UDP協定資料中,通過按需安裝一定的插件擷取。

綜合上述幾種方案來說,FULLNAT模式對我們的業務場景(非虛拟化環境)适合度是最佳的。

既然我們打算使用FULLNAT模式, 則④的解決就沒有任何困難了,因為負載均衡器間接充當了用戶端角色,後端的資料必然要全部轉發給負載均衡器,由負載均衡器再發給真正的用戶端即可。

循序漸進講解負載均衡vivoGateway(VGW)

表1:各種模式之間的優劣勢分析

3.2 如何剔除異常後端伺服器

負載均衡一般提供對後端的健康檢查探測機制,以便能快速剔除異常的後端IP位址。理想情況下,基于語義的探測是最好的,能更有效的檢測到後端是不是異常。但這種方式一來會帶來大量的資源消耗,特别是後端龐大的情況下;這還不是特别嚴重的,最嚴重的是後端可能運作了HTTP、DNS、Mysql、Redis等等很多種協定,管理配置非常多樣化,太複雜。兩個問題點加起來導緻健康檢查太過于笨重,會大量占用本來用于轉發資料的資源,管理成本過高。是以一個簡單有效的方式是必要的,既然作為4層負載,我們都不去識别上遊業務是什麼,隻關注TCP或者UDP端口是不是可達即可。識别上層業務是什麼的工作交給Nginx這類型的7層負載去做。

是以隻要定期檢查所有後端的TCP/UDP端口是否開放,開放就認為後端服務是正常的,沒有開放就認為是服務異常,後端清單中剔除,後續将不再往該異常後端轉發任何資料。

那麼如何探測?既然隻是判斷TCP端口是不是正常開放,我們隻要嘗試建立一個TCP連接配接即可,如果能建立成功,則表明端口是正常開放的。但是對于UDP來說,因為UDP是無連接配接的,沒有建立連接配接的這種說法,但同樣能夠靠直接發送資料來達到探測的目的。即,直接發送一份資料,假設UDP端口是正常開放的,是以後端通常不會做響應。如果端口是沒有開放的,作業系統會傳回一個icmp port unreachable狀态,可以借此判斷端口不可達。但有個問題,如果UDP探測資料包裡帶了payload,可能會導緻後端認為是業務資料導緻收取到無關資料。

3.3 如何實作負載均衡器的故障隔離

前面我們說過,4層負載均衡依賴于網絡層衡來確定4層負載均衡器之間的負載是平衡的,那麼負載均衡器的故障隔離就是依賴于網絡層來做。

具體如何做?

實際上,我們是依賴于路由的方式來做網絡層的負載均衡,負載均衡叢集中每台伺服器都把相同的VIP位址通過路由協定BGP通告給網絡裝置(交換機或者路由器),網絡裝置收到相同的一個VIP來自不同的伺服器,就會形成一個等價路由(ECMP),言外之意就是形成負載均衡。是以如果我們想要隔離掉某台負載均衡器的話,隻要在該伺服器上把通過BGP路由協定釋出的VIP撤銷即可,這樣,上遊交換機就認為該伺服器已經被隔離,進而不再轉發資料到對應裝置上。

循序漸進講解負載均衡vivoGateway(VGW)

圖7、通過撤銷VIP路由進行故障隔離

至此,我們已經實作了一個基于FULLNAT,主要依賴三層協定端口做健康檢查,通過BGP和網絡裝置對接實作VIP收發的方式實作負通用載均衡架構模型。

四、VGW的實作方案

基于上述4層負載的架構,我們建設了VGW(vivo Gateway),主要對内網和外網業務提供4層負載均衡服務。下面我們将從邏輯架構、實體架構、備援保障、如何提高管理性轉發性能等方面進行說明。

4.1 VGW元件

VGW核心功能是複雜均衡,同時兼具健康檢查,業務引流等功能,是以組成VGW的元件主要就是核心的負載均衡轉發子產品、健康檢查子產品、路由控制子產品。

  1. 負載均衡轉發子產品:主要負責負載計算和資料轉發;
  2. 健康檢查子產品:主要負責檢測後端(RealServer)的可用狀态,并及時清除不可用後端,或者恢複可用後端;
  3. 路由控制子產品:主要進行VIP釋出引流和隔離異常VGW伺服器。

4.2 邏輯架構方案

為了友善了解,我們把用戶端到VGW環節的部分稱之為外部網絡(External),VGW到後端(RealServer)之間的環節較内部網絡(Internal)。從邏輯架構上将,VGW功能很簡單,就是把External的業務請求均勻分發到Internal的RealServer上。

循序漸進講解負載均衡vivoGateway(VGW)

圖8、VGW邏輯示意圖

4.3 實體架構方案

實體架構上,對于提供内網的VGW和外網的VGW會有一定差異。

外網VGW叢集使用了至少2張網卡,分别接外網側網絡裝置和内網側網絡裝置。對于VGW伺服器來說,兩個網口延伸出兩條鍊路,類似人的一雙手臂,是以稱這種模式為雙臂模式,一個資料包隻經過VGW伺服器的單張網卡一次。

循序漸進講解負載均衡vivoGateway(VGW)

圖9、外網VGW實體示意圖

而内網VGW和外網不同,内網VGW則隻用使用了1張網卡,直接内網側網絡裝置。相對應的,該方式稱為單臂模式,一個資料包需要需要先從僅有的一張網卡進,然後再從網卡出,最後轉發到外部,總計穿過網卡2次。

循序漸進講解負載均衡vivoGateway(VGW)

圖10、内網VGW實體示意圖

4.4 VGW現有業務模型

前面我們說過,負載均衡可以為7層負載提供更上一層的負載均衡。

  • 目前VGW最大的業務流量來自于7層接入接出平台(也就是Nginx)的流量,而Nginx基本承載了公司絕大部分核心業務。
  • 當然Nginx并不能支援所有類型的業務,直接建構于TCP、UDP之上的非HTTP類型這一部分流量7層Nginx并不支援,這類業務直接有VGW将資料轉發至業務伺服器上,中間沒有其他環節,比如kafka、Mysql等等。
  • 還有一部分業務是使用者自建了各種代理平台,類似于Nginx等等,但也由VGW為其提供4層負載均衡。
循序漸進講解負載均衡vivoGateway(VGW)

圖11、VGW業務模型圖

4.5 VGW的備援保障

為了提高可用性,那麼考慮哪些風險?大家自然而然的考慮到伺服器故障、程序故障等場景。但VGW場景需要考慮更多,因為VGW整個系統包括了鍊路、網絡裝置、伺服器、程序等。而且還不能隻考慮裝置當機這種簡單的場景,實際上,上述任何裝置出現不當機但轉發異常的情況才是最麻煩的。

是以監控VGW服務轉發是不是正常是第一步,我們通過布放在不同機房和地區的探測節點定期和VIP建立連接配接,通過建立連接配接的失敗比列來作為衡量VGW是不是正常的标準。實際上,該監控相當于檢測了整個涉及VGW的所有環節的鍊路和轉發是不是良好的。

上面的監控覆寫到的是叢集級别的探測,當然我們也建立了其他更細粒度的監控來發現具體問題點。

在有監控一手資料之後,我們就能提供伺服器級别故障處理和叢集級别的故障處理能力。

  1. 所有裝置級别的直接當機,VGW做到自動隔離;
  2. 所有鍊路級别的異常,一部分能自動隔離;
  3. 所有程序級别的異常,能達到自動隔離;
  4. 其他非完全故障的異常,人工介入隔離。

伺服器級别故障隔離是将某一些VGW伺服器通過路由調整将取消VIP的釋出,進而達到隔離目的;

叢集級别故障隔離是将整個VGW叢集的VIP取消釋出,讓流量自動被備用叢集牽引,由備用叢集接管所有業務流量。

循序漸進講解負載均衡vivoGateway(VGW)

圖12、伺服器、鍊路級别故障隔離

循序漸進講解負載均衡vivoGateway(VGW)

圖13、叢集級别的故障隔離

4.6 如何提高VGW性能

随着業務量級越來越大,VGW單機要接收近百萬的QPS請求,同時要達到500W/s以上的包處理能力。顯然一般伺服器根本無法達到這麼大量的請求和包處理速度,主要原因在于Linux的網絡處理機制。網絡資料包都必須經過Linux核心,網卡收到資料包後都要發送中斷給CPU,由CPU在核心處理,然後再拷貝一份副本給應用程式。發送資料也要經過核心進行處理一遍。頻繁的中斷、使用者空間和核心空間之間不斷的拷貝資料,導緻CPU時長嚴重被消耗在了網絡資料處理上,包速率越大,性能越差。當然還有其他諸如Cache Miss,跨CPU的資料拷貝消耗等等問題。

這裡會很容易想到,能不能把上面CPU幹的這些髒活累活扔網卡去幹了,CPU就純粹處理業務資料就行。目前很多方案就是根據這個想法來的,硬體方案有智能網卡,純軟體方案目前用的較多的是DPDK(Intel Data Plane Development Kit)。顯然智能網卡的成本會偏高,而且還在發展階段,應用有一定成本。而DPDK純軟體來說在成本和可控方面要好得多,我們選擇了DPDK作為底層的包轉發元件(實際上是基于愛奇藝開源的DPVS的二次開發)。

DPDK主要是攔截了核心的包處理流程,将使用者資料包直接上送至應用程式中,而不是由核心進行處理。同時擯棄了依靠網卡中斷的方式處理資料的行為,轉而采用輪詢的方式從網卡中讀取資料,從達到降低CPU中斷的目的。當然還利用了CPU親和性,使用固定的CPU處理網卡資料,減少程序的切換消耗。另外還有很多關于Cache、記憶體等方面的優化技術。總體上能夠将伺服器網卡包處理速度達到千萬PPS,極大提升網卡的包處理能力,進而能提升伺服器的CPS(每秒建立連接配接數目)。目前我們在100G網卡下,能夠達到 100w+的CPS和1200w+PPS的業務處理量(有限條件下的測試結果,非理論值)。

循序漸進講解負載均衡vivoGateway(VGW)

圖14、VGW使用的底層工具DPVS(DPDK+LVS)對比幾種現有的負載均衡方案性能

五、總結

通過上述講解,我們逐漸從一個業務可靠性的需求推演出一套可行的負載均衡方案,同時結合vivo的實際需求,落地了我們的VGW負載均衡接入平台。當然,目前的負載均衡方案都是大量取舍後的結果,不可能做到完美。同時我們未來還面臨着新的業務協定支援的問題,以及資料中心去中心化的業務模型對負載均衡的集中式控制之間沖突的問題。但技術一直在進步,但總會找到合适的方案的!

作者:vivo 網際網路運維團隊- Duan Chengping

來源:微信公衆号:vivo網際網路技術

出處:https://mp.weixin.qq.com/s/hPB3STR39MuoSAJkf1pYmg

繼續閱讀