負載均衡知識總結前端
參考:mysql
微信公衆號:架構師之路linux
什麼是負載均衡nginx
負載均衡(Load Balance)是分佈式系統架構設計中必須考慮的因素之一,它一般是指,將請求/數據【均勻】分攤到多個操做單元上執行,負載均衡的關鍵在於【均勻】。web
常見的負載均衡方案sql
常見互聯網分佈式架構如上,分爲客戶端層、反向代理nginx層、站點層、服務層、數據層。能夠看到,每個下游都有多個上游調用,只須要作到,每個上游都均勻訪問每個下游,就能實現「將請求/數據【均勻】分攤到多個操做單元上執行」。數據庫
【客戶端層->反向代理層】的負載均衡apache
【客戶端層】到【反向代理層】的負載均衡,是經過「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)…
【站點層->服務層】的負載均衡
【站點層】到【服務層】的負載均衡,是經過「服務鏈接池」實現的。
上游鏈接池會創建與下游服務多個鏈接,每次請求會「隨機」選取鏈接來訪問下游服務。
上一篇文章《RPC-client實現細節》中有詳細的負載均衡、故障轉移、超時處理的細節描述,歡迎點擊link查閱,此處再也不展開。
【數據層】的負載均衡
在數據量很大的狀況下,因爲數據層(db,cache)涉及數據的水平切分,因此數據層的負載均衡更爲複雜一些,它分爲「數據的均衡」,與「請求的均衡」。
數據的均衡是指:水平切分後的每一個服務(db,cache),數據量是差很少的。
請求的均衡是指:水平切分後的每一個服務(db,cache),請求量是差很少的。
業內常見的水平切分方式有這麼幾種:
1、按照range水平切分
每個數據服務,存儲必定範圍的數據,上圖爲例:
user0服務,存儲uid範圍1-1kw
user1服務,存儲uid範圍1kw-2kw
這個方案的好處是:
(1)規則簡單,service只需判斷一下uid範圍就能路由到對應的存儲服務
(2)數據均衡性較好
(3)比較容易擴展,能夠隨時加一個uid[2kw,3kw]的數據服務
不足是:
(1)請求的負載不必定均衡,通常來講,新註冊的用戶會比老用戶更活躍,大range的服務請求壓力會更大
2、按照id哈希水平切分
每個數據服務,存儲某個key值hash後的部分數據,上圖爲例:
user0服務,存儲偶數uid數據
user1服務,存儲奇數uid數據
這個方案的好處是:
(1)規則簡單,service只需對uid進行hash能路由到對應的存儲服務
(2)數據均衡性較好
(3)請求均勻性較好
不足是:
(1)不容易擴展,擴展一個數據服務,hash方法改變時候,可能須要進行數據遷移
總結
負載均衡(Load Balance)是分佈式系統架構設計中必須考慮的因素之一,它一般是指,將請求/數據【均勻】分攤到多個操做單元上執行,負載均衡的關鍵在於【均勻】。
(1)【客戶端層】到【反向代理層】的負載均衡,是經過「DNS輪詢」實現的
(2)【反向代理層】到【站點層】的負載均衡,是經過「nginx」實現的
(3)【站點層】到【服務層】的負載均衡,是經過「服務鏈接池」實現的
(4)【數據層】的負載均衡,要考慮「數據的均衡」與「請求的均衡」兩個點,常見的方式有「按照範圍水平切分」與「hash水平切分」
上一篇文章「一分鐘瞭解負載均衡的一切」引發了很多同窗的關注,評論中你們爭論的比較多的一個技術點是接入層負載均衡技術,部分同窗持這樣的觀點:
1)nginx前端加入lvs和keepalived能夠替代「DNS輪詢」
2)F5能搞定接入層高可用、擴展性、負載均衡,能夠替代「DNS輪詢」
「DNS輪詢」到底是不是過期的技術,是否是能夠被其餘方案替代,接入層架構技術演進,是本文將要細緻討論的內容。
1、問題域
nginx、lvs、keepalived、f五、DNS輪詢,往往提到這些技術,每每討論的是接入層的這樣幾個問題:
1)可用性:任何一臺機器掛了,服務受不受影響
2)擴展性:可否經過增長機器,擴充系統的性能
3)反向代理+負載均衡:請求是否均勻分攤到後端的操做單元執行
2、上面那些名詞都是幹嗎的
因爲每一個技術人的背景和知識域不一樣,上面那些名詞縮寫(運維的同窗再熟悉不過了),仍是花1分鐘簡單說明一下(詳細請自行「百度」):
1)nginx:一個高性能的web-server和實施反向代理的軟件
2)lvs:Linux Virtual Server,使用集羣技術,實如今linux操做系統層面的一個高性能、高可用、負載均衡服務器
3)keepalived:一款用來檢測服務狀態存活性的軟件,經常使用來作高可用
4)f5:一個高性能、高可用、負載均衡的硬件設備(聽上去和lvs功能差很少?)
5)DNS輪詢:經過在DNS-server上對一個域名設置多個ip解析,來擴充web-server性能及實施負載均衡的技術
3、接入層技術演進
【裸奔時代(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出場了(以前的文章「使用shadow-master保證系統可用性」詳細介紹過):
此時:
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來作負載均衡,業務七層路由
4、結論
聊了這麼多,稍微作一個簡要的總結:
1)接入層架構要考慮的問題域爲:高可用、擴展性、反向代理+擴展均衡
2)nginx、keepalived、lvs、f5能夠很好的解決高可用、擴展性、反向代理+擴展均衡的問題
3)水平擴展scale out是解決擴展性問題的根本方案,DNS輪詢是不能徹底被nginx/lvs/f5所替代的
末了,上一篇文章有同窗留言問58到家採用什麼方案,58到家目前部署在阿里雲上,前端購買了SLB服務(能夠先粗暴的認爲是一個lvs+keepalived的高可用負載均衡服務),後端是nginx+tomcat。
5、挖坑
接入層講了這麼多,下一章,準備講講服務層「異構服務的負載均」(牛逼的機器應該分配更多的流量,如何作到?)。
零、需求緣起
第一篇文章「一分鐘瞭解負載均衡」和你們share了互聯網架構中反向代理層、站點層、服務層、數據層的經常使用負載均衡方法。
第二篇文章「lvs爲什麼不能徹底代替DNS輪詢」和你們share了互聯網接入層負載均衡須要解決的問題及架構演進。
在這兩篇文章中,都強調了「負載均衡是指,將請求/數據【均勻】分攤到多個操做單元上執行,負載均衡的關鍵在於【均勻】」。
然而,後端的service有可能部署在硬件條件不一樣的服務器上:
1)若是對標最低配的服務器「均勻」分攤負載,高配的服務器的利用率不足;
2)若是對標最高配的服務器「均勻」分攤負載,低配的服務器可能會扛不住;
可否根據異構服務器的處理能力來動態、自適應進行負載均衡及過載保護,是本文要討論的問題。
1、service層的負載均衡一般是怎麼作的
「一分鐘瞭解負載均衡」中提到,service層的負載均衡,通常是經過service鏈接池來實現的,調用方鏈接池會創建與下游服務多個鏈接,每次請求「隨機」獲取鏈接,來保證service訪問的均衡性。
「RPC-client實現細節」中提到,負載均衡、故障轉移、超時處理等細節也都是經過調用方鏈接池來實現的。
這個調用方鏈接池可否實現,根據service的處理能力,動態+自適應的進行負載調度呢?
2、經過「靜態權重」標識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作反向代理與負載均衡,就有相似的機制。
這個方案的優勢是:簡單,可以快速的實現異構服務器的負載均衡。
缺點也很明顯:這個權重是固定的,沒法自適應動態調整,而不少時候,服務器的處理能力是很難用一個固定的數值量化。
3、經過「動態權重」標識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會被分配到更多的流量。
4、過載保護
提問:什麼是過載保護?
圖示:無過載保護的負載與處理能力圖(會掉底)
回答:互聯網軟件架構設計中所指的過載保護,是指當系統負載超過一個service的處理能力時,若是service不進行自我保護,可能致使對外呈現處理能力爲0,且不能自動恢復的現象。而service的過載保護,是指即便系統負載超過一個service的處理能力,service讓能保證對外提供有損的穩定服務。
圖示:有過載保護的負載與處理能力圖(不會掉底)
提問:如何進行過載保護?
回答:最簡易的方式,服務端設定一個負載閾值,超過這個閾值的請求壓過來,所有拋棄。這個方式不是特別優雅。
5、如何藉助「動態權重」來實施過載保護
動態權重是用來標識每一個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集羣」的處理能力,怎麼轉移請求也是處理不過來的,還得經過拋棄請求來實施自我保護。
6、總結
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是一種很常見的解決單點高可用問題的技術方案。
「影子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)水平擴展也是提高單點系統性能的好方案
準備系統性介紹「技術體系規劃」了,這是第一篇。
監控平臺,服務治理,調用鏈跟蹤,數據收集中心,自動化運維,自動化測試… 不少要講,卻沒想好從哪裏入手。
講Z平臺,可能須要提早介紹Y服務;講Y服務,可能須要提早介紹X知識。
思來想去,準備從技術體系裏,最容易被遺漏,很是基礎,卻又很是重要的「集羣信息管理」開始介紹。
因爲基礎,可能部分同窗會以爲簡單;因爲你們所在公司處於不一樣階段,因此在實現上會介紹不一樣階段的公司應該如何來實現。
仍是一如既往的按照「架構師之路」的思路:
是什麼
什麼場景,爲何會用到,存在什麼問題
常見方案及痛點
不一樣階段公司,不一樣實現方案
但願大夥有收穫。
1、啥是集羣?
互聯網典型分層架構以下:
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兩個實例組成
與「集羣」相對應的是「單機」。
畫外音:關於高可用架構,詳見文章《究竟啥纔是互聯網架構「高可用」》。
畫外音:緩存若是沒有高可用要求,多是單機架構,而不是集羣。
2、集羣信息
什麼是集羣信息?
一個集羣,會包含若干信息(額,這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服務
日誌清理,服務監控,二進制備份的過程,也都與上述相似。
3、存在什麼問題?
上述業務場景,對於集羣信息的使用,有兩個最大的特色:
每一個應用場景,所需集羣信息都不同(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,誰痛誰知道
如何解決上述耦合的問題呢?
一句話回答:集羣信息管理集中化。
4、如何集中化管理集羣信息
如何集中化管理集羣配置信息,不一樣發展階段的公司,實現的方式不同。
早期方案
經過全局配置文件,實現集羣信息集中管理,舉例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來操做
長期方案
集羣信息服務能夠解決大部分的耦合問題,但仍然有一個不足:集羣信息變動時,沒法反向實時通知關注方,集羣信息發生了改變。更長遠的,要引入配置中心來解決。
配置中心的細節,網上的分析不少,以前也撰文寫過,細節就再也不本文展開。
5、總結
集羣信息管理,是架構設計中很是容易遺漏的一環,但又是很是基礎,很是重要的基礎設施,必定要在早期規劃好:
傳統的方式,分散化管理集羣信息,容易致使耦合
集中管理集羣信息,有全局配置,信息服務,配置中心三個階段
6、調研
調研一、對於集羣信息管理,你的感覺是:
ca,沒考慮過這個問題,一直是分散式管理
在使用全局配置文件
在使用信息管理服務
在使用配置中心
調研二、對於自動化運維,你的感覺是:
ca,啥是運維,都是研發在線上亂搞
有專門的運維,但一直是人肉運維
運維在使用腳本,實現了自動化
運維都下崗了,在使用平臺,實現了平臺化