本篇文章為大家展示了如何解決Spring Cloud 服務沖突問題,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
創(chuàng)新互聯(lián)是一家集網(wǎng)站建設,莒南企業(yè)網(wǎng)站建設,莒南品牌網(wǎng)站建設,網(wǎng)站定制,莒南網(wǎng)站建設報價,網(wǎng)絡營銷,網(wǎng)絡優(yōu)化,莒南網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。
一、背景
在我們開發(fā)微服務架構系統(tǒng)時,雖然說每個微服務都是孤立的可以單獨開發(fā),但實際上并非如此,要調(diào)試和測試你的服務不僅需要您的微服務啟動和運行,還需要它的上下文服務、依賴的基礎服務等都要運行;但如果你的系統(tǒng)服務數(shù)和依賴比較多呢,那就是一個比較棘手的問題!有沒有辦法能提高開發(fā)效率呢?
如上圖所示,我們能不能用服務器把所有的服務都部署起來,然后開發(fā)只在本地運行自己所負責開發(fā)的服務,因為需要依賴其他服務所以本地啟動的服務也需要注冊到公共的注冊中心里;
例子中業(yè)務服務B有3臺實例注冊到注冊中心里
分別是:服務上的、開發(fā)A與開發(fā)B自己本機啟動的
但是這樣做又會出現(xiàn)新的問題:服務會沖突亂竄,意思就是開發(fā)A在debug自己的業(yè)務服務B服務的時候可能請求會跳轉到其他人的實例上(服務器、開發(fā)B)
二、解決思路
解決這個服務亂竄問題有一個比較優(yōu)雅的方式就是自定義負載均衡規(guī)則,主要實現(xiàn)以下目標:
普通用戶訪問服務器上的頁面時,請求的所有路由只調(diào)用服務器上的實例
開發(fā)A訪問時,請求的所有路由優(yōu)先調(diào)用開發(fā)A本機啟動的實例,如果沒有則調(diào)用服務器上的實例
開發(fā)B訪問時同上,請求的所有路由優(yōu)先調(diào)用開發(fā)B本機啟動的實例,如果沒有則調(diào)用服務器上的實例
三、具體實現(xiàn)
要實現(xiàn)上面的目標有兩個比較關鍵的問題需要解決
區(qū)分不同用戶的服務實例
實現(xiàn)自定義負載均衡規(guī)則
3.1. 區(qū)分不同用戶的服務實例
直接使用注冊中心的元數(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
啟動服務后元數(shù)據(jù)就會注冊上去,如下圖
經(jīng)過元數(shù)據(jù)區(qū)分后,目前是下面這個情況
服務器的實例version為空
開發(fā)人員自己本地啟動的實例version為唯一標識(自己的名字)
3.2. 自定義負載均衡規(guī)則
首先在Spring Cloud微服務框架里實例的負載均衡是由Ribbon負責。
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(); ListtargetList = null; List 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 upList) { int nextInt = RandomUtil.randomInt(upList.size()); return upList.get(nextInt); } }
集成輪詢規(guī)則RoundRobinRule來實現(xiàn),主要的邏輯為
根據(jù)上游輸入的版本號version,有值的話則取服務元信息中version值一樣的實例
上游的版本號version沒值或者該版本號匹配不到任何服務,則只取服務元信息中version值為空的實例
并通過配置開關控制是否開啟自定義負載規(guī)則
@Configuration @ConditionalOnProperty(value = "zlt.ribbon.isolation.enabled", havingValue = "true") @RibbonClients(defaultConfiguration = {RuleConfigure.class}) public class LbIsolationConfig { }
四、總結
上面提到的區(qū)分服務實例和自定義負載規(guī)則為整個解決思路的核心點,基本實現(xiàn)了服務實例的隔離,剩下要做的就是上游的version怎樣傳遞呢?,下面我提供兩個思路
開發(fā)人員自己啟動前端工程,通過配置參數(shù),統(tǒng)一在前端工程傳遞version
通過postman調(diào)用接口的時候在header參數(shù)中添加
上述內(nèi)容就是如何解決Spring Cloud 服務沖突問題,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。