負載均衡(彙總)

一分鐘瞭解負載均衡的一切

什麼是負載均衡

負載均衡(Load Balance)是分佈式系統架構設計中必須考慮的因素之一,它通常是指,將請求/數據【均勻】分攤到多個操作單元上執行,負載均衡的關鍵在於【均勻】。

 

常見的負載均衡方案


常見互聯網分佈式架構如上,分爲客戶端層、反向代理nginx層、站點層、服務層、數據層。可以看到,每一個下游都有多個上游調用,只需要做到,每一個上游都均勻訪問每一個下游,就能實現“將請求/數據【均勻】分攤到多個操作單元上執行”。

 

【客戶端層->反向代理層】的負載均衡


【客戶端層】到【反向代理層】的負載均衡,是通過“DNS輪詢”實現的:DNS-server對於一個域名配置了多個解析ip,每次DNS解析請求來訪問DNS-server,會輪詢返回這些ip,保證每個ip的解析概率是相同的。這些ip就是nginx的外網ip,以做到每臺nginx的請求分配也是均衡的。

 

【反向代理層->站點層】的負載均衡


【反向代理層】到【站點層】的負載均衡,是通過“nginx”實現的。通過修改nginx.conf,可以實現多種負載均衡策略:

1)請求輪詢:和DNS輪詢類似,請求依次路由到各個web-server

2)最少連接路由:哪個web-server的連接少,路由到哪個web-server

3)ip哈希:按照訪問用戶的ip哈希值來路由web-server,只要用戶的ip分佈是均勻的,請求理論上也是均勻的,ip哈希均衡方法可以做到,同一個用戶的請求固定落到同一臺web-server上,此策略適合有狀態服務,例如session(58沈劍備註:可以這麼做,但強烈不建議這麼做,站點層無狀態是分佈式架構設計的基本原則之一,session最好放到數據層存儲)

4)…

 

【站點層->服務層】的負載均衡


【站點層】到【服務層】的負載均衡,是通過“服務連接池”實現的。

上游連接池會建立與下游服務多個連接,每次請求會“隨機”選取連接來訪問下游服務。

【數據層】的負載均衡

在數據量很大的情況下,由於數據層(db,cache)涉及數據的水平切分,所以數據層的負載均衡更爲複雜一些,它分爲“數據的均衡”,與“請求的均衡”。

數據的均衡是指:水平切分後的每個服務(db,cache),數據量是差不多的。

請求的均衡是指:水平切分後的每個服務(db,cache),請求量是差不多的。

業內常見的水平切分方式有這麼幾種:

一、按照range水平切分


每一個數據服務,存儲一定範圍的數據,上圖爲例:

user0服務,存儲uid範圍1-1kw

user1服務,存儲uid範圍1kw-2kw

這個方案的好處是:

(1)規則簡單,service只需判斷一下uid範圍就能路由到對應的存儲服務

(2)數據均衡性較好

(3)比較容易擴展,可以隨時加一個uid[2kw,3kw]的數據服務

不足是:

(1)請求的負載不一定均衡,一般來說,新註冊的用戶會比老用戶更活躍,大range的服務請求壓力會更大

 

二、按照id哈希水平切分


每一個數據服務,存儲某個key值hash後的部分數據,上圖爲例:

user0服務,存儲偶數uid數據

user1服務,存儲奇數uid數據

這個方案的好處是:

(1)規則簡單,service只需對uid進行hash能路由到對應的存儲服務

(2)數據均衡性較好

(3)請求均勻性較好

不足是:

(1)不容易擴展,擴展一個數據服務,hash方法改變時候,可能需要進行數據遷移

 

總結

負載均衡(Load Balance)是分佈式系統架構設計中必須考慮的因素之一,它通常是指,將請求/數據【均勻】分攤到多個操作單元上執行,負載均衡的關鍵在於【均勻】。

(1)【客戶端層】到【反向代理層】的負載均衡,是通過“DNS輪詢”實現的

(2)【反向代理層】到【站點層】的負載均衡,是通過“nginx”實現的

(3)【站點層】到【服務層】的負載均衡,是通過“服務連接池”實現的

(4)【數據層】的負載均衡,要考慮“數據的均衡”與“請求的均衡”兩個點,常見的方式有“按照範圍水平切分”與“hash水平切分”

 

lvs爲何不能完全替代DNS輪詢

對於接入層負載均衡技術,部分同學持這樣的觀點:

1)nginx前端加入lvs和keepalived可以替代“DNS輪詢”

2)F5能搞定接入層高可用、擴展性、負載均衡,可以替代“DNS輪詢”

“DNS輪詢”究竟是不是過時的技術,是不是可以被其他方案替代???”

一、問題域

nginx、lvs、keepalived、f5、DNS輪詢,每每提到這些技術,往往討論的是接入層的這樣幾個問題:

1)可用性:任何一臺機器掛了,服務受不受影響

2)擴展性:能否通過增加機器,擴充系統的性能

3)反向代理+負載均衡:請求是否均勻分攤到後端的操作單元執行

 

二、上面那些名詞都是幹嘛的

由於每個技術人的背景和知識域不同,上面那些名詞縮寫(運維的同學再熟悉不過了),還是花1分鐘簡單說明一下:

1)nginx:一個高性能的web-server和實施反向代理的軟件

2)lvs:Linux Virtual Server,使用集羣技術,實現在linux操作系統層面的一個高性能、高可用、負載均衡服務器

3)keepalived:一款用來檢測服務狀態存活性的軟件,常用來做高可用

4)f5:一個高性能、高可用、負載均衡的硬件設備(聽上去和lvs功能差不多?)

5)DNS輪詢:通過在DNS-server上對一個域名設置多個ip解析,來擴充web-server性能及實施負載均衡的技術

 

三、接入層技術演進

【裸奔時代(0)單機架構】


裸奔時代的架構圖如上:

1)瀏覽器通過DNS-server,域名解析到ip

2)瀏覽器通過ip訪問web-server

缺點

1)非高可用,web-server掛了整個系統就掛了

2)擴展性差,當吞吐量達到web-server上限時,無法擴容

注:單機不涉及負載均衡的問題

 

【簡易擴容方案(1)DNS輪詢】

假設tomcat的吞吐量是1000次每秒,當系統總吞吐量達到3000時,如何擴容是首先要解決的問題,DNS輪詢是一個很容易想到的方案:


此時的架構圖如上:

1)多部署幾份web-server,1個tomcat抗1000,部署3個tomcat就能抗3000

2)在DNS-server層面,域名每次解析到不同的ip

優點

1)零成本:在DNS-server上多配幾個ip即可,功能也不收費

2)部署簡單:多部署幾個web-server即可,原系統架構不需要做任何改造

3)負載均衡:變成了多機,但負載基本是均衡的

缺點

1)非高可用:DNS-server只負責域名解析ip,這個ip對應的服務是否可用,DNS-server是不保證的,假設有一個web-server掛了,部分服務會受到影響

2)擴容非實時:DNS解析有一個生效週期

3)暴露了太多的外網ip

 

【簡易擴容方案(2)nginx】

tomcat的性能較差,但nginx作爲反向代理的性能就強多了,假設線上跑到1w,就比tomcat高了10倍,可以利用這個特性來做擴容:


此時的架構圖如上:

1)站點層與瀏覽器層之間加入了一個反向代理層,利用高性能的nginx來做反向代理

2)nginx將http請求分發給後端多個web-server

優點

1)DNS-server不需要動

2)負載均衡:通過nginx來保證

3)只暴露一個外網ip,nginx->tomcat之間使用內網訪問

4)擴容實時:nginx內部可控,隨時增加web-server隨時實時擴容

5)能夠保證站點層的可用性:任何一臺tomcat掛了,nginx可以將流量遷移到其他tomcat

缺點

1)時延增加+架構更復雜了:中間多加了一個反向代理層

2)反向代理層成了單點,非高可用:tomcat掛了不影響服務,nginx掛了怎麼辦?

 

【高可用方案(3)keepalived】

爲了解決高可用的問題,keepalived出場了:


此時:

1)做兩臺nginx組成一個集羣,分別部署上keepalived,設置成相同的虛IP,保證nginx的高可用

2)當一臺nginx掛了,keepalived能夠探測到,並將流量自動遷移到另一臺nginx上,整個過程對調用方透明


優點

1)解決了高可用的問題

缺點

1)資源利用率只有50%

2)nginx仍然是接入單點,如果接入吞吐量超過的nginx的性能上限怎麼辦,例如qps達到了50000咧?

 

【scale up擴容方案(4)lvs/f5】

nginx畢竟是軟件,性能比tomcat好,但總有個上限,超出了上限,還是扛不住。

lvs就不一樣了,它實施在操作系統層面;f5的性能又更好了,它實施在硬件層面;它們性能比nginx好很多,例如每秒可以抗10w,這樣可以利用他們來擴容,常見的架構圖如下:


此時:

1)如果通過nginx可以擴展多個tomcat一樣,可以通過lvs來擴展多個nginx

2)通過keepalived+VIP的方案可以保證可用性

99.9999%的公司到這一步基本就能解決接入層高可用、擴展性、負載均衡的問題。

 

這就完美了嘛?還有潛在問題麼?

好吧,不管是使用lvs還是f5,這些都是scale up的方案,根本上,lvs/f5還是會有性能上限,假設每秒能處理10w的請求,一天也只能處理80億的請求(10w秒吞吐量*8w秒),那萬一系統的日PV超過80億怎麼辦呢?(好吧,沒幾個公司要考慮這個問題)

 

【scale out擴容方案(5)DNS輪詢】

如之前文章所述,水平擴展,纔是解決性能問題的根本方案,能夠通過加機器擴充性能的方案才具備最好的擴展性。

facebook,google,baidu的PV是不是超過80億呢,它們的域名只對應一個ip麼,終點又是起點,還是得通過DNS輪詢來進行擴容


此時:

1)通過DNS輪詢來線性擴展入口lvs層的性能

2)通過keepalived來保證高可用

3)通過lvs來擴展多個nginx

4)通過nginx來做負載均衡,業務七層路由

 

四、結論

聊了這麼多,稍微做一個簡要的總結:

1)接入層架構要考慮的問題域爲:高可用、擴展性、反向代理+擴展均衡

2)nginx、keepalived、lvs、f5可以很好的解決高可用、擴展性、反向代理+擴展均衡的問題

3)水平擴展scale out是解決擴展性問題的根本方案,DNS輪詢是不能完全被nginx/lvs/f5所替代的

 

末了,上一篇文章有同學留言問58到家採用什麼方案,58到家目前部署在阿里雲上,前端購買了SLB服務(可以先粗暴的認爲是一個lvs+keepalived的高可用負載均衡服務),後端是nginx+tomcat。

 

五、挖坑

接入層講了這麼多,下一章,準備講講服務層“異構服務的負載均”(牛逼的機器應該分配更多的流量,如何做到?)。

 

如何實施異構服務器的負載均衡及過載保護?

“負載均衡是指,將請求/數據【均勻】分攤到多個操作單元上執行,負載均衡的關鍵在於【均勻】”。

然而,後端的service有可能部署在硬件條件不同的服務器上

1)如果對標最低配的服務器“均勻”分攤負載,高配的服務器的利用率不足;

2)如果對標最高配的服務器“均勻”分攤負載,低配的服務器可能會扛不住;

能否根據異構服務器的處理能力來動態、自適應進行負載均衡及過載保護,是本文要討論的問題。

 

一、service層的負載均衡通常是怎麼做的


service層的負載均衡,一般是通過service連接池來實現的,調用方連接池會建立與下游服務多個連接,每次請求“隨機”獲取連接,來保證service訪問的均衡性。

負載均衡、故障轉移、超時處理等細節也都是通過調用方連接池來實現的。

這個調用方連接池能否實現,根據service的處理能力,動態+自適應的進行負載調度呢?

 

二、通過“靜態權重”標識service的處理能力


調用方通過連接池組件訪問下游service,通常採用“隨機”的方式返回連接,以保證下游service訪問的均衡性。

 

要打破這個隨機性,最容易想到的方法,只要爲每個下游service設置一個“權重”,代表service的處理能力,來調整訪問到每個service的概率,例如:

假設service-ip1,service-ip2,service-ip3的處理能力相同,可以設置weight1=1,weight2=1,weight3=1,這樣三個service連接被獲取到的概率分別就是1/3,1/3,1/3,能夠保證均衡訪問。

 

假設service-ip1的處理能力是service-ip2,service-ip3的處理能力的2倍,可以設置weight1=2,weight2=1,weight3=1,這樣三個service連接被獲取到的概率分別就是2/4,1/4,1/4,能夠保證處理能力強的service分別到等比的流量,不至於資源浪費。

 

使用nginx做反向代理與負載均衡,就有類似的機制。

這個方案的優點是:簡單,能夠快速的實現異構服務器的負載均衡。

缺點也很明顯:這個權重是固定的,無法自適應動態調整,而很多時候,服務器的處理能力是很難用一個固定的數值量化。

 

三、通過“動態權重”標識service的處理能力

提問:通過什麼來標識一個service的處理能力呢?

回答:其實一個service能不能處理得過來,能不能響應得過來,應該由調用方說了算。調用服務,快速處理了,處理能力跟得上;調用服務,處理超時了,處理能力很有可能跟不上了。

 

動態權重設計

1)用一個動態權重來標識每個service的處理能力,默認初始處理能力相同,即分配給每個service的概率相等;

2)每當service成功處理一個請求,認爲service處理能力足夠,權重動態+1

3)每當service超時處理一個請求,認爲service處理能力可能要跟不上了,權重動態-10(權重下降會更快)

4)爲了方便權重的處理,可以把權重的範圍限定爲[0, 100],把權重的初始值設爲60分

舉例說明:

假設service-ip1,service-ip2,service-ip3的動態權重初始值weight1=weight2=weight3=60,剛開始時,請求分配給這3臺service的概率分別是60/180,60/180,60/180,即負載是均衡的。

隨着時間的推移,處理能力強的service成功處理的請求越來越多,處理能力弱的service偶爾有超時,隨着動態權重的增減,權重可能變化成了weight1=100,weight2=60,weight3=40,那麼此時,請求分配給這3臺service的概率分別是100/200,60/200,40/200,即處理能力強的service會被分配到更多的流量。

 

四、過載保護

提問:什麼是過載保護?

互聯網軟件架構設計中所指的過載保護,是指當系統負載超過一個service的處理能力時,如果service不進行自我保護,可能導致對外呈現處理能力爲0,且不能自動恢復的現象。而service的過載保護,是指即使系統負載超過一個service的處理能力,service讓能保證對外提供有損的穩定服務。

提問:如何進行過載保護?

回答:最簡易的方式,服務端設定一個負載閾值,超過這個閾值的請求壓過來,全部拋棄。這個方式不是特別優雅。

 

五、如何藉助“動態權重”來實施過載保護

動態權重是用來標識每個service的處理能力的一個值,它是RPC-client客戶端連接池層面的一個東東。服務端處理超時,客戶端RPC-client連接池都能夠知道,這裏只要實施一些策略,就能夠對“疑似過載”的服務器進行降壓,而不用服務器“拋棄請求”這麼粗暴的實施過載保護。

應該實施一些什麼樣的策略呢,例如:

1)如果某一個service的連接上,連續3個請求都超時,即連續-10分三次,客戶端就可以認爲,服務器慢慢的要處理不過來了,得給這個service緩一小口氣,於是設定策略:接下來的若干時間內,例如1秒(或者接下來的若干個請求),請求不再分配給這個service;

2)如果某一個service的動態權重,降爲了0(像連續10個請求超時,中間休息了3次還超時),客戶端就可以認爲,服務器完全處理不過來了,得給這個service喘一大口氣,於是設定策略:接下來的若干時間內,例如1分鐘(爲什麼是1分鐘,根據經驗,此時service一般在發生fullGC,差不多1分鐘能回過神來),請求不再分配給這個service;

3)可以有更復雜的保護策略…

這樣的話,不但能借助“動態權重”來實施動態自適應的異構服務器負載均衡,還能在客戶端層面更優雅的實施過載保護,在某個下游service快要響應不過來的時候,給其喘息的機會。

需要注意的是:要防止客戶端的過載保護引起service的雪崩,如果“整體負載”已經超過了“service集羣”的處理能力,怎麼轉移請求也是處理不過來的,還得通過拋棄請求來實施自我保護。

六、總結

1)service的負載均衡、故障轉移、超時處理通常是RPC-client連接池層面來實施的

2)異構服務器負載均衡,最簡單的方式是靜態權重法,缺點是無法自適應動態調整

3)動態權重法,可以動態的根據service的處理能力來分配負載,需要有連接池層面的微小改動

4)過載保護,是在負載過高時,service爲了保護自己,保證一定處理能力的一種自救方法

5)動態權重法,還可以用做service的過載保護

 

單點系統架構的可用性與性能優化

一、需求緣起

明明架構要求高可用,爲何系統中還會存在單點?

回答:單點master的設計,會大大簡化系統設計,何況有時候避免不了單點

 

在哪些場景中會存在單點?先來看一下一個典型互聯網高可用架構。


典型互聯網高可用架構:

(1)客戶端層,這一層是瀏覽器或者APP,第一步先訪問DNS-server,由域名拿到nginx的外網IP

(2)負載均衡層,nginx是整個服務端的入口,負責反向代理與負載均衡工作

(3)站點層,web-server層,典型的是tomcat或者apache

(4)服務層,service層,典型的是dubbo或者thrift等提供RPC調用的後端服務

(5)數據層,包含cache和db,典型的是主從複製讀寫分離的db架構

在這個互聯網架構中,站點層、服務層、數據庫的從庫都可以通過冗餘的方式來保證高可用,但至少

(1)nginx層是一個潛在的單點

(2)數據庫寫庫master也是一個潛在的單點

 

再舉一個GFS(Google File System)架構的例子。


GFS的系統架構裏主要有這麼幾種角色:

(1)client,就是發起文件讀寫的調用端

(2)master,這是一個單點服務,它有全局事業,掌握文件元信息

(3)chunk-server,實際存儲文件額服務器

這個系統裏,master也是一個單點的服務,Map-reduce系統裏也有類似的全局協調的master單點角色。

 

系統架構設計中,像nginx,db-master,gfs-master這樣的單點服務,會存在什麼問題,有什麼方案來優化呢,這是本文要討論的問題。

 

二、單點架構存在的問題

單點系統一般來說存在兩個很大的問題:

(1)非高可用:既然是單點,master一旦發生故障,服務就會受到影響

(2)性能瓶頸:既然是單點,不具備良好的擴展性,服務性能總有一個上限,這個單點的性能上限往往就是整個系統的性能上限

接下來,就看看有什麼優化手段可以優化上面提到的兩個問題

三、shadow-master解決單點高可用問題

shadow-master是一種很常見的解決單點高可用問題的技術方案。

“影子master”,顧名思義,服務正常時,它只是單點master的一個影子,在master出現故障時,shadow-master會自動變成master,繼續提供服務。

shadow-master它能夠解決高可用的問題,並且故障的轉移是自動的,不需要人工介入,但不足是它使服務資源的利用率降爲了50%,業內經常使用keepalived+vip的方式實現這類單點的高可用

 


以GFS的master爲例,master正常時:

(1)client會連接正常的master,shadow-master不對外提供服務

(2)master與shadow-master之間有一種存活探測機制

(3)master與shadow-master有相同的虛IP(virtual-IP)

 


當發現master異常時:

shadow-master會自動頂上成爲master,虛IP機制可以保證這個過程對調用方是透明的

 

除了GFS與MapReduce系統中的主控master,nginx亦可用類似的方式保證高可用,數據庫的主庫master(主庫)亦可用類似的方式來保證高可用,只是細節上有些地方要注意:


傳統的一主多從,讀寫分離的db架構,只能保證讀庫的高可用,是無法保證寫庫的高可用的,要想保證寫庫的高可用,也可以使用上述的shadow-master機制:


(1)兩個主庫設置相互同步的雙主模式

(2)平時只有一個主庫提供服務,言下之意,shadow-master不會往master同步數據

(3)異常時,虛IP漂移到另一個主庫,shadow-master變成主庫繼續提供服務

需要說明的是,由於數據庫的特殊性,數據同步需要時延,如果數據還沒有同步完成,流量就切到了shadow-master,可能引起小部分數據的不一致。

 

四、減少與單點的交互,是存在單點的系統優化的核心方向

既然知道單點存在性能上限,單點的性能(例如GFS中的master)有可能成爲系統的瓶頸,那麼,減少與單點的交互,便成了存在單點的系統優化的核心方向。

怎麼來減少與單點的交互,這裏提兩種常見的方法。

批量寫

批量寫是一種常見的提升單點性能的方式。

例如一個利用數據庫寫單點生成做“ID生成器”的例子:


(1)業務方需要ID

(2)利用數據庫寫單點的auto increament id來生成和返回ID

這是一個很常見的例子,很多公司也就是這麼生成ID的,它利用了數據庫寫單點的特性,方便快捷,無額外開發成本,是一個非常帥氣的方案。

潛在的問題是:生成ID的併發上限,取決於單點數據庫的寫性能上限。

如何提升性能呢?批量寫

 


(1)中間加一個服務,每次從數據庫拿出100個id

(2)業務方需要ID

(3)服務直接返回100個id中的1個,100個分配完,再訪問數據庫

這樣一來,每分配100個纔會寫數據庫一次,分配id的性能可以認爲提升了100倍。

 

客戶端緩存

客戶端緩存也是一種降低與單點交互次數,提升系統整體性能的方法。

還是以GFS文件系統爲例:


(1)GFS的調用客戶端client要訪問shenjian.txt,先查詢本地緩存,miss了

(2)client訪問master問說文件在哪裏,master告訴client在chunk3上

(3)client把shenjian.txt存放在chunk3上記錄到本地的緩存,然後進行文件的讀寫操作

(4)未來client要訪問文件,從本地緩存中查找到對應的記錄,就不用再請求master了,可以直接訪問chunk-server。如果文件發生了轉移,chunk3返回client說“文件不在我這兒了”,client再訪問master,詢問文件所在的服務器。

 

根據經驗,這類緩存的命中非常非常高,可能在99.9%以上(因爲文件的自動遷移是小概率事件),這樣與master的交互次數就降低了1000倍。

 

五、水平擴展是提升單點系統性能的好方案

無論怎麼批量寫,客戶端緩存,單點畢竟是單機,還是有性能上限的。

想方設法水平擴展,消除系統單點,理論上才能夠無限的提升系統系統。

以nginx爲例,如何來進行水平擴展呢?


第一步的DNS解析,只能返回一個nginx外網IP麼?答案顯然是否定的,“DNS輪詢”技術支持DNS-server返回不同的nginx外網IP,這樣就能實現nginx負載均衡層的水平擴展。

 


DNS-server部分,一個域名可以配置多個IP,每次DNS解析請求,輪詢返回不同的IP,就能實現nginx的水平擴展,擴充負載均衡層的整體性能。

 

數據庫單點寫庫也是同樣的道理,在數據量很大的情況下,可以通過水平拆分,來提升寫入性能。

 

遺憾的是,並不是所有的業務場景都可以水平拆分,例如秒殺業務,商品的條數可能不多,數據庫的數據量不大,就不能通過水平拆分來提升秒殺系統的整體寫性能(總不能一個庫100條記錄吧?)。

 

六、總結

今天的話題就討論到這裏,內容很多,佔用大家寶貴的時間深表內疚,估計大部分都記不住,至少記住這幾個點吧:

(1)單點系統存在的問題:可用性問題,性能瓶頸問題

(2)shadow-master是一種常見的解決單點系統可用性問題的方案

(3)減少與單點的交互,是存在單點的系統優化的核心方向,常見方法有批量寫,客戶端緩存

(4)水平擴展也是提升單點系統性能的好方案

集羣信息管理,架構設計中最容易遺漏的一環

  • 是什麼

  • 什麼場景,爲什麼會用到,存在什麼問題

  • 常見方案及痛點

  • 不同階段公司,不同實現方案

一、啥是集羣?

互聯網典型分層架構如下:

  • web-server層

  • service層

  • db層與cache層

 

爲了保證高可用,每一個站點、服務、數據庫、緩存都會冗餘多個實例,組成一個分佈式的系統,集羣則是一個分佈式的物理形態。

 

額,好拗口,通俗的說,集羣就是一堆機器,上面部署了提供相似功能的站點,服務,數據庫,或者緩存。

如上圖:

  • web集羣,由web.1和web.2兩個實例組成

  • service集羣,由service.1/service.2/service.3三個實例組成

  • db集羣,由mysql-M/mysql-S1/mysql-S2三個實例組成

  • cache集羣,由cache-M/cache-S兩個實例組成

 

與“集羣”相對應的是“單機”。

畫外音:關於高可用架構,詳見文章《究竟啥纔是互聯網架構“高可用”》。

畫外音:緩存如果沒有高可用要求,可能是單機架構,而不是集羣。

 

二、集羣信息

什麼是集羣信息?

一個集羣,會包含若干信息(額,這tm算什麼解釋),例如:

  • 集羣名稱

  • IP列表

  • 二進制目錄

  • 配置目錄

  • 日誌目錄

  • 負責人列表

畫外音:集羣IP列表不建議直接使用IP,而建議使用內網域名,詳見文章《小小的IP,大大的耦合》。

 

什麼時候會用到集羣信息呢?

很多場景,特別是線上操作,都會使用到各種集羣信息,例如:

  • 自動化上線

  • 監控

  • 日誌清理

  • 二進制與配置的備份

  • 下游的調用(額,這個最典型)

 

這些場景,分別都是如何讀取集羣信息的?

一般來說,早期會把集羣信息寫在配置文件裏。

 

例如,自動化上線,有一個配置文件,deploy.user.service.config,其內容是:

name : user.service

ip.list : ip1, ip2, ip3

bin.path : /user.service/bin/

ftp.path : ftp://192.168.0.1/USER_2_0_1_3/user.exe

 

自動化上線的過程,則是:

  • 把可執行文件從ftp拉下來

  • 讀取集羣IP列表

  • 讀取二進制應該部署的目錄

  • 把二進制部署到線上

  • 逐臺重啓

畫外音:啥,還沒有實現自動化腳本部署?還處在運維ssh到線上,手動執行命令,逐臺機器人肉部署的刀耕火種階段?趕緊照着這個方案,做自動化改造吧。

又例如,web-X調用下游的user服務,又有一個配置文件,web-X.config,其內容配置了:

service.name : user.service

service.ip.list : ip1, ip2, ip3

service.port : 8080

web-X調用user服務的過程,則是:

  • web-X啓動

  • web-X讀取user服務集羣的IP列表與端口

  • web-X初始化user服務連接池

  • web-X拿取user服務的連接,通過RPC接口調用user服務

日誌清理,服務監控,二進制備份的過程,也都與上述類似。

三、存在什麼問題?

上述業務場景,對於集羣信息的使用,有兩個最大的特點

  • 每個應用場景,所需集羣信息都不一樣(A場景需要集羣abc信息,B場景需要集羣def信息)

  • 每個應用場景,集羣信息都寫在“自己”的配置文件裏

一句話總結:集羣信息管理分散化。

這裏最大的問題,是耦合,當集羣的信息發生變化的時候,有非常多的配置需要修改:

  • deploy.user.service.config

  • clean.log.user.service.config

  • backup.bin.user.service.config

  • monitor.config

  • web-X.config

這些配置裏,user服務集羣的信息都需要修改:

  • 隨着研發、測試、運維人員的流動,很多配置放在哪裏,逐步就被遺忘了

  • 隨着時間的推移,一些配置就被改漏了

  • 逐漸的,莫名其妙的問題出現了

畫外音:ca,誰痛誰知道

如何解決上述耦合的問題呢?

一句話回答:集羣信息管理集中化。

四、如何集中化管理集羣信息

如何集中化管理集羣配置信息,不同發展階段的公司,實現的方式不一樣。

 

早期方案

通過全局配置文件,實現集羣信息集中管理,舉例global.config如下:

[user.service]

ip.list : ip1, ip2, ip3

port : 8080

bin.path : /user.service/bin/

log.path : /user.service/log/

conf.path : /user.service/conf/

ftp.path :ftp://192.168.0.1/USER_2_0_1_3/user.exe

owner.list : shenjian, zhangsan, lisi

 

[passport.web]

ip.list : ip11, ip22, ip33

port : 80

bin.path : /passport.web/bin/

log.path : /passport.web/log/

conf.path : /passport.web/conf/

ftp.path :ftp://192.168.0.1/PST_1_2_3_4/passport.jar

owner.list : shenjian, zui, shuaiqi

 

集中維護集羣信息之後:

  • 任何需要讀取集羣信息的場景,都從global.config裏讀取

  • 任何集羣信息的修改,只需要修改global.config一處

  • global.config會部署到任何一臺線上機器,維護和管理也很方便

畫外音:額,當然,信息太多的話,global.config也要垂直拆分

 

中期方案

隨着公司業務的發展,隨着技術團隊的擴充,隨着技術體系的完善,通過集羣信息管理服務,來維護集羣信息的訴求原來越強烈。

畫外音:慢慢的,配置太多了,通過global.config來修改配置太容易出錯了

如上圖,建立集羣信息管理服務

  • info.db :存儲集羣信息

  • info.cache :緩存集羣信息

  • info.service :提供集羣信息訪問的RPC接口,以及HTTP接口

  • info.web :集羣信息維護後臺

 

服務的核心接口是:

Info InfoService::getInfo(String ClusterName);

Bool InfoService::setInfo(String ClusterName, String key, String value);

 

然後,統一通過服務來獲取與修改集羣信息:

  • 所有需要獲取集羣信息的場景,都通過info.service提供的接口來讀取集羣信息

  • 所有需要修改集羣信息的場景,都通過info.web來操作

 

長期方案

集羣信息服務可以解決大部分的耦合問題,但仍然有一個不足:集羣信息變更時,無法反向實時通知關注方,集羣信息發生了改變。更長遠的,要引入配置中心來解決。

配置中心的細節,網上的分析很多,之前也撰文寫過,細節就不再本文展開。

 

五、總結

集羣信息管理,是架構設計中非常容易遺漏的一環,但又是非常基礎,非常重要的基礎設施,一定要在早期規劃好:

  • 傳統的方式,分散化管理集羣信息,容易導致耦合

  • 集中管理集羣信息,有全局配置,信息服務,配置中心三個階段

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章