欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Cloud Alibaba 本地調(diào)試介紹及方案設(shè)計(jì)

 更新時(shí)間:2021年07月13日 09:39:20   作者:isea533  
為了解決 本地調(diào)試 的問題,本文實(shí)現(xiàn)了一種簡單實(shí)用的策略,可以通過 Nacos 動(dòng)態(tài)配置服務(wù)路由,還可以基于用戶,部門,組織等級(jí)別配置服務(wù)路由,實(shí)現(xiàn) 本地調(diào)試 的同時(shí),實(shí)際上也實(shí)現(xiàn) 灰度發(fā)布,感興趣的朋友跟隨小編一起看看吧

1 本地調(diào)試介紹

本地調(diào)試: 這里是指在開發(fā)環(huán)境中,部署了一整套的某個(gè)項(xiàng)目或者產(chǎn)品的服務(wù),開發(fā)人員開發(fā)時(shí),本地會(huì)起一個(gè)或多個(gè)服務(wù),這些服務(wù)和開發(fā)環(huán)境中部署的服務(wù)是相同的,這種情況下,一個(gè)服務(wù)就會(huì)有多個(gè)實(shí)例,大多數(shù)微服務(wù)中的默認(rèn)負(fù)載均衡策略都是輪詢,這些實(shí)例會(huì)輪流被調(diào)用。

為了方便 本地調(diào)試,需要提供一種策略,可以指定在負(fù)載均衡時(shí),選擇哪個(gè)實(shí)例進(jìn)行調(diào)用。在使用 Nacos 作為注冊(cè)中心時(shí),可以通過 上線和下線 的方式來選擇使用哪個(gè)實(shí)例,但是這種方式只能強(qiáng)制調(diào)用某個(gè)實(shí)例,如果開發(fā)環(huán)境還有其他人在調(diào)試,自己程序 設(shè)置斷點(diǎn) 時(shí)會(huì)阻塞所有調(diào)用,非常不利于多人調(diào)試的協(xié)調(diào)。

為了解決 本地調(diào)試 的問題,本文實(shí)現(xiàn)了一種簡單實(shí)用的策略,可以通過 Nacos 動(dòng)態(tài)配置服務(wù)路由,還可以基于用戶,部門,組織等級(jí)別配置服務(wù)路由,實(shí)現(xiàn) 本地調(diào)試 的同時(shí),實(shí)際上也實(shí)現(xiàn) 灰度發(fā)布。

2 框架環(huán)境

本文基于 Spring Cloud Alibaba 框架,和 Spring Cloud 相比增加了一部分針對(duì) Dubbo 的方案,因此本文適合以下框架參考:

  • Spring Cloud Alibaba
  • Spring Cloud

Spring Cloud Gateway
Spring Cloud Ribbon

  • Dubbo

下圖是 Spring Cloud Alibaba 框架中,一次方法調(diào)用的可能情況,Ailbaba 這部分多的是圖中 ServiceA -> ServiceB 部分使用 Dubbo 協(xié)議。Spring Cloud 框架中,用的是 ServiceA -> ServiceC 這種 Feign(HTTP) 方式。

在這里插入圖片描述

圖中的所有過濾器和攔截器,雖然名稱不同,但是作用相同。這部分的主要作用就是 獲取或傳遞路由規(guī)則,例如,可以實(shí)現(xiàn)基于 HTTP Header 設(shè)置路由規(guī)則的配置,可以基于 HTTP 和 token 實(shí)現(xiàn)基于用戶的路由規(guī)則配置,這部分的實(shí)現(xiàn)和需求有關(guān),沒有統(tǒng)一的實(shí)現(xiàn)。

3 方案設(shè)計(jì)

這里以這兩種場景簡單舉個(gè)例子。

3.1 基于 HTTP Header 的本地調(diào)試方案

在這個(gè)方案中,按照上面的流程圖敘述一遍。

  1. 用戶調(diào)用服務(wù)前,在 Header 中設(shè)置調(diào)用規(guī)則,比如增加 service-route 請(qǐng)求頭,請(qǐng)求頭的內(nèi)容為 servicea:10.10.10.130;serviceb:10.10.10.100;servicec:10.10.10.0/24,在請(qǐng)求頭中指明需要控制路由的服務(wù)信息(不需要控制的直接省略走默認(rèn))。
  2. 通過 Spring Cloud Gateway 的 GlobalFilter 實(shí)現(xiàn)提取請(qǐng)求頭信息,將配置信息記錄下來(如 ThreadLocal
  3. 負(fù)載均衡時(shí),根據(jù)這里的配置選擇優(yōu)先路由的服務(wù),調(diào)用 ServiceA 時(shí),仍然是 HTTP 請(qǐng)求,請(qǐng)求頭會(huì)傳遞過去。
  4. 攔截器獲取請(qǐng)求頭中的路由規(guī)則,這一步和 1 類似,但是屬于 Spring MVC 的攔截器,獲取路由規(guī)則后記錄下來(如 ThreadLocal
  5. ServiceA 調(diào)用 ServiceB 是 Dubbo 協(xié)議的路徑,和 7,8 Feign 方式?jīng)]有先后順序,是兩個(gè)分支。 在 4 這一步通過 Dubbo 的 Consumer Filter 過濾器和 RpcContext 將路由信息記錄到 attachment 中,這樣可以把路由配置傳遞到 ServiceB,如果 ServiceB 還需要調(diào)用其他服務(wù),路由仍然會(huì)起到作用。
  6. 在 Dubbo 的 Router 實(shí)現(xiàn)中,根據(jù)路由信息選擇優(yōu)先調(diào)用的服務(wù),然后進(jìn)行調(diào)用。
  7. Dubbo 的 Provider Filter 從 RpcContext 獲取路由配置,記錄下來(如 ThreadLocal),如果后續(xù)調(diào)用其他服務(wù),邏輯和 4,5,6一樣。在 6 這一步的 Provider Filter 結(jié)束調(diào)用的時(shí)候,注意清空路由信息(如 ThreadLocal.clear()),避免對(duì)其他調(diào)用產(chǎn)生污染。
  8. 這一步和4,5,6沒有順序關(guān)系,是純 Spring Cloud 方式的調(diào)用,在 ServiceA 調(diào)用時(shí),通過自定義 Ribbon 中的 IRule 實(shí)現(xiàn)基于自己路由規(guī)則的調(diào)用。
  9. 在最終調(diào)用 ServiceC 之前,通過 Feign 的 RequestInterceptor 攔截器添加 service-route 頭,將服務(wù)路由傳遞下去。
  10. 和第3步相同,通過 Spring MVC 攔截器獲取服務(wù)路由記錄下來。后續(xù)在調(diào)用其他服務(wù)時(shí),Dubbo服務(wù)走4,5,6,F(xiàn)eign方式走7,8,9。

3.2 基于操作用戶的本地調(diào)試方案

基于操作用戶的方案中,和上面類似,但是不需要在每次請(qǐng)求的時(shí)候設(shè)置 HTTP Header,但是需要一種方式存取服務(wù)路由的配置。

這里以使用 Nacos 配置管理實(shí)現(xiàn)服務(wù)路由配置的存取。

根據(jù)自己使用的用戶在 Nacos 配置服務(wù)路由,配置名規(guī)則如 服務(wù)名.user-routes,使用 Spring Cloud Alibaba 的默認(rèn)組 dubbo,用戶服務(wù)路由的配置規(guī)則可以自己定義,這里舉個(gè)簡單例子:

enabled: true # 啟用,停用
ip: 10.10.0.0/24 # 默認(rèn)優(yōu)先IP或網(wǎng)段,所有IP都支持具體IP和網(wǎng)段
userIps: # Map<Long, String>,優(yōu)先級(jí)最高,針對(duì)用戶配置 IP 優(yōu)先
  # userId: IP 
  1: 10.10.0.100
  2: 10.10.0.101
# 這部分定義根據(jù)自己需要設(shè)計(jì)  
deptIps: # 針對(duì)部門配置
  # deptId: IP
  1: 10.10.0.0/24
orgIps: # 針對(duì)組織配置
  # orgId: IP
  1: 10.10.10.0/24

Spring Cloud Gateway 的 GlobalFilter 根據(jù)請(qǐng)求 token 獲取 用戶信息,記錄用戶信息(如 ThreadLocal)。

  1. 負(fù)載均衡時(shí),使用 Nacos ConfigService,根據(jù) 服務(wù)名.user-routes 查詢配置信息,同時(shí)監(jiān)聽該配置信息,根據(jù)這里的配置選擇優(yōu)先路由的服務(wù)。
  2. 攔截器根據(jù)請(qǐng)求 token 獲取 用戶信息,記錄用戶信息(如 ThreadLocal)。
  3. ServiceA 調(diào)用 ServiceB 是 Dubbo 協(xié)議的路徑,和 7,8 Feign 方式?jīng)]有先后順序,是兩個(gè)分支。 在 4 這一步通過 Dubbo 的 Consumer Filter 過濾器和 RpcContext 將用戶信息記錄到 attachment 中,這樣可以把用戶信息傳遞到 ServiceB,如果 ServiceB 還需要調(diào)用其他服務(wù),用戶信息仍然會(huì)起到作用。
  4. 在 Dubbo 的 Router 實(shí)現(xiàn)中,根據(jù)路由信息選擇優(yōu)先調(diào)用的服務(wù),然后進(jìn)行調(diào)用。
  5. Dubbo 的 Provider Filter 從 RpcContext 獲取用戶信息,記錄下來(如 ThreadLocal),如果后續(xù)調(diào)用其他服務(wù),邏輯和 4,5,6一樣。在 6 這一步的 Provider Filter 結(jié)束調(diào)用的時(shí)候,注意清空用戶信息(如 ThreadLocal.clear()),避免對(duì)其他調(diào)用產(chǎn)生污染。
  6. 這一步和4,5,6沒有順序關(guān)系,是純 Spring Cloud 方式的調(diào)用,在 ServiceA 調(diào)用時(shí),通過自定義 Ribbon 中的 IRule 實(shí)現(xiàn)基于自己路由規(guī)則的調(diào)用。
  7. 在最終調(diào)用 ServiceC 之前,通過 Feign 的 RequestInterceptor 攔截器設(shè)置token或用戶信息,將操作用戶傳遞下去。
  8. 和第3步相同,通過 Spring MVC 攔截器獲取用戶信息記錄下來。后續(xù)在調(diào)用其他服務(wù)時(shí),Dubbo服務(wù)走4,5,6,F(xiàn)eign方式走7,8,9。

本文選擇第 2 種方案,針對(duì) 1~9 步,分別講解需要實(shí)現(xiàn)的接口和接口應(yīng)用(生效)的配置。

4 實(shí)現(xiàn)要點(diǎn)

上面提到的 ThreadLocal,實(shí)現(xiàn)時(shí)使用一個(gè) static 變量存儲(chǔ),提供相應(yīng)的存取清空的靜態(tài)方法,方便跨接口的 用戶信息 傳遞。

4.1 Spring Cloud Gateway 全局過濾器

假設(shè)有一個(gè) UserGlobalFilter,該過濾器根據(jù) token 獲取并緩存用戶信息,在請(qǐng)求完成后需要清空緩存的用戶信息。

Spring Cloud Gateway 中的過濾器,直接在 @Configuration 的配置類中用 @Bean 提供即可。

4.2 Ribbon 負(fù)載均衡

實(shí)現(xiàn) ribbon-loadbalancer 中的 com.netflix.loadbalancer.IRule 接口,將來調(diào)用具體服務(wù)時(shí)通過 choose 接口返回符合條件的實(shí)例。

實(shí)現(xiàn)這個(gè)接口之后,需要特殊的方式注冊(cè)該接口,在啟動(dòng)類增加注解 @RibbonClients(defaultConfiguration = UserRuleConfiguration.class),
注解中指定了一個(gè)配置類,這個(gè)類一定不要添加 @Configuration 注解?。。?/strong>。

在這個(gè)類中,通過 @Bean 注解返回一個(gè) IRule 接口的實(shí)現(xiàn)。

在 Ribbon 中,會(huì)創(chuàng)建一個(gè)新的 ApplicationContext 來初始化這些配置,在這個(gè)新的 ApplicationContext 中,配置的 IRule 實(shí)現(xiàn)會(huì)被使用。

4.3 Spring MVC 攔截器

實(shí)現(xiàn) HandlerInterceptor 攔截器,從請(qǐng)求獲取用戶信息并記錄下來。

攔截器想要生效,需要提供一個(gè)配置類,繼承 WebMvcConfigurer 接口,實(shí)現(xiàn) addInterceptors 方法,在這個(gè)方法實(shí)現(xiàn)中添加攔截器的實(shí)現(xiàn)類。

4.4 Dubbo Consumer Filter 過濾器

實(shí)現(xiàn)Dubbo 的Filter接口,通過 RpcContext 傳遞前面記錄的用戶信息。

可以在實(shí)現(xiàn)類添加 @Activate 注解,指定 groupCommonConstants.CONSUMER。

按照 dubbo SPI 要求,添加 META-INF/dubbo/org.apache.dubbo.rpc.Filter 文件,寫上實(shí)現(xiàn)類。

4.5 Dubbo Router 路由

這一步實(shí)際上可以放在 Dubbo 負(fù)載均衡實(shí)現(xiàn),也可以用 Router 實(shí)現(xiàn)。

使用 Router 時(shí),需要同時(shí)使用 RouterFactoryRouter 接口,然后配置 RouterFactory 的 SPI 配置文件。

Routerroute 方法中根據(jù)規(guī)則返回合適的 Invoker。

4.6 Dubbo Provider Filter 過濾器

實(shí)現(xiàn)Dubbo 的Filter接口,通過 RpcContext 獲取傳遞過來的用戶信息。

可以在實(shí)現(xiàn)類添加 @Activate 注解,指定 groupCommonConstants.PROVIDER。

按照 dubbo SPI 要求,添加 META-INF/dubbo/org.apache.dubbo.rpc.Filter 文件,寫上實(shí)現(xiàn)類。

這個(gè)實(shí)現(xiàn)類可以和 4.4 的放一個(gè) Filter 實(shí)現(xiàn)中,需要自己區(qū)分當(dāng)前是 consumer 還是 provider 實(shí)現(xiàn)不同的邏輯。

4.7 Ribbon 負(fù)載均衡,同 4.2

這一步的實(shí)現(xiàn)和 4.2 一樣,4.2 是用在 Spring Cloud Gateway 中,這里是配置到具體的服務(wù)中。配置方式一樣。

4.8 Feign RequestInterceptor 攔截器

首先實(shí)現(xiàn) RequestInterceptor 接口,在實(shí)現(xiàn)中往 requst 的 Header 中放置要傳遞的數(shù)據(jù)。

接口想要生效,需要和 Ribbon 類似的配置。

@EnableFeignClients 的注解中,通過 defaultConfiguration 設(shè)置一個(gè) Feign 的配置類。在這個(gè)配置中通過 @Bean 提供 RequestInterceptor 接口的實(shí)現(xiàn)。

4.9 Spring MVC 攔截器,同 4.3

4.3 中是網(wǎng)關(guān)調(diào)用服務(wù),4.9是服務(wù)通過 Feign (或resttemplate)調(diào)用服務(wù),對(duì)被調(diào)用的服務(wù)來說都是 HTTP 請(qǐng)求,因此都會(huì)執(zhí)行 Spring MVC 的攔截器,所以這里的實(shí)現(xiàn)是一樣的。

5. 總結(jié)

本文提供了本地調(diào)試的方案和主要的實(shí)現(xiàn)要點(diǎn),可以根據(jù)文中的關(guān)鍵指引和自己的實(shí)際需求實(shí)現(xiàn)自己的方案。關(guān)于本地調(diào)試如果有更好的方案,歡迎留言討論。

附:工具方法

判斷IP是否相等或輸入子網(wǎng)IP的方法:

public static boolean ipInRange(String ip, String cidr) {
	if(cidr.indexOf('/') < 0) {
		return ip.equals(cidr);
	}
	int ipAddr = ipToInt(ip);
	int type = Integer.parseInt(cidr.replaceAll(".*/", ""));
	String cidrIp = cidr.replaceAll("/.*", "");
	if(type == 32){
		return ip.equals(cidrIp);
	}
	int cidrIpAddr = ipToInt(cidrIp);
	int mask = 0xFFFFFFFF << (32 - type);
	return (ipAddr & mask) == (cidrIpAddr & mask);
}

public static int ipToInt(String ip) {
	String[] ips = ip.split("\\.");
	return (Integer.parseInt(ips[0] << 24) |
			Integer.parseInt(ips[1] << 16) |
			Integer.parseInt(ips[2] << 8) |
			Integer.parseInt(ips[3]));
}

到此這篇關(guān)于Spring Cloud Alibaba 本地調(diào)試方案的文章就介紹到這了,更多相關(guān)Spring Cloud Alibaba 本地調(diào)試內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java Mail郵件發(fā)送如何實(shí)現(xiàn)簡單封裝

    Java Mail郵件發(fā)送如何實(shí)現(xiàn)簡單封裝

    這篇文章主要介紹了Java Mail郵件發(fā)送如何實(shí)現(xiàn)簡單封裝,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • IntelliJ IDEA失焦自動(dòng)重啟服務(wù)的解決方法

    IntelliJ IDEA失焦自動(dòng)重啟服務(wù)的解決方法

    在使用 IntelliJ IDEA運(yùn)行 SpringBoot 項(xiàng)目時(shí),你可能會(huì)遇到一個(gè)令人困擾的問題,一旦你的鼠標(biāo)指針離開當(dāng)前IDE窗口,點(diǎn)擊其他位置時(shí), IDE 窗口會(huì)失去焦點(diǎn),你的 SpringBoot 服務(wù)就會(huì)自動(dòng)重啟,所以本文給大家介紹了IntelliJ IDEA失焦自動(dòng)重啟服務(wù)的解決方法
    2023-10-10
  • java多線程編程之java線程簡介

    java多線程編程之java線程簡介

    線程是程序運(yùn)行的基本執(zhí)行單元,線程不僅可以共享進(jìn)程的內(nèi)存,而且還擁有一個(gè)屬于自己的內(nèi)存空間,這段內(nèi)存空間也叫做線程棧
    2014-01-01
  • java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實(shí)現(xiàn)

    java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實(shí)現(xiàn)

    這篇文章主要介紹了java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • jstack和線程dump實(shí)例解析

    jstack和線程dump實(shí)例解析

    這篇文章主要介紹了jstack和線程dump實(shí)例解析,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • Java創(chuàng)建線程池為什么一定要用ThreadPoolExecutor

    Java創(chuàng)建線程池為什么一定要用ThreadPoolExecutor

    本文介紹了Java創(chuàng)建線程池為什么一定要用ThreadPoolExecutor,手動(dòng)方式使用ThreadPoolExecutor創(chuàng)建線程池和使用Executors執(zhí)行器自動(dòng)創(chuàng)建線程池,下文更多相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2022-05-05
  • Spring?cloud負(fù)載均衡@LoadBalanced?&?LoadBalancerClient

    Spring?cloud負(fù)載均衡@LoadBalanced?&?LoadBalancerClient

    由于Spring?cloud2020之后移除了Ribbon,直接使用Spring?Cloud?LoadBalancer作為客戶端負(fù)載均衡組件,我們討論Spring負(fù)載均衡以Spring?Cloud2020之后版本為主,學(xué)習(xí)Spring?Cloud?LoadBalance
    2023-11-11
  • Spring注解驅(qū)動(dòng)開發(fā)實(shí)現(xiàn)屬性賦值

    Spring注解驅(qū)動(dòng)開發(fā)實(shí)現(xiàn)屬性賦值

    這篇文章主要介紹了Spring注解驅(qū)動(dòng)開發(fā)實(shí)現(xiàn)屬性賦值,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Java中Lombok常用注解分享

    Java中Lombok常用注解分享

    以前的Java項(xiàng)目中充斥了太多不友好的代碼,這些代碼不僅沒有什么技術(shù)含量,還影響代碼的美觀,所以Lombok應(yīng)運(yùn)而生了。本文和大家分享了一些Java中Lombok常用注解,需要的可以了解一下
    2023-04-04
  • JVM類加載之雙親委派機(jī)制解讀

    JVM類加載之雙親委派機(jī)制解讀

    這篇文章主要介紹了JVM類加載之雙親委派機(jī)制解讀,類加載階段分為加載、連接、初始化三個(gè)階段,而加載階段需要通過類的全限定名來獲取定義了此類的二進(jìn)制字節(jié)流,Java特意把這一步抽出來用類加載器來實(shí)現(xiàn),需要的朋友可以參考下
    2023-12-12

最新評(píng)論