Spring Cloud體系實(shí)現(xiàn)標(biāo)簽路由的方法示例
如果你正在使用Spring Cloud體系,在實(shí)際使用過程中正遇到以下問題,可以閱讀本文章的內(nèi)容作為后續(xù)你解決這些問題的參考,文章內(nèi)容不保證無(wú)錯(cuò),請(qǐng)務(wù)必仔細(xì)思考之后再進(jìn)行實(shí)踐。
問題:
1,本地連上開發(fā)或測(cè)試環(huán)境的集群連調(diào),正常測(cè)試請(qǐng)求可能會(huì)請(qǐng)求到本地,被自己的debug阻塞。
2,測(cè)試環(huán)境維護(hù)時(shí),多項(xiàng)目并發(fā)提測(cè),維護(hù)多個(gè)相同的集群進(jìn)行測(cè)試是否必要,是否有更好的方案。
一般,我們?cè)谑褂肧pring Cloud全家桶的時(shí)候,會(huì)選擇zuul作為網(wǎng)關(guān),Ribbon作為負(fù)載均衡器,F(xiàn)eign作為遠(yuǎn)程服務(wù)調(diào)用模版。使用過Spring Cloud的同學(xué)對(duì)這些組件的作用必然非常熟悉。這里就拿這些組件組合成的微服務(wù)集群來(lái)實(shí)現(xiàn)標(biāo)簽路由的功能。
實(shí)現(xiàn)的效果如圖所示,在頭上帶上標(biāo)簽的請(qǐng)求會(huì)在經(jīng)過網(wǎng)關(guān)和各個(gè)應(yīng)用時(shí)進(jìn)行標(biāo)簽判斷流量應(yīng)該打到哪一個(gè)去,而每一個(gè)應(yīng)用自己本身的標(biāo)簽是通過eureka上的matedate實(shí)現(xiàn)的。
如下圖可以構(gòu)想動(dòng)態(tài)修改標(biāo)簽控制應(yīng)用所能承接的請(qǐng)求,這里暫時(shí)不描述mq部分的功能:
答案:
實(shí)現(xiàn)一個(gè)ZoneAvoidanceRule的繼承類,重寫getPredicate方法:
@Override public AbstractServerPredicate getPredicate() { OfflineEnvMetadataAwarePredicate offlineEnvMetadataAwarePredicate = new OfflineEnvMetadataAwarePredicate(); offlineEnvMetadataAwarePredicate.setEnv(env); return offlineEnvMetadataAwarePredicate; }
Predicate的實(shí)現(xiàn)屏蔽了開發(fā)測(cè)試環(huán)境中非這個(gè)環(huán)境網(wǎng)段啟動(dòng)的應(yīng)用,并且比對(duì)請(qǐng)求的標(biāo)簽和本地的標(biāo)簽,來(lái)控制路由給哪一個(gè)服務(wù)器。
@Override public AbstractServerPredicate getPredicate() { OfflineEnvMetadataAwarePredicate offlineEnvMetadataAwarePredicate = new OfflineEnvMetadataAwarePredicate(); offlineEnvMetadataAwarePredicate.setEnv(env); return offlineEnvMetadataAwarePredicate; }
那么我們注意到請(qǐng)求頭上的標(biāo)簽要在初始時(shí)就拿到,所以需要一個(gè)ServletRequestListener,將拿到的zone放入RequestZoneLabelContext。我們知道在一個(gè)請(qǐng)求中如果是一個(gè)io線程執(zhí)行到底,我們只需要利用threadlocal來(lái)存儲(chǔ)線程變量,可是如果一個(gè)請(qǐng)求中會(huì)產(chǎn)生不定的子線程完成,數(shù)據(jù)在線程間的傳遞就成為問題,這里使用了InheritableThreadLocal來(lái)決解,在RequestZoneLabelContext中可以看到。
public class RequestZoneLabelContextListener implements ServletRequestListener { private static final String ZONE_LABEL_NAME = "zone"; @Override public void requestDestroyed(ServletRequestEvent sre) { RequestZoneLabelContext.remove(); } @Override public void requestInitialized(ServletRequestEvent requestEvent) { HttpServletRequest request = (HttpServletRequest)requestEvent.getServletRequest(); String lbZone = request.getHeader(ZONE_LABEL_NAME); if(StringUtils.isNotBlank(lbZone)){ RequestZoneLabelContext.setZone(lbZone); } } }
/** * 從request header上傳遞label到feign請(qǐng)求 */ public class RequestZoneLabelContext { private static InheritableThreadLocal<String> zoneLabelThreadLocal = new InheritableThreadLocal<>(); public static void setZone(String zone){ zoneLabelThreadLocal.set(zone); } public static String getRequestZone(){ return zoneLabelThreadLocal.get(); } public static void remove(){ zoneLabelThreadLocal.remove(); } }
那么在應(yīng)用之間調(diào)用的feign中我們是需要繼續(xù)把這個(gè)zone通過header傳遞下去的,所以又?jǐn)U展了RequestInterceptor:
public class FeignZoneHeaderInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { String requestZone = RequestZoneLabelContext.getRequestZone(); if(StringUtils.isNotBlank(requestZone)){ template.header("zone", requestZone); } } }
至此就基本實(shí)現(xiàn)了最初的想法。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java中使用雪花算法(Snowflake)為分布式系統(tǒng)生成全局唯一ID代碼示例
Java雪花算法是一種用于生成唯一ID的算法,它可以在分布式系統(tǒng)中生成全局唯一的ID,這篇文章主要給大家介紹了關(guān)于java中使用雪花算法(Snowflake)為分布式系統(tǒng)生成全局唯一ID的相關(guān)資料,需要的朋友可以參考下2024-07-07SpringBoot整合Xxl-job實(shí)現(xiàn)定時(shí)任務(wù)的全過程
XXL-JOB是一個(gè)分布式任務(wù)調(diào)度平臺(tái),其核心設(shè)計(jì)目標(biāo)是開發(fā)迅速、學(xué)習(xí)簡(jiǎn)單、輕量級(jí)、易擴(kuò)展,下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合Xxl-job實(shí)現(xiàn)定時(shí)任務(wù)的相關(guān)資料,需要的朋友可以參考下2022-01-01Springboot?No?bean?named?'XXXXX'?available?問
這篇文章主要介紹了Springboot?No?bean?named?'XXXXX'?available?問題解決方法,解決方法也很簡(jiǎn)單,盡量規(guī)范類的命名,注解中指定bean名稱,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07關(guān)于Spring?Data?Jpa?自定義方法實(shí)現(xiàn)問題
這篇文章主要介紹了關(guān)于Spring?Data?Jpa?自定義方法實(shí)現(xiàn)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Mybatis-Plus開發(fā)提速器mybatis-plus-generator-ui詳解
這篇文章主要介紹了Mybatis-Plus開發(fā)提速器mybatis-plus-generator-ui,本文簡(jiǎn)要介紹一款基于Mybatis-Plus的代碼自助生成器,文章通過實(shí)例集成的方式來(lái)詳細(xì)講解mybatis-plus-generator-ui,從相關(guān)概念到實(shí)際集成案例,以及具體的擴(kuò)展開發(fā)介紹,需要的朋友可以參考下2022-11-11java阻塞隊(duì)列實(shí)現(xiàn)原理及實(shí)例解析
這篇文章主要介紹了java阻塞隊(duì)列實(shí)現(xiàn)原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Java動(dòng)態(tài)修改配置即時(shí)生效的方式WatchService
這篇文章給大家分享了Java動(dòng)態(tài)修改配置即時(shí)生效的方式WatchService的相關(guān)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友可以參考學(xué)習(xí)下。2018-06-06SpringMVC項(xiàng)目訪問controller時(shí)候報(bào)404的解決
這篇文章主要介紹了SpringMVC項(xiàng)目訪問controller時(shí)候報(bào)404的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09