谈谈怎么做【服务隔离】
本文轉(zhuǎn)載自公眾號(hào)? 孤獨(dú)煙
引言
OK,如下圖所示
那顯而易見(jiàn),做服務(wù)隔離的目的就是避免服務(wù)之間相互影響。畢竟誰(shuí)也不能說(shuō)自己的微服務(wù)百分百可用,如果不做隔離,一旦一個(gè)服務(wù)出現(xiàn)了問(wèn)題,整個(gè)系統(tǒng)的穩(wěn)定性都會(huì)受到影響!
因此,做服務(wù)隔離是很有必要的。那么怎么隔離呢?
-
按種類(lèi)隔離
-
按用戶(hù)隔離
OK,接下來(lái)開(kāi)始細(xì)說(shuō)這兩種方式!
?
正文
種類(lèi)隔離
其實(shí)按照服務(wù)種類(lèi)隔離要從兩個(gè)緯度來(lái)說(shuō):即服務(wù)提供方和服務(wù)調(diào)用方!
假設(shè)我們一個(gè)系統(tǒng)有三個(gè)服務(wù):訂單服務(wù),庫(kù)存服務(wù),支付服務(wù)!有如下調(diào)用關(guān)系:
OK,我們先明確一點(diǎn),上面有幾個(gè)服務(wù)扮演服務(wù)提供方的角色?
一共是三個(gè):支付服務(wù)(給用戶(hù)提供服務(wù))、庫(kù)存服務(wù)(給支付服務(wù)提供服務(wù))、訂單服務(wù)(給支付服務(wù)提供服務(wù))
有幾個(gè)服務(wù)扮演服務(wù)調(diào)用方的角色?
一共是一個(gè):支付服務(wù)(調(diào)用訂單服務(wù)和庫(kù)存服務(wù))
針對(duì)服務(wù)提供方這個(gè)角度而言,怎么做隔離呢?
很簡(jiǎn)單,每一個(gè)服務(wù)乃至其對(duì)應(yīng)的數(shù)據(jù)庫(kù),給一個(gè)服務(wù)器部署就行!這樣某個(gè)服務(wù)出現(xiàn)了故障,就不會(huì)相互影響,達(dá)到一種物理層面上的隔離!
什么,你們公司服務(wù)器不夠?了解一下《微服務(wù)為什么一定要用docker》
針對(duì)服務(wù)調(diào)用方這個(gè)角度而言,怎么做隔離呢?
OK,先明白一點(diǎn),服務(wù)調(diào)用方不做隔離會(huì)出現(xiàn)什么情況?如圖所示
一個(gè)請(qǐng)求過(guò)來(lái),占用支付服務(wù)中的Tomcat的一個(gè)線程。然后,該線程去順序調(diào)用訂單服務(wù)和庫(kù)存服務(wù)!那么,一旦庫(kù)存服務(wù)出問(wèn)題了,這個(gè)Tomcat的線程就一直卡在那,無(wú)法返回!與此同時(shí),頁(yè)面上源源不斷的有請(qǐng)求過(guò)來(lái),會(huì)把Tomcat里頭的線程池資源全部消耗完畢!對(duì)于后面的請(qǐng)求,Tomcat就無(wú)法響應(yīng)!
因此,如果不針對(duì)被調(diào)服務(wù)做服務(wù)隔離,一個(gè)被調(diào)服務(wù)出問(wèn)題,就將導(dǎo)致調(diào)用方服務(wù)不可用!
那怎么隔離呢?
這里介紹一種線程池隔離方式,給每個(gè)微服務(wù)都初始化出一個(gè)線程池,如下圖所示,給訂單服務(wù)和庫(kù)存服務(wù)都初始化出一個(gè)線程池,不使用Tomcat線程池中的線程直接調(diào)用,而是用相應(yīng)線程池中的線程去調(diào)用!
OK,如果此時(shí)庫(kù)存服務(wù)不可用了呢?
庫(kù)存服務(wù)線程池會(huì)被迅速塞滿(mǎn),此時(shí)后面進(jìn)來(lái)的新請(qǐng)求發(fā)現(xiàn)庫(kù)存服務(wù)線程池滿(mǎn)啦,于是乎就不去調(diào)庫(kù)存服務(wù),直接返回!如下圖所示
ps:目前業(yè)內(nèi)有信號(hào)量隔離和線程池隔離兩種隔離方式,這里舉的是線程池隔離!
怎么實(shí)現(xiàn)呢?
可以了解一下Hytrix、Sentinel、以及Resilience4j如何和你的項(xiàng)目結(jié)合起來(lái)使用!Resilience4j只提供信號(hào)量隔離!
用戶(hù)隔離
OK,我們先明白一點(diǎn)這里的租戶(hù)和用戶(hù)不是一個(gè)概念!
-
用戶(hù): 一個(gè)環(huán)境/系統(tǒng)的一個(gè)使用者即該環(huán)境/系統(tǒng)的一個(gè)用戶(hù)。
-
租戶(hù):用戶(hù)從某種粒度上被分到若干組內(nèi),每組成為一個(gè)租戶(hù)。
這里的組可以這么理解:用戶(hù)根據(jù)一定的特征去做分組,比如是VIP的一組,不是VIP的一組。又或者北方的用戶(hù)一組,南方的用戶(hù)一組。按照自己的業(yè)務(wù)場(chǎng)景來(lái)分組。
那么所謂的用戶(hù)隔離,就是按照不同的分組形成不同的服務(wù)實(shí)例。這樣某個(gè)服務(wù)實(shí)例掛了,只影響對(duì)應(yīng)分組的用戶(hù),而不是全部用戶(hù)!
有如下三種方式!
-
方式一:每個(gè)租戶(hù)有獨(dú)立的服務(wù)和獨(dú)立的數(shù)據(jù)庫(kù)
-
方式二:每個(gè)租戶(hù)有共享的服務(wù)和獨(dú)立的數(shù)據(jù)庫(kù)
-
方式三:每個(gè)租戶(hù)有共享的服務(wù)和共享的數(shù)據(jù)庫(kù)
下面開(kāi)始逐個(gè)說(shuō)明
方式一
每個(gè)租戶(hù)有獨(dú)立的服務(wù)和獨(dú)立的數(shù)據(jù)庫(kù)!
這個(gè)在生產(chǎn)上一般是這么做,如下所示
如圖所示,用戶(hù)在請(qǐng)求的時(shí)候會(huì)經(jīng)過(guò)網(wǎng)關(guān)!網(wǎng)關(guān)根據(jù)tenant_id識(shí)別出對(duì)應(yīng)的服務(wù)實(shí)例,進(jìn)行轉(zhuǎn)發(fā)。至于用什么當(dāng)網(wǎng)關(guān),我們用的是Zuul。
方式二
每個(gè)租戶(hù)有共享的服務(wù)和獨(dú)立的數(shù)據(jù)庫(kù)!
這個(gè)在生產(chǎn)上一般是這么做,如下所示
如圖所示,用戶(hù)在請(qǐng)求的時(shí)候會(huì)經(jīng)過(guò)網(wǎng)關(guān),網(wǎng)關(guān)將數(shù)據(jù)轉(zhuǎn)發(fā)給用戶(hù)服務(wù)!用戶(hù)服務(wù)根據(jù)tenant_id確定該操作哪一個(gè)數(shù)據(jù)庫(kù)!
OK,這個(gè)時(shí)候大家應(yīng)該有一個(gè)疑問(wèn),
在項(xiàng)目代碼中,怎么確定該操作的數(shù)據(jù)庫(kù)?
好,這個(gè)就是ORM框架,動(dòng)態(tài)選擇數(shù)據(jù)源的問(wèn)題!我以國(guó)內(nèi)流行的hibernate和mybatis來(lái)進(jìn)行說(shuō)明!
(1)?hibernate方式
在4.0版本hibenate開(kāi)始支持多租戶(hù)架構(gòu),即對(duì)不同租戶(hù)使用獨(dú)立數(shù)據(jù)庫(kù)!大家可以搜索一個(gè)配置,叫hibernate.multiTenancy。該值有一個(gè)value值為
將這項(xiàng)的value值設(shè)為DATABASE后,還需要給hibernate.tenant_identifier_resolver配置項(xiàng)賦值,即告訴hibernate,如何解析出tenant_id。以及給hibernate.multi_tenant_connection_provider配置項(xiàng)賦值,即告訴hibernate如何以租戶(hù)特有的方式獲取數(shù)據(jù)連接!
ps:看不懂的童鞋略過(guò),懂hibernate的童鞋自然懂這個(gè)配置!
(2)?mybatis方式
mybatis沒(méi)提供這種多租戶(hù)架構(gòu)的支持!我們必須要擴(kuò)展AbstractRoutingDataSource抽象類(lèi),實(shí)現(xiàn)多數(shù)據(jù)源切換!
嫌麻煩?
OK,介紹你一個(gè)插件叫mybatis plus可以實(shí)現(xiàn)這種動(dòng)態(tài)數(shù)據(jù)源切換!
API地址都給你貼出來(lái)了:
https://mp.baomidou.com/guide/dynamic-datasource.html
ps:我只能給你點(diǎn)一下思路,自己去查。因?yàn)榫唧w如何配置,都可以寫(xiě)一篇文章!我很不愛(ài)寫(xiě)這種貼配置的文章,覺(jué)得含金量不高,所以大家根據(jù)我的思路去實(shí)現(xiàn)即可!
方式三
每個(gè)租戶(hù)有共享的服務(wù)和共享的數(shù)據(jù)庫(kù)!
這個(gè)在生產(chǎn)上一般是這么做,如下所示
如圖所示,用戶(hù)在請(qǐng)求的時(shí)候會(huì)經(jīng)過(guò)網(wǎng)關(guān),網(wǎng)關(guān)將數(shù)據(jù)轉(zhuǎn)發(fā)給用戶(hù)服務(wù)!用戶(hù)服務(wù)根據(jù)tenant_id確定操作數(shù)據(jù)庫(kù)中的哪一行記錄!
老規(guī)矩,和你們說(shuō)一下在ORM中難點(diǎn)在哪!以mybatis為例,所有的sql上都要加一句
是不是覺(jué)得很麻煩?怎么解決呢?
(1)?hibernate方式
利用hibernate filter配置, OR-Mapping配置文件使用Filter,可以在進(jìn)行數(shù)據(jù)查詢(xún)時(shí)自動(dòng)過(guò)濾數(shù)據(jù)!
如下所示
ps:看不懂的童鞋略過(guò),懂hibernate的童鞋自然懂這個(gè)配置!
(2)?mybatis方式
mybatis中有一個(gè)東西叫做自定義Interceptor,可以攔截出你要執(zhí)行的sql,然后動(dòng)態(tài)拼上你的租戶(hù)條件即可!
嫌麻煩?
OK,介紹你一個(gè)插件叫mybatis plus可以實(shí)現(xiàn)這種多租戶(hù)的更改,可以動(dòng)態(tài)的解析出sql,增加上條件!
API地址都給你貼出來(lái)了:
https://mp.baomidou.com/guide/tenant.html
?
總結(jié)
本文介紹了服務(wù)隔離的分類(lèi),以及在生產(chǎn)上具體是怎么做的,希望大家有所收獲!
總結(jié)
以上是生活随笔為你收集整理的谈谈怎么做【服务隔离】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 微服务为什么一定要用docker
- 下一篇: 一道泄露并遭禁用的谷歌面试题,背后玄机全