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

Spring?Cloud?Gateway動態(tài)路由Apollo實現詳解

 更新時間:2022年10月29日 17:17:02   作者:weihubeats  
這篇文章主要為大家介紹了Spring?Cloud?Gateway動態(tài)路由通過Apollo實現示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

背景

在之前我們了解的Spring Cloud Gateway配置路由方式有兩種方式

  • 通過配置文件
spring:
  cloud:
    gateway:
      routes:
        - id: test
          predicates:
            - Path=/ms/test/*
          filters:
            - StripPrefix=2
          uri: http://localhost:9000
  • 通過JavaBean
    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route(r -> r.path("/ms/test/**")
                .filters(f -> f.stripPrefix(2))
                .uri("http://localhost:9000"))
                .build();
    }

但是遺憾的是這兩種方式都不支持動態(tài)路由,都需要重啟服務。 所以我們需要對Spring Cloud Gateway進行改造,在改造的時候我們就需要看看源碼了解下Spring Cloud Gateway的路由加載

路由的加載

我們之前分析了路由的加載主要在GatewayAutoConfigurationrouteDefinitionRouteLocator方法加載的

實際上最終獲取的路由信息都是在GatewayProperties這個配置類中

所以我們在動態(tài)路由的時候修改GatewayProperties中的屬性即可,即

List<RouteDefinition> routes

List<FilterDefinition> defaultFilters

恰巧Spring Cloud Gateway也提供了相應的getset方法

實際如果我們修改了該屬性我們會發(fā)現并不會立即生效,因為我們會發(fā)現還有一個RouteLocator就是CachingRouteLocator,并且在配置Bean的時候加了注解@Primary,說明最后使用額RouteLocator實際是CachingRouteLocator

CachingRouteLocator最后還是使用RouteDefinitionRouteLocator類加載的,也是就我們上面分析的,看CachingRouteLocator就知道是緩存作用

這里引用網上一張加載圖片

參考http://www.dbjr.com.cn/article/219238.htm

所以看到這里我們知道我們還需要解決的一個問題就是更新緩存,如何刷新緩存呢,這里Spring Cloud Gateway利用spring的事件機制給我提供了擴展

所以我們要做的事情就是這兩件事:

  • GatewayProperties
  • 刷新緩存

實現動態(tài)路由

這里代碼參考 github.com/apolloconfi…

@Component
@Slf4j
public class GatewayPropertiesRefresher implements ApplicationContextAware, ApplicationEventPublisherAware {
	private static final String ID_PATTERN = "spring\\.cloud\\.gateway\\.routes\\[\\d+\\]\\.id";
	private static final String DEFAULT_FILTER_PATTERN = "spring\\.cloud\\.gateway\\.default-filters\\[\\d+\\]\\.name";
	private ApplicationContext applicationContext;
	private ApplicationEventPublisher publisher;
	@Autowired
	private GatewayProperties gatewayProperties;
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
	@Override
	public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
		this.publisher = applicationEventPublisher;
	}
	@ApolloConfigChangeListener(value = "route.yml",interestedKeyPrefixes = "spring.cloud.gateway.")
	public void onChange(ConfigChangeEvent changeEvent) {
		refreshGatewayProperties(changeEvent);
	}
	/***
	 * 刷新org.springframework.cloud.gateway.config.PropertiesRouteDefinitionLocator中定義的routes
	 *
	 * @param changeEvent
	 * @return void
	 * @author ksewen
	 * @date 2019/5/21 2:13 PM
	 */
	private void refreshGatewayProperties(ConfigChangeEvent changeEvent) {
		log.info("Refreshing GatewayProperties!");
		preDestroyGatewayProperties(changeEvent);
		this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
		refreshGatewayRouteDefinition();
		log.info("GatewayProperties refreshed!");
	}
	/***
	 * GatewayProperties沒有@PreDestroy和destroy方法
	 * org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder#rebind(java.lang.String)中destroyBean時不會銷毀當前對象
	 * 如果把spring.cloud.gateway.前綴的配置項全部刪除(例如需要動態(tài)刪除最后一個路由的場景),initializeBean時也無法創(chuàng)建新的bean,則return當前bean
	 * 若仍保留有spring.cloud.gateway.routes[n]或spring.cloud.gateway.default-filters[n]等配置,initializeBean時會注入新的屬性替換已有的bean
	 * 這個方法提供了類似@PreDestroy的操作,根據配置文件的實際情況把org.springframework.cloud.gateway.config.GatewayProperties#routes
	 * 和org.springframework.cloud.gateway.config.GatewayProperties#defaultFilters兩個集合清空
	 *
	 * @param
	 * @return void
	 * @author ksewen
	 * @date 2019/5/21 2:13 PM
	 */
	private synchronized void preDestroyGatewayProperties(ConfigChangeEvent changeEvent) {
		log.info("Pre Destroy GatewayProperties!");
		final boolean needClearRoutes = this.checkNeedClear(changeEvent, ID_PATTERN, this.gatewayProperties.getRoutes()
				.size());
		if (needClearRoutes) {
			this.gatewayProperties.setRoutes(new ArrayList<>());
		}
		final boolean needClearDefaultFilters = this.checkNeedClear(changeEvent, DEFAULT_FILTER_PATTERN, this.gatewayProperties.getDefaultFilters()
				.size());
		if (needClearDefaultFilters) {
			this.gatewayProperties.setDefaultFilters(new ArrayList<>());
		}
		log.info("Pre Destroy GatewayProperties finished!");
	}
	private void refreshGatewayRouteDefinition() {
		log.info("Refreshing Gateway RouteDefinition!");
		this.publisher.publishEvent(new RefreshRoutesEvent(this));
		log.info("Gateway RouteDefinition refreshed!");
	}
	/***
	 * 根據changeEvent和定義的pattern匹配key,如果所有對應PropertyChangeType為DELETED則需要清空GatewayProperties里相關集合
	 *
	 * @param changeEvent
	 * @param pattern
	 * @param existSize
	 * @return boolean
	 * @author ksewen
	 * @date 2019/5/23 2:18 PM
	 */
	private boolean checkNeedClear(ConfigChangeEvent changeEvent, String pattern, int existSize) {
		return changeEvent.changedKeys().stream().filter(key -> key.matches(pattern))
				.filter(key -> {
					ConfigChange change = changeEvent.getChange(key);
					return PropertyChangeType.DELETED.equals(change.getChangeType());
				}).count() == existSize;
	}
}

然后我們在apollo添加namespace:route.yml

配置內容如下:

spring:
  cloud:
    gateway:
      routes:
        - id: test
          predicates:
            - Path=/ms/test/*
          filters:
            - StripPrefix=2
          uri: http://localhost:9000

然后我們可以通過訪問地址: http:localhost:8080/ms/test/health

看刪除后是否是404,加上后是否可以正常動態(tài)路由

值得注意的是上面@ApolloConfigChangeListener中如果沒有添加新的namespace,value可以不用填寫,如果配置文件是yml配置文件,在監(jiān)聽的時候需要指定文件后綴

以上就是Spring Cloud Gateway動態(tài)路由Apollo實現詳解的詳細內容,更多關于Spring Cloud Gateway Apollo的資料請關注腳本之家其它相關文章!

相關文章

  • Java將json對象轉換為map鍵值對案例詳解

    Java將json對象轉換為map鍵值對案例詳解

    這篇文章主要介紹了Java將json對象轉換為map鍵值對案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-09-09
  • 關于@MapperScan包掃描的坑及解決

    關于@MapperScan包掃描的坑及解決

    這篇文章主要介紹了關于@MapperScan包掃描的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • java實現錄音播放功能

    java實現錄音播放功能

    這篇文章主要為大家詳細介紹了java實現錄音播放功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • java?SpringBootWeb請求響應舉例詳解

    java?SpringBootWeb請求響應舉例詳解

    SpringBoot是一種整合Spring技術棧的方式(或者說是框架),同時也是簡化Spring的一種快速開發(fā)的腳手架,這篇文章主要給大家介紹了關于java?SpringBootWeb請求響應的相關資料,需要的朋友可以參考下
    2024-05-05
  • java使用JMF實現音樂播放功能

    java使用JMF實現音樂播放功能

    這篇文章主要為大家詳細介紹了java使用JMF實現音樂播放的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Java8函數式接口的基礎學習教程

    Java8函數式接口的基礎學習教程

    這篇文章主要給大家介紹了關于Java8函數式接口基礎學習的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • 深入淺析 Spring Security 緩存請求問題

    深入淺析 Spring Security 緩存請求問題

    這篇文章主要介紹了 Spring Security 緩存請求問題,本文通過實例文字相結合的形式給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友參考下吧
    2019-04-04
  • Spring示例講解條件注入方法

    Spring示例講解條件注入方法

    Spring支持按照條件來注入某些特定的bean,這也是Spring Boot實現自動化配置的底層方法,文中的示例代碼講解詳細,需要的可以參考一下
    2022-06-06
  • 淺談Java中實現深拷貝的兩種方式—clone() & Serialized

    淺談Java中實現深拷貝的兩種方式—clone() & Serialized

    這篇文章主要介紹了Java中實現深拷貝的兩種方式—clone() & Serialized,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • java實現一個簡單的Web服務器實例解析

    java實現一個簡單的Web服務器實例解析

    這篇文章主要介紹了java實現一個簡單的Web服務器實例解析,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02

最新評論