TCP接入層的負載均衡、高可用、擴展性架構

今天和你們系統性聊聊TCP的負載均衡,高可用,與擴展性架構。

web-server的負載均衡,高可用,擴展性架構是怎麼實施的?
互聯網架構中,web-server接入通常使用nginx來作反向代理,實施負載均衡。整個架構分三層:
(1)上游調用層,通常是browser或者APP;
(2)中間反向代理層,nginx;
(3)下游真實接入集羣,web-server,常見web-server的有tomcat,apache;
 
那整個訪問過程是怎麼樣的?
(1)browser向daojia.com發起請求;
(2)DNS將daojia.com解析爲外網IP(1.2.3.4);
(3)browser經過外網IP(1.2.3.4)訪問nginx;
(4)nginx實施負載均衡策略,常見策略有輪詢,隨機,IP-hash等;
(5)nginx將請求轉發給內網IP(192.168.0.1)的web-server;
 
因爲http短鏈接,以及web應用無狀態的特性,理論上任何一個http請求落在任意一臺web-server都應該獲得正常處理
畫外音:若是必須落在一臺,說明架構可能不合理,難以水平擴展。
 
問題來了,tcp是有狀態的鏈接,客戶端和服務端一旦創建鏈接,一個client發起的請求必須落在同一臺tcp-server上,此時如何作負載均衡,如何保證水平擴展呢?
 
方案一:單機法tcp-server
單個tcp-server顯然是能夠保證請求一致性:
(1)client向tcp.daojia.com發起tcp請求;
(2)DNS將 tcp.daojia.com 解析爲外網IP(1.2.3.4);
(3)client經過外網IP(1.2.3.4)向tcp-server發起請求;
 
這個方案有什麼缺點?
沒法保證高可用。
 
方案二:集羣法tcp-server
能夠經過搭建tcp-server集羣來保證高可用客戶端來實現負載均衡
(1)client內配置有tcp1/tcp2/tcp3.daojia.com三個tcp-server的外網IP;
(2)客戶端經過「隨機」的方式選擇tcp-server,假設選擇到的是tcp1.daojia.com;
(3)經過DNS解析tcp1.daojia.com;
(4)經過外網IP鏈接真實的tcp-server;
 
如何保證高可用呢?
若是client發現某個tcp-server鏈接不上,則選擇另外一個。
 
這個方案有什麼缺點?
每次鏈接前,須要多實施一次DNS訪問:
(1)難以預防DNS劫持;
(2)多一次DNS訪問意味着更長的鏈接時間,這個不足在手機端更爲明顯;
 
如何解決DNS的問題?
直接將IP配置在客戶端,能夠解決上述兩個問題,不少公司也就是這麼作的, 俗稱「 IP直通車 」。
 
「IP直通車」有什麼新問題?
將IP寫死在客戶端,在客戶端實施負載均衡,擴展性不好
(1)若是原有IP發生變化,客戶端得不到實時通知;
(2)若是新增IP,即tcp-sever擴容,客戶端也得不到實時通知;
(3)若是負載均衡策略變化,須要升級客戶端;
 
方案三:服務端實施負載均衡
只有將複雜的策略下沉到服務端,才能根本上解決擴展性的問題
增長一個http接口,將客戶端的「IP配置」與「均衡策略」放到服務端是一個不錯的方案:
(1)client每次訪問tcp-server前,先調用一個新增的get-tcp-ip接口,對於client而言,這個http接口只返回一個tcp-server的IP;
(2)這個http接口,實現的是原client的IP均衡策略;
(3)拿到tcp-server的IP後,和原來同樣向tcp-server發起TCP長鏈接;
 
這樣的話,擴展性問題就解決了:
(1)若是原有IP發生變化,只須要修改get-tcp-ip接口的配置;
(2)若是新增IP,也是修改get-tcp-ip接口的配置;
(3)若是負載均衡策略變化,不須要升級客戶端;
 
然而,新的問題又產生了,若是全部IP放在客戶端,當有一個IP掛掉的時候,client能夠再換一個IP鏈接,保證可用性,而get-tcp-ip接口只是維護靜態的tcp-server集羣IP,對於這些IP對應的tcp-server是否可用,是徹底不知情的,怎麼辦呢?
 
方案四:tcp-server狀態上報
get-tcp-ip接口怎麼知道tcp-server集羣中各臺服務器是否可用呢,tcp-server主動上報是一個潛在方案,若是某一個tcp-server掛了,則會終止上報,對於中止上報狀態的tcp-server,get-tcp-ip接口,將不返回給client相應的tcp-server的外網IP。
 
該設計的存在的問題?
誠然,狀態上報解決了tcp-server高可用的問題,但這個設計犯了一個「反向依賴」的耦合小錯誤:使得tcp-server要依賴於一個與自己業務無關的web-server。
 
方案五:tcp-server狀態拉取
更優的方案是:web-server經過「拉」的方式獲取各個tcp-server的狀態,而不是tcp-server經過「推」的方式上報本身的狀態。
 
這樣的話,每一個tcp-server都獨立與解耦,只需專一於資深的tcp業務功能便可。

高可用、負載均衡、擴展性等任務由get-tcp-ip的web-server專一來執行
 
多說一句,將負載均衡實如今服務端,還有一個好處,能夠實現異構tcp-server的負載均衡,以及過載保護
(1)靜態實施:web-server下的多個tcp-server的IP能夠配置負載權重,根據tcp-server的機器配置分配負載(nginx也有相似的功能);
(2)動態實施:web-server能夠根據「拉」回來的tcp-server的狀態,動態分配負載,並在tcp-server性能急劇降低時實施過載保護;
 
總結
web-server如何實施負載均衡?
利用nginx反向代理來輪詢、隨機、ip-hash。
 
tcp-server怎麼快速保證請求一致性?
單機。
 
如何保證高可用?
客戶配置多個tcp-server的域名。
 
如何防止DNS劫持,以及加速?
IP直通車,客戶端配置多個tcp-server的IP。
 
如何保證擴展性?
服務端提供get-tcp-ip接口,向client屏屏蔽負載均衡策略,並實施便捷擴容。
 
如何保證高可用?
tcp-server「推」狀態給get-tcp-ip接口,
or
get-tcp-ip接口「拉」tcp-server狀態。

細節重要,思路比細節更重要
系統性瞭解架構,但願你們有收穫,謝轉

本文分享自微信公衆號 - 架構師之路(road5858)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。nginx

相關文章
相關標籤/搜索