如何大大提升微服務(wù)的高可用性?
微服務(wù)架構(gòu)現(xiàn)在是個(gè)熱門(mén)話題,微服務(wù)的高可用性自然也是企業(yè)非常關(guān)注的。眼下互聯(lián)網(wǎng)的架構(gòu)秘籍三板斧“高可用可擴(kuò)展,緩存提速,消峰減流去并發(fā)”,在微服務(wù)架構(gòu)體系中有著不一樣的詮釋。
在微服務(wù)中消息隊(duì)列不僅用來(lái)消峰,還可以通過(guò)消息隊(duì)列來(lái)解決微服務(wù)之間的多耦合,把同步調(diào)用轉(zhuǎn)化為異步調(diào)用,減少調(diào)用鏈路,提升系統(tǒng)穩(wěn)定性。單體應(yīng)用拆分為獨(dú)立的多個(gè)無(wú)形中增加了系統(tǒng)的響應(yīng)時(shí)間,可以通過(guò)本地緩存、分布式緩存相結(jié)合的方式來(lái)彌補(bǔ)性能的損耗。以前通過(guò)內(nèi)部接口調(diào)用的方法變成RPC調(diào)用多個(gè)服務(wù),服務(wù)與服務(wù)之間還有依賴(lài)關(guān)系,每個(gè)服務(wù)接口響應(yīng)時(shí)間也都不一樣,簡(jiǎn)單的設(shè)置單個(gè)接口的超時(shí)時(shí)間已解決不了問(wèn)題,可通過(guò)服務(wù)定級(jí),哪些服務(wù)不能出問(wèn)題,哪些服務(wù)允許有異常,采用降級(jí)、熔斷的方式來(lái)解決問(wèn)題,以達(dá)到系統(tǒng)的高可用。這三種方式如能合理運(yùn)用,微服務(wù)的高可用性大大提升,所以說(shuō)緩存、隊(duì)列、熔斷降級(jí)成了微服務(wù)架構(gòu)中的新三板斧。
以下是相關(guān)技術(shù)應(yīng)用中的一些難點(diǎn)解答,供大家參考。
1、微服務(wù)架構(gòu)中有哪些技術(shù)手段必須在設(shè)計(jì)階段就需要規(guī)劃進(jìn)去?
互聯(lián)網(wǎng)的三板斧:熔斷、消息隊(duì)列、緩存、這個(gè)必須有要考慮進(jìn)入,另外為了提高響應(yīng)時(shí)間,并行化操作也需要提前考慮。
熔斷:保障服務(wù)高可用的重要手段,用戶的請(qǐng)求將不再直接訪問(wèn)服務(wù),而是通過(guò)線程池中的空閑線程來(lái)訪問(wèn)服務(wù),如果線程池已滿,則會(huì)進(jìn)行降級(jí)處理,用戶的請(qǐng)求不會(huì)被阻塞,至少可以看到一個(gè)執(zhí)行結(jié)果(例如返回友好的提示信息),而不是無(wú)休止的等待或者看到系統(tǒng)崩潰。
消息隊(duì)列:消息隊(duì)列(MQ)是一種不同應(yīng)用程序之間(跨進(jìn)程)的通信方法,在微服務(wù)中引入消息隊(duì)列的目的就是為了減少鏈路,減少依賴(lài)。
緩存:為了提高QPS,減少數(shù)據(jù)庫(kù)壓力,分本地和遠(yuǎn)程緩存;
2、 緩存是每個(gè)互聯(lián)網(wǎng)應(yīng)用系統(tǒng)必備的組件,在微服務(wù)框架下如何用好緩存來(lái)提高系統(tǒng)的QPS?
在緩存的使用場(chǎng)景中,有一種2/8法則的說(shuō)法,即20%的請(qǐng)求訪問(wèn)DB(如有可能再少一點(diǎn)),80%的請(qǐng)求訪問(wèn)緩存。在微服務(wù)場(chǎng)景下,本身是接口調(diào)用的現(xiàn)在變成了RPC遠(yuǎn)程調(diào)用了,在一定程度上的確提高了單個(gè)接口的響應(yīng)時(shí)間。但是從全局角度看,微服務(wù)提高了系統(tǒng)的QPS量級(jí),所以從某種程度上來(lái)說(shuō),因?yàn)镻RC的原因提高了單個(gè)接口的RT是可以忽略的。當(dāng)然如果是為了最求極致,想盡可能的降低因?yàn)镻RC帶來(lái)的接口響應(yīng)時(shí)間,如果是涉及多個(gè)服務(wù)調(diào)用的,可以并行調(diào)用服務(wù),同時(shí)將并行結(jié)果緩存在本地。后端每個(gè)原子服務(wù)都會(huì)對(duì)接緩存,這樣能有效提高系統(tǒng)的響應(yīng)時(shí)間。
一般API接口發(fā)起請(qǐng)求到后端服務(wù),如果涉及到會(huì)調(diào)用多個(gè)接口,那么會(huì)有一層聚合層,通常在聚合層做緩存,緩存分本地緩存(如JVM)或者遠(yuǎn)端緩存(如Redis或Memcache)。由于是都是分布式架構(gòu),所以緩存一般采用TTL自動(dòng)過(guò)期來(lái)清除緩存。如果業(yè)務(wù)量非常大,但是對(duì)于數(shù)據(jù)的不一致有比較高的要求,可以設(shè)置1秒。如果要求不高可以設(shè)置30秒或者分鐘級(jí)別都可以。但是在軟件架構(gòu)中通常會(huì)使用讀寫(xiě)分離來(lái)提高QPS,由于緩存會(huì)導(dǎo)致數(shù)據(jù)的不一致性,某些場(chǎng)景如需要數(shù)據(jù)強(qiáng)一致性,可以通過(guò)版本號(hào)的方式來(lái)處理。比如李四讀取A數(shù)據(jù)的時(shí)候version=1,同時(shí)有用戶張三對(duì)記錄A做了一次操作,那么version=2。這個(gè)時(shí)候李四是不能對(duì)于記錄A做變更操作的。
3、 消息隊(duì)列MQ在微服務(wù)中怎么用,有什么好的技巧?使用MQ一定要考慮冪等性嗎?
消息隊(duì)列(MQ)是一種不同應(yīng)用程序之間(跨進(jìn)程)的通信方法。消息隊(duì)列主要有:異步處理 - 增加吞吐量;削峰填谷 - 提高系統(tǒng)穩(wěn)定性;系統(tǒng)解耦 - 業(yè)務(wù)邊界隔離;數(shù)據(jù)同步 - 最終一致性保證。在微服務(wù)中引入消息隊(duì)列的目的就是為了減少鏈路,減少依賴(lài)。舉例說(shuō),用戶注冊(cè)后系統(tǒng)會(huì)給用戶發(fā)積分,發(fā)優(yōu)惠券,以及一些其他初始化操作。如果不用MQ的話,那么需要依賴(lài)積分服務(wù),優(yōu)惠券服務(wù)等其他服務(wù)。但是對(duì)于用戶服務(wù)來(lái)說(shuō),只管注冊(cè)不管其他的衍生服務(wù),所以發(fā)送MQ后其他依賴(lài)方消費(fèi)即可。微服務(wù)只要配置了重試機(jī)制寫(xiě)入接口都需要考慮冪等性。因?yàn)樾枰紤]網(wǎng)絡(luò)的抖動(dòng),數(shù)據(jù)包會(huì)重復(fù)提交,如果沒(méi)有冪等性就會(huì)出現(xiàn)臟數(shù)據(jù)了。使用消息隊(duì)列也需要使用冪等性,因?yàn)橄M(fèi)端可能在某個(gè)環(huán)節(jié)失敗后沒(méi)有commit,導(dǎo)致消息會(huì)再次投遞的。
4、 使用熔斷降級(jí)技術(shù)需要考慮哪些方面?哪些參數(shù)需要調(diào)優(yōu)?
所謂的降級(jí)或熔斷是針對(duì)非核心業(yè)務(wù)系統(tǒng),當(dāng)非核心業(yè)務(wù)系統(tǒng)因流量過(guò)大而出現(xiàn)響應(yīng)慢,那么部分請(qǐng)求這個(gè)接口會(huì)出現(xiàn)降級(jí),當(dāng)達(dá)到一定策略之后就會(huì)變成熔斷。熔斷后可以是時(shí)候異步做處理。另外一種情況就是手動(dòng)指定某個(gè)接口熔斷,例如某電商會(huì)在大促的時(shí)候把猜你喜歡或者為你推薦給屏蔽。如果沒(méi)有熔斷方式,那么就需要手動(dòng)寫(xiě)代碼,經(jīng)過(guò)開(kāi)發(fā)-測(cè)試-預(yù)發(fā)-線上環(huán)節(jié),比較浪費(fèi)時(shí)間。所有的策略都是為了高可用而做鋪墊的。一般使用hystrix來(lái)做降級(jí)熔斷功能,可配置的參數(shù)非常多,但是重點(diǎn)需要注意的點(diǎn):circuitBreaker.requestVolumeThreshold circuitBreaker.errorThresholdPercentage execution.isolation.thread.timeoutInMilliseconds hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 另外,需要支持手動(dòng)打開(kāi)熔斷器,以防止特殊情況下需要主動(dòng)打開(kāi)熔斷器。
5、微服務(wù)面臨壓力過(guò)大怎么自動(dòng)進(jìn)行調(diào)整或臨時(shí)做到彈性增加服務(wù)?
流量基本上會(huì)分成2種:
1、正常業(yè)務(wù)流量,運(yùn)營(yíng)期間大流量(提前知曉)
2、被攻擊流量 大量用戶請(qǐng)求峰值基本上都會(huì)提前預(yù)知,比如運(yùn)營(yíng)做活動(dòng),會(huì)預(yù)估用戶量,根據(jù)這個(gè)預(yù)估的量來(lái)事先做容量擴(kuò)充。如果是突發(fā)性的異常大流量,那就懷疑是否被攻擊了,需要做相關(guān)網(wǎng)絡(luò)層面的防護(hù)了。一般系統(tǒng)都會(huì)基本的保護(hù)措施,如, 限流:比如針對(duì)IP的限流 黑名單:針對(duì)IP的黑名單 通過(guò)上述方式基本上能攔截很大的非正常流量,然后系統(tǒng)層面對(duì)接口做限流以及降級(jí)和熔斷來(lái)保障平臺(tái)穩(wěn)定。
彈性擴(kuò)容是增加系統(tǒng)能支持的QPS量級(jí)。這里涉及到幾個(gè)需要做無(wú)狀態(tài)的核心組件:
1、緩存:緩存是否支持動(dòng)態(tài)增加;
2、DB:這里的DB是指只讀叢庫(kù) 因?yàn)槲⒎?wù)天生支持多實(shí)例部署,由于能做到1,2了,那么可以根據(jù)營(yíng)銷(xiāo)活動(dòng)的用戶量初步預(yù)估下系統(tǒng)在高峰期的QPS會(huì)有多少,然后再去計(jì)算需要增加多少實(shí)例,緩存增加多少只讀只讀實(shí)例,DB增加多少只讀實(shí)例。
同時(shí)需要做好如下3點(diǎn):
1、控制好限流和熔斷策略,以防止流量壓垮服務(wù)。
2、熱門(mén)活動(dòng)場(chǎng)景,本地+遠(yuǎn)端緩存一起使用;
3、活動(dòng)期間把一些非核心流程先做熔斷處理;
6、微服務(wù)主要用什么方法保證高可用呢?硬負(fù)載均衡設(shè)備還是軟負(fù)載方式保證?
微服務(wù)框架本身就支持了同一個(gè)服務(wù)發(fā)布多個(gè)應(yīng)用實(shí)例,且部署的應(yīng)用和注冊(cè)中心都有心跳檢測(cè),以保障應(yīng)用都是在線狀態(tài)。同時(shí)框架本身會(huì)支持負(fù)載均衡以及重試機(jī)制,可以確保在單個(gè)應(yīng)用宕機(jī)的情況下不影響應(yīng)用,可以說(shuō)微服務(wù)的框架通過(guò)軟負(fù)載的方式來(lái)保證了服務(wù)的高可用。
談到高可用,就想到了微服務(wù),為什么說(shuō)微服務(wù)難,其實(shí)并不是難在開(kāi)發(fā)階段,而且對(duì)于整個(gè)團(tuán)隊(duì)的整體性要求高了。其中包括:運(yùn)維流程,監(jiān)控體系。
運(yùn)維流程:是否有持續(xù)集成,是否支持鏈?zhǔn)讲渴?,支持版本回滾。
監(jiān)控體系:慢響應(yīng),超時(shí)、ERROR能否及時(shí)的報(bào)警通知。
所有要提高微服務(wù)的高可用性,不僅僅是研發(fā)的事情,而是開(kāi)發(fā)、運(yùn)維一體才可以。
7、微服務(wù)框架部署時(shí)的業(yè)務(wù)連續(xù)性如何考慮?
近年金融行業(yè),尤其是銀行業(yè)監(jiān)管越來(lái)越嚴(yán)格,對(duì)業(yè)務(wù)連續(xù)性要求的更高,銀行系統(tǒng)對(duì)于由傳統(tǒng)架構(gòu)遷移至微服務(wù)有較迫切的需求,目前在實(shí)際部署系統(tǒng)時(shí),一般需要考慮系統(tǒng)的同城雙活或同城、異地多活,以保障業(yè)務(wù)連續(xù)性。那么在遷移至微服務(wù)架構(gòu)的過(guò)程中,微服務(wù)架構(gòu)上對(duì)于雙活、多活的需求是如何考慮的?如何實(shí)現(xiàn)異常情況下快速無(wú)中斷切換、不同中心間數(shù)據(jù)一致性等問(wèn)題是否有解決建議?
解答1:
這個(gè)問(wèn)題信息量比較大,同城雙活或同城、異地多活甚至目前跨云的多活都是大家所關(guān)注的話題。微服務(wù)的定義就是服務(wù)獨(dú)立化、動(dòng)態(tài)擴(kuò)容等一些優(yōu)點(diǎn),所以從微服務(wù)角度看并不關(guān)注多活,雙活,只要服務(wù)能正常允許即可。但是從架構(gòu)角度來(lái)看,如需要支持多活,雙活,那么一些基礎(chǔ)設(shè)施是否具備了這些特性,比如Redis,Mysql是否支持雙主,是否支持主主自動(dòng)切換,MQ的是否支持。這些工作量非常的大。個(gè)人建議在技術(shù)能力、人力都不足的情況下不要搞雙活,如非得考慮這方案因素,那還是建議去實(shí)施主備模式,即每個(gè)機(jī)房都部署一模一樣的系統(tǒng),當(dāng)主的出現(xiàn)問(wèn)題后把流量切到備用上。
解答2:
目前應(yīng)該還沒(méi)有微服務(wù)跨數(shù)據(jù)中心的合適技術(shù),跨數(shù)據(jù)中心,需要解決微服務(wù)調(diào)度、服務(wù)發(fā)布的問(wèn)題,還需要面對(duì)時(shí)延挑戰(zhàn)。所以比較好的方法是一個(gè)應(yīng)用的微服務(wù)盡量都盡量在一個(gè)數(shù)據(jù)中心部署,考慮容災(zāi)可以在另一個(gè)數(shù)據(jù)中心也部署統(tǒng)一套應(yīng)用,前端通過(guò)負(fù)載均衡或者服務(wù)治理引流。
解答3:
這個(gè)問(wèn)題其實(shí)展開(kāi)說(shuō)還是非常復(fù)雜的。底層不用區(qū)分上層是基于傳統(tǒng)的服務(wù)方式,還是微服務(wù)方式,只需要注意數(shù)據(jù)同步問(wèn)題即可。在應(yīng)用層面,拆分成微服務(wù)后,微服務(wù)應(yīng)用數(shù)量大量增加,并且會(huì)使用到配置中心,注冊(cè)中心等微服務(wù)分布式組件,這些都對(duì)網(wǎng)絡(luò)要求比較高。所以比較好的方式是在一個(gè)業(yè)務(wù)請(qǐng)求在一個(gè)機(jī)房?jī)?nèi)完成,同時(shí)每個(gè)機(jī)房部署各自的微服務(wù)框架,減少跨機(jī)房流量。同時(shí)配置相應(yīng)的微服務(wù)監(jiān)控模塊,以及故障自愈。
8、微服務(wù)是否一定要Docker容器化?如果是,原因是什么?優(yōu)缺點(diǎn)都有哪些?
成本角度:docker或者虛擬機(jī)將原本單體物理服務(wù)器拆分為多臺(tái)虛擬機(jī),機(jī)器之間的資源也是隔離的,所以成本上有很大程度降低。
部署效率:簡(jiǎn)單說(shuō)docker和虛擬機(jī)都是一個(gè)概念,在服務(wù)化的場(chǎng)景下docker比虛擬機(jī)強(qiáng)的原因其實(shí)也很簡(jiǎn)單,舉個(gè)例子,明天需要做一個(gè)非常大的影響活動(dòng),初步估算下每種核心節(jié)點(diǎn)服務(wù)需要增加10臺(tái)集群,目前核心服務(wù)有12個(gè),即12*10=120臺(tái),需要擴(kuò)容120臺(tái)機(jī)器。虛擬機(jī)做法:開(kāi)通120個(gè)虛擬機(jī),配置環(huán)境,設(shè)置IP,端口,安裝應(yīng)用,啟動(dòng),調(diào)試。按一個(gè)熟手沒(méi)部署一臺(tái)需要10分鐘,那么累計(jì)需要1200分鐘,約20個(gè)小時(shí) docker做法:由于在部署的時(shí)候,每個(gè)應(yīng)用都被做成了一個(gè)鏡像,所以要發(fā)布這120個(gè)應(yīng)用,只需要通過(guò)腳本或者命令即可,整個(gè)過(guò)程約1個(gè)小時(shí)內(nèi)完成。所以在服務(wù)數(shù)量不是很多的情況下,用虛機(jī)也是能符合要求的。
9、微服務(wù)架構(gòu)下底層數(shù)據(jù)存儲(chǔ)的實(shí)現(xiàn)方式?
微服務(wù)的底層數(shù)據(jù)基本上都是異構(gòu)的,如MySQL、HBase、Redis、ES、hive等等。業(yè)務(wù)處理都會(huì)先直接寫(xiě)入MySQL,然后通過(guò)訂閱binLog的方式來(lái)做數(shù)據(jù)同步,一般會(huì)將binLog的數(shù)據(jù)寫(xiě)入MQ,消費(fèi)方在數(shù)據(jù)處理的時(shí)候需要考慮亂序問(wèn)題。對(duì)于要求強(qiáng)一致性的數(shù)據(jù)一定要攜帶版號(hào)。
10、我們處在微服務(wù)+容器的轉(zhuǎn)型探索時(shí)期,如何選擇微服務(wù)框架,以及鏈路追蹤?
框架選擇:微服務(wù)框架目前比較火的有dubbo和spring cloud,他們各有利弊。spring cloud個(gè)全家桶啥都全,但是真正能用好的并不多,無(wú)非是組件的堆疊。dubbo也從阿里自己運(yùn)營(yíng)轉(zhuǎn)向apache國(guó)際化方向,目前互聯(lián)網(wǎng)大部分公司都是使用dubbo框架,遇到問(wèn)題也能通過(guò)社區(qū)快速解決,響應(yīng)效率比較快,而且有各種技術(shù)沙龍可以學(xué)習(xí)。
鏈路追蹤:APM的選擇性比較多,有開(kāi)源的,有收費(fèi)的,目前市面的系統(tǒng)基本都是參考Google的Dapper論文來(lái)開(kāi)發(fā)的。如果預(yù)算充足,可以選擇收費(fèi)的企業(yè)版。好處是比較穩(wěn)定,遇到問(wèn)題有專(zhuān)人負(fù)責(zé)解答。如果研發(fā)資源充足,又想自己造輪子,可以選擇開(kāi)源版本,如skywalking,Pinpoint,Zipkin,CAT。skywalking,Pinpoint:基本不用修改源碼和配置文件,只要在啟動(dòng)命令里指定javaagent參數(shù)即可,對(duì)于運(yùn)維人員來(lái)講最為方便;Zipkin:需要對(duì)Spring、web.xml之類(lèi)的配置文件做修改,相對(duì)麻煩一些;CAT:需要在程序中硬編碼,侵入性比較大。具體選擇哪個(gè),這個(gè)根據(jù)業(yè)務(wù)團(tuán)隊(duì)的熟悉具體產(chǎn)品的程度來(lái)決定。