最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

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

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

2 框架環(huán)境

本文基于 Spring Cloud Alibaba 框架,和 Spring Cloud 相比增加了一部分針對 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ī)則,例如,可以實現(xiàn)基于 HTTP Header 設置路由規(guī)則的配置,可以基于 HTTP 和 token 實現(xiàn)基于用戶的路由規(guī)則配置,這部分的實現(xiàn)和需求有關,沒有統(tǒng)一的實現(xiàn)。

3 方案設計

這里以這兩種場景簡單舉個例子。

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

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

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

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

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

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

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

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

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

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

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

4 實現(xiàn)要點

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

4.1 Spring Cloud Gateway 全局過濾器

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

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

4.2 Ribbon 負載均衡

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

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

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

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

4.3 Spring MVC 攔截器

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

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

4.4 Dubbo Consumer Filter 過濾器

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

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

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

4.5 Dubbo Router 路由

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

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

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

4.6 Dubbo Provider Filter 過濾器

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

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

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

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

4.7 Ribbon 負載均衡,同 4.2

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

4.8 Feign RequestInterceptor 攔截器

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

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

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

4.9 Spring MVC 攔截器,同 4.3

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

5. 總結(jié)

本文提供了本地調(diào)試的方案和主要的實現(xiàn)要點,可以根據(jù)文中的關鍵指引和自己的實際需求實現(xià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]));
}

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

相關文章

  • Java抽象類、繼承及多態(tài)和適配器的實現(xiàn)代碼

    Java抽象類、繼承及多態(tài)和適配器的實現(xiàn)代碼

    這篇文章主要介紹了Java抽象類、繼承及多態(tài)和適配器的實現(xiàn),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-06-06
  • springboot遠程debug調(diào)試全過程

    springboot遠程debug調(diào)試全過程

    這篇文章主要介紹了springboot遠程debug調(diào)試全過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • java導出csv方法實現(xiàn)講解

    java導出csv方法實現(xiàn)講解

    這篇文章主要介紹了java導出csv的方法,客戶要求在項目中有導出CSV文件的功能,并且給出了如何在不知道如何在不知道對象類型(沒有應用泛型)的List中如何得到對象的屬性值,下面就詳細說下這個功能是如何實現(xiàn)的
    2013-12-12
  • 一場由Java中Integer引發(fā)的踩坑實戰(zhàn)

    一場由Java中Integer引發(fā)的踩坑實戰(zhàn)

    Java中的數(shù)據(jù)類型分為基本數(shù)據(jù)類型和復雜數(shù)據(jù)類型int是前者而integer是后者(也就是一個類),下面這篇文章主要給大家介紹了關于由Java中Integer引發(fā)的踩坑實戰(zhàn),需要的朋友可以參考下
    2022-11-11
  • 關于springboot中的SPI機制

    關于springboot中的SPI機制

    這篇文章主要介紹了springboot中的SPI機制,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Spring?Data?JPA系列QueryByExampleExecutor使用詳解

    Spring?Data?JPA系列QueryByExampleExecutor使用詳解

    這篇文章主要為大家介紹了Spring?Data?JPA系列QueryByExampleExecutor使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 深入淺析HashMap key和value能否為null

    深入淺析HashMap key和value能否為null

    HashMap的key和value可為null,線程不安全,HashTable的key和value均不可為null,線程安全,ConcurrentHashMap在多線程場景下使用,key和value也不能為null,還對它們進行了測試和底層代碼分析,本文介紹HashMap key和value能否為null,感興趣的朋友跟隨小編一起看看吧
    2025-04-04
  • 使用Properties讀取配置文件的示例詳解

    使用Properties讀取配置文件的示例詳解

    開發(fā)SpringBoot項目時,使用配置文件配置項目相關屬性是必不可少的,所以下文為大家準備了使用Properties讀取配置文件的示例代碼,希望對大家有所幫助
    2023-06-06
  • java冒泡排序和選擇排序詳解

    java冒泡排序和選擇排序詳解

    這篇文章主要介紹了java數(shù)組算法例題代碼詳解(冒泡排序,選擇排序),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-07-07
  • Mybatis實現(xiàn)SQL存儲流程詳解

    Mybatis實現(xiàn)SQL存儲流程詳解

    MyBatis作為一款優(yōu)秀的持久層框架,它支持自定義SQL、存儲過程以及高級映射。它免除了幾乎所有的JDBC代碼以及設置參數(shù)和獲取結(jié)果集的工作
    2023-03-03

最新評論

大厂| 阜新市| 本溪| 商洛市| 甘谷县| 射洪县| 襄汾县| 伊宁市| 运城市| 西充县| 喀什市| 通榆县| 惠来县| 乌拉特后旗| 克什克腾旗| 阳春市| 财经| 济源市| 新宁县| 腾冲县| 鄂托克前旗| 海口市| 屯昌县| 驻马店市| 那曲县| 北票市| 合阳县| 凭祥市| 白山市| 平凉市| 永福县| 句容市| 泗洪县| 营山县| 上犹县| 成安县| 九龙县| 高淳县| 荣成市| 浦江县| 修武县|