天天看點

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

一、web-server的負載均衡

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

網際網路架構中,web-server接入一般使用nginx來做反向代理,實施負載均衡。整個架構分三層:

上遊調用層,一般是browser或者APP

中間反向代理層,nginx

下遊真實接入叢集,web-server,常見web-server的有tomcat,apache

整個通路過程為:

browser向daojia.com發起請求

DNS伺服器将daojia.com解析為外網IP(1.2.3.4)

browser通過外網IP(1.2.3.4)通路nginx

nginx實施負載均衡政策,常見政策有輪詢,随機,IP-hash等

nginx将請求轉發給内網IP(192.168.0.1)的web-server

由于http短連接配接,以及web應用無狀态的特性,理論上任何一個http請求落在任意一台web-server都應該得到正常處理(如果必須落在一台,說明架構不合理,不能水準擴充)。

問題來了,tcp是有狀态的連接配接,用戶端和服務端一旦建立連接配接,一個client發起的請求必須落在同一台tcp-server上,此時如何做負載均衡,如何保證水準擴充呢?

二、單機法tcp-server

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

單個tcp-server顯然是可以保證請求一緻性:

client向tcp.daojia.com發起tcp請求

DNS伺服器将tcp.daojia.com解析為外網IP(1.2.3.4)

client通過外網IP(1.2.3.4)向tcp-server發起請求

方案的缺點?

無法保證高可用。

三、叢集法tcp-server

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

通過搭建tcp-server叢集來保證高可用,用戶端來實作負載均衡:

client内配置有tcp1/tcp2/tcp3.daojia.com三個tcp-server的外網IP

用戶端通過“随機”的方式選擇tcp-server,假設選擇到的是tcp1.daojia.com

通過DNS解析tcp1.daojia.com

通過外網IP連接配接真實的tcp-server

如何保證高可用呢?

如果client發現某個tcp-server連接配接不上,則選擇另一個。

潛在的缺點?

每次連接配接前,需要多實施一次DNS通路:

難以預防DNS劫持

多一次DNS通路意味着更長的連接配接時間,這個不足在手機端更為明顯

如何解決DNS的問題?

直接将IP配置在用戶端,可以解決上述兩個問題,很多公司也就是這麼做的(俗稱“IP直通車”)。

“IP直通車”有什麼新問題?

将IP寫死在用戶端,在用戶端實施負載均衡,擴充性很差:

如果原有IP發生變化,用戶端得不到實時通知

如果新增IP,即tcp-sever擴容,用戶端也得不到實時通知

如果負載均衡政策變化,需要更新用戶端

四、服務端實施負載均衡

隻有将複雜的政策下沉到服務端,才能根本上解決擴充性的問題。

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

增加一個http接口,将用戶端的“IP配置”與“均衡政策”放到服務端是一個不錯的方案:

client每次通路tcp-server前,先調用一個新增的get-tcp-ip接口,對于client而言,這個http接口隻傳回一個tcp-server的IP

這個http接口,實作的是原client的IP均衡政策

拿到tcp-server的IP後,和原來一樣向tcp-server發起TCP長連接配接

這樣的話,擴充性問題就解決了:

如果原有IP發生變化,隻需要修改get-tcp-ip接口的配置

如果新增IP,也是修改get-tcp-ip接口的配置

然而,新的問題又産生了,如果所有IP放在用戶端,當有一個IP挂掉的時候,client可以再換一個IP連接配接,保證可用性,而get-tcp-ip接口隻是維護靜态的tcp-server叢集IP,對于這些IP對應的tcp-server是否可用,是完全不知情的,怎麼辦呢?

五、tcp-server狀态上報

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

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狀态拉取

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

更優的方案是:web-server通過“拉”的方式擷取各個tcp-server的狀态,而不是tcp-server通過“推”的方式上報自己的狀态。

這樣的話,每個tcp-server都獨立與解耦,隻需專注于資深的tcp業務功能即可。

高可用、負載均衡、擴充性等任務由get-tcp-ip的web-server專注來執行。

多說一句,将負載均衡實作在服務端,還有一個好處,可以實作異構tcp-server的負載均衡,以及過載保護:

靜态實施:web-server下的多個tcp-server的IP可以配置負載權重,根據tcp-server的機器配置配置設定負載(nginx也有類似的功能)

動态實施: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狀态。

細節重要,思路比細節更重要

繼續閱讀