溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何解決Spring Cloud 服務(wù)沖突問題

發(fā)布時間:2021-12-08 10:25:05 來源:億速云 閱讀:135 作者:柒染 欄目:大數(shù)據(jù)

本篇文章為大家展示了如何解決Spring Cloud 服務(wù)沖突問題,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

一、背景

在我們開發(fā)微服務(wù)架構(gòu)系統(tǒng)時,雖然說每個微服務(wù)都是孤立的可以單獨開發(fā),但實際上并非如此,要調(diào)試和測試你的服務(wù)不僅需要您的微服務(wù)啟動和運行,還需要它的上下文服務(wù)、依賴的基礎(chǔ)服務(wù)等都要運行;但如果你的系統(tǒng)服務(wù)數(shù)和依賴比較多呢,那就是一個比較棘手的問題!有沒有辦法能提高開發(fā)效率呢?

如何解決Spring Cloud 服務(wù)沖突問題

如上圖所示,我們能不能用服務(wù)器把所有的服務(wù)都部署起來,然后開發(fā)只在本地運行自己所負責(zé)開發(fā)的服務(wù),因為需要依賴其他服務(wù)所以本地啟動的服務(wù)也需要注冊到公共的注冊中心里;

例子中業(yè)務(wù)服務(wù)B有3臺實例注冊到注冊中心里

分別是:服務(wù)上的、開發(fā)A與開發(fā)B自己本機啟動的

但是這樣做又會出現(xiàn)新的問題:服務(wù)會沖突亂竄,意思就是開發(fā)A在debug自己的業(yè)務(wù)服務(wù)B服務(wù)的時候可能請求會跳轉(zhuǎn)到其他人的實例上(服務(wù)器、開發(fā)B)

二、解決思路

解決這個服務(wù)亂竄問題有一個比較優(yōu)雅的方式就是自定義負載均衡規(guī)則,主要實現(xiàn)以下目標(biāo):

  1. 普通用戶訪問服務(wù)器上的頁面時,請求的所有路由只調(diào)用服務(wù)器上的實例

  2. 開發(fā)A訪問時,請求的所有路由優(yōu)先調(diào)用開發(fā)A本機啟動的實例,如果沒有則調(diào)用服務(wù)器上的實例

  3. 開發(fā)B訪問時同上,請求的所有路由優(yōu)先調(diào)用開發(fā)B本機啟動的實例,如果沒有則調(diào)用服務(wù)器上的實例

三、具體實現(xiàn)

要實現(xiàn)上面的目標(biāo)有兩個比較關(guān)鍵的問題需要解決

  1. 區(qū)分不同用戶的服務(wù)實例

  2. 實現(xiàn)自定義負載均衡規(guī)則

3.1. 區(qū)分不同用戶的服務(wù)實例

直接使用注冊中心的元數(shù)據(jù)(metadata)來區(qū)分就可以了

主流的注冊中心都帶有元數(shù)據(jù)管理

以Nacos為例,只需要在配置文件下添加

spring:
 cloud:
 nacos:
 discovery:
 server-addr: localhost:8848
 metadata:
 version: zlt

metadata下的version就是我添加的元數(shù)據(jù)key為version,value為zlt

啟動服務(wù)后元數(shù)據(jù)就會注冊上去,如下圖

如何解決Spring Cloud 服務(wù)沖突問題

經(jīng)過元數(shù)據(jù)區(qū)分后,目前是下面這個情況

  • 服務(wù)器的實例version為空

  • 開發(fā)人員自己本地啟動的實例version為唯一標(biāo)識(自己的名字)

如何解決Spring Cloud 服務(wù)沖突問題

3.2. 自定義負載均衡規(guī)則

首先在Spring Cloud微服務(wù)框架里實例的負載均衡是由Ribbon負責(zé)。

CustomIsolationRule詳細類信息可查看:CustomIsolationRule.java

public class CustomIsolationRule extends RoundRobinRule {
 /**
 * 優(yōu)先根據(jù)版本號取實例
 */
 @Override
 public Server choose(ILoadBalancer lb, Object key) {
 if (lb == null) {
 return null;
 }
 String version = LbIsolationContextHolder.getVersion();
 List<Server> targetList = null;
 List<Server> upList = lb.getReachableServers();
 if (StrUtil.isNotEmpty(version)) {
 //取指定版本號的實例
 targetList = upList.stream().filter(
 server -> version.equals(
 ((NacosServer) server).getMetadata().get(CommonConstant.METADATA_VERSION)
 )
 ).collect(Collectors.toList());
 }
 if (CollUtil.isEmpty(targetList)) {
 //只取無版本號的實例
 targetList = upList.stream().filter(
 server -> {
 String metadataVersion = ((NacosServer) server).getMetadata().get(CommonConstant.METADATA_VERSION);
 return StrUtil.isEmpty(metadataVersion);
 }
 ).collect(Collectors.toList());
 }
 if (CollUtil.isNotEmpty(targetList)) {
 return getServer(targetList);
 }
 return super.choose(lb, key);
 }
 /**
 * 隨機取一個實例
 */
 private Server getServer(List<Server> upList) {
 int nextInt = RandomUtil.randomInt(upList.size());
 return upList.get(nextInt);
 }
}

集成輪詢規(guī)則RoundRobinRule來實現(xiàn),主要的邏輯為

  • 根據(jù)上游輸入的版本號version,有值的話則取服務(wù)元信息中version值一樣的實例

  • 上游的版本號version沒值或者該版本號匹配不到任何服務(wù),則只取服務(wù)元信息中version值為空的實例

并通過配置開關(guān)控制是否開啟自定義負載規(guī)則

@Configuration
@ConditionalOnProperty(value = "zlt.ribbon.isolation.enabled", havingValue = "true")
@RibbonClients(defaultConfiguration = {RuleConfigure.class})
public class LbIsolationConfig {
}

四、總結(jié)

上面提到的區(qū)分服務(wù)實例和自定義負載規(guī)則為整個解決思路的核心點,基本實現(xiàn)了服務(wù)實例的隔離,剩下要做的就是上游的version怎樣傳遞呢?,下面我提供兩個思路

  • 開發(fā)人員自己啟動前端工程,通過配置參數(shù),統(tǒng)一在前端工程傳遞version

  • 通過postman調(diào)用接口的時候在header參數(shù)中添加

如何解決Spring Cloud 服務(wù)沖突問題

上述內(nèi)容就是如何解決Spring Cloud 服務(wù)沖突問題,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI