關于負載均衡和服務發現,Google的經驗在這里

云天羽翊 7年前發布 | 28K 次閱讀 負載均衡 集群/負載均衡

今天主要分享三個議題,首先是Google數據中心的簡單介紹——Google數據中心約有200萬臺X86PC服務,沒有買任何大、小型機,完全使用廉價的PC服務器搭建,因規模龐大,所以對網絡要求非常高,交換機都是自行設計后定制的。服務發現、負載均衡的問題,對于Google的量級來說非常復雜,此次跟大家分享下Google內部如何實現服務發現和負載均衡。

經典的服務發現與負載均衡

靜態的服務發現方式其實很好理解,即基于IP地址和端口做服務發現,應用綁定了服務器的IP地址和端口后,當有請求時,應用就可以接收。

經典的負載均衡器也是綁定某個特定的IP地址和端口,同時負載均衡器將需要做負載均衡的應用實例預先配置好,當負載均衡器收到請求后即可分發給后臺的應用實例。

用IP+端口的方式做服務發現對人不友好,因為IP地址不好記憶,所以人們又發明了DNS作為非常經典的服務發現方式。

DNS實現的是域名解析,比較常用的方式是A記錄向:DNS查詢某個域名的A紀錄會返回該域名對應的一個或多個IP地址,圖上圖所示,給定一個域名,通過查詢DNS服務器返回來這個域名所對應的IP地址。

另外一種DNS解析方式是SRV記錄,這是DNS里實現更高級服務發現的一種方式,向DNS查詢某個域名的SRV記錄要返回該域名對應的一個或多哥地址及端口,如上圖所示,向DNS查詢一個域名地址,DNS返回了該域名對應的一系列地址和端口。

DNS除了具有服務發現功能,也可以實現負載均衡,如上圖所示,DNS可以根據用戶請求,動態的返回某域名的A紀錄,如,DNS返回的A紀錄是目前最不繁忙的實例IP地址,這樣DNS就可以實現負載均衡的功能。

靜態環境下的負載均衡是最常見的負載均衡器使用場景,如上圖所示,用戶的請求發給負載均衡器,其根據一定的策略,如輪轉策略或暗轉一定的權重把收到的請求分發給后面具體的應用實例,應用實例在處理完請求后把響應返回給負載均衡器,之后負載均衡器再把請求響應返回給最終用戶。

關于負載均衡和服務發現,Google的經驗在這里

常見的負載均衡器支持四層和七層協議,具體來說就是TCP協議和HTTP協議。

四層負載均衡器,按照TCP協議來說是實現了一種路由轉發——一個TCP請求數據包經過四層負載均衡器時,負載均衡器只修改這個TCP請求數據包的目的地址然后轉給后面的應用實例;當負載均衡器收到應用實例返回的TCP響應數據包時,會修改這個TCP響應數據包的目的地址然后返回給用戶。

七層負載均衡器和四層負載均衡器的工作原理不一樣,當七層負載均衡器收到一個用戶的HTTP請求數據包會把該請求包拆掉,然后封裝成一個新的HTTP請求數據包傳給后面的應用實例;當負載均衡器收到應用實例返回的HTTP響應數據包時,會把HTTP響應數據包拆掉然后重新封裝一個新的HTTP響應數據包返回給用戶,所以四層和七層負載均衡器的工作原理不同,四層類似于路由轉發,七層則是完全重新封裝的包。

常見的服務發現方式有三種:

第一種是用IP地址+端口或域名+端口的方式做服務發現,比如,“website.com:8080”代表一個應用,“website.com:8081”代表另一個應用,雖然這兩個應用的域名相同。這種方式適用于四層和七層協議,即TCP及HTTP協議都可以用。

第二種是子域名的方式,僅適用于七層協議,子域名的方式是指不同的應用可能有共同的根源,但是有不同的子域名,比如 http://service1.zone1.website.comhttp://service2.zone1.website.com ,這兩個不同的域名(訪問端口都是80),有共同的根域名website.com,但子域名不同,因此七層協議如HTTP協議會通過不同的子域名解析到不同的應用。

第三種是子路徑的方式,也僅適用于七層協議,如 http://zone1.website.com/service1http://zone1.website.com/service2 ,兩個路徑的域名完全一樣,但子路徑不同,可以用于區分不同的應用服務。

這三種服務發現方式其實總結下來只有IP地址或者域名+端口同時適用于四層、七層,其他如子域名、子路徑的方式只適用于七層服務發現。

動態環境

上述都是非常經典的負載均衡、服務發現的基本概念和做法,但當數據中心規模達到一定程度時應用和服務器之間更確切的說應用和具體IP地址+端口之間就不再是靜態的綁定關系。

如Google的數據中心大約有200萬臺服務器,若Google的應用和服務器之間是一一對應的靜態綁定關系:即某個應用必須要綁在某一個服務武器上,或者綁定某個服務器的IP地址+端口上,那么對Google來說,每時每刻大概會有幾百萬到上千萬個應用運行在200萬臺服務器中,靜態管理應用和服務器非常復雜,因此對于Google這樣龐大規模的數據中心來說,必須用動態管理,即要求應用不能以靜態綁定在服務器的IP地址+端口上,它可以在不同的服務器之間動態遷移來實現故障自愈,應用運行在某一個服務器上,這個服務器宕機或有問題,會被自動遷移到別的服務器上回復運行,動態的應用調度管理方式可以使應用的管理即服務器的管理進行解耦——應用和服務器之間不再是靜態的綁定關系。

動態環境下如何做負載均衡和服務發現?首先要明確問題,動態環境最根本的一點是要把服務發現實現,客戶端要找到服務的后臺,它從哪里找?這就是服務發現,在動態的環境下其實并不復雜,每個服務的后臺實例綁定的IP地址和端口注冊側到一個服務注冊中心,注冊的方式可以是被動注冊也可以是主動注冊,被動注冊是指負責應用調度的調度器來完成應用實例的IP地址+端口注冊;主動注冊是指每一個服務的實例要主動地上報自己目前所綁定的IP地址+端口。

關于負載均衡和服務發現,Google的經驗在這里

有了動態服務注冊機制后,動態環境下的負載均衡也就好實現了,在動態環境下,當負載均衡器收到一個請求后,會去服務注冊中心進行查詢響應的應用實例地址,然后把請求路由到該應用的后臺實例上。

實例:數人云Swan

Google內部的服務發現和負載均衡外面看不到,數人云借鑒Google的理念實現了Swan(Github地址: https://github.com/Dataman-Cloud/swan ),Swan基于Mesos來做容器化應用的動態調度,同時Swan實現了DNS和Proxy支持服務發現和負載均衡,跟Google的方式幾乎一模一樣,因此后面用Swan作例子給大家分享下Google怎么做服務發現和負載均衡。

首先,如何給應用命名,在動態的應用調度和運行的環境下非常重要,因為經典的應用發現偶讀是按照IP和端口,沒有對應用有統一的命名,但Google對于每個應用、實例都會有相應的命名,要明確幾個概念:

  1. 一個實例,是應用的某個Task,運行在一個容器里,應用會包含多個Task,都是運行同樣的二進制程序;
  2. 一個應用,是一組運行同樣二進制程序的實例集合,每個實例是這個應用的某個Task;
  3. 一組服務可以是一組應用程序;
  4. 一個服務會由一個用戶在某個集群上發起運行。

Swan給每個實例用五個標簽去命名,task-app-service-user-cluster ,Task是從0開始的連續整數,用于標識不同實例;相應地Swan給每個應用四個標簽來命名,app-service-user-cluster;進而,Swan給每個服務用是三個標簽來命名,service-user-cluster。

Swan實現了DNS用于服務發現,即Swan DNS把Swan調度的每一個實例所綁定的IP地址+端口的信息都記錄下來,或是A記錄或是SRV記錄。

對于每個應用,Swan的DNS也生成一個相應的域名用于四層服務發現,即app.service.user.cluster.swan.com 。另外七層的應用SwanProx會解析應用的另外一個域名 http://app.service.user.cluster.gateway.swan.com ,用于七層應用的服務發現和負載均衡。

上圖是Swan架構的示意圖,簡單解釋了Swan、DNS、Proxy之間的關系:如何通過Swan對應用動態調度后實現服務發現和負載均衡,舉例說明:首先,Swan發布一個應用app-app-service-user-cluster ,包含三個實例分別是:0-app-service-user-cluster,1-app-service-user-cluster,2-app-service-user-cluster;當Swan把三個實例都運行起來后,會將三個實例目前運行時所綁定的IP+端口信息提交給Swan DNS。

比如可以訪問Swan DNS去解析app.service.user.cluster.swan.com這個域名,會解析出來三個容器的實例;當用戶的請求訪問app.service.user.cluster.gateway.swan.com,該請求會送達到Swan Proxy上,因為Swan Proxy地址是gateway.swan.com ,Swan Proxy采用子域名的方式解析app.service.user.cluster,在解析此地址時會查Swan DNS,查此應用所對應的實例,每個實例分別在哪個IP+端口上,Swan Proxy查詢了Swan DNS后,發現它后面有三個實例,分別在不同的IP和端口上,當Swan Proxy收到對這個應用請求時回分別往后面三個實例上進行分發。

上圖詳細地解析了Swan DNS如何做服務發現,展示了Swan DNS里面的A紀錄,圖里對應的A紀錄是nginx-demo.default.xcm.beijing.swan.com應用,應用名稱為nginx-demo,屬于default服務,用戶為是:xcm,default 服務目前運行在beijing數據中心中,swan.com作為一個后綴去表示是Swan的內網域名,A紀錄展現出應用有6個實例,都在192.168.1.196的IP地址上。

上圖是Swan DNS的SRV記錄,SRV記錄和A記錄不同之處是A記錄只返回域名的IP地址,SRV記錄要返回域名的IP地址+端口。上圖所示的SRV查詢結果包含了6個不同的應用實例,分別在不同的端口上,6個不同的實例又在同一個IP地址上:192.168.1.196,但它們綁定的端口不一樣:31000、31001、301002、301003、301004、301005、31006。

Swan實現了Proxy用于負載均衡。

七層負載均衡:通過Swan Proxy支持子域名方式實現前面提到,用戶的HTTP請求發往app.service.user.cluster.gateway.swan.com這個域名地址時,先是.gateway.swan.com解析到Swan Proxy的IP地址上,然后因為Swan Proxy針對HTTP協議做解析的時候它會解析HTTP協議里面的域名,這個域名的子域名就是app.service.user.cluster,也就是這個域名里面的前綴。按照這個前綴,Swan Proxy可以區分出該HTTP請求是要訪問哪個具體的應用。Swan Proxy在做HTTP這個服務發現負載均衡的時候會支持會話保持,也會支持HTTPS。

但是Swan Proxy不支持HTTP子路徑方式,因為子路徑的方式本質上講不是一種負載均衡的方式,子路徑其實和應用所提供的不同服務相關的,所以具體的子路徑服務的注冊方式需要用額外的,比如微服務自身的服務發現支持,比如SpringCloud里面的Eurake或者阿里的Dubbo這些服務注冊中心來做子路徑方式的服務注冊。

四層負載均衡:因為四層協議,比如TCP協議,的特殊性,Swan Proxy支持的TCP協議只能是端口方式,根據一個Swan Proxy的IP或者Swan Proxy的域名,加上不同的端口來區分不同的應用。Swan Proxy在對TCP進行負載均衡的時候也會支持會話保持。

最后匯總下Swan的服務發現、負載均衡方式。結合容器目前的幾種網絡模式:Bridge方式、Host方式還有固定IP的方式,上圖給出Swan在不同容器的網絡模式下如何做服務發現、負載均衡。

王璞本次分享介紹了經典的四層、七層負載均衡以及服務發現的三種方式,又以Google數據中心入手,講述了大體量動態環境的負載均衡及服務發現方式,最后以數人云Swan為例,進行了詳細講解,小數希望大家看后有所收獲。

 

來自:http://dockone.io/article/2688

 

 本文由用戶 云天羽翊 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!