springcloud gateway高级功能之集成apollo后动态刷新路由方式

 更新时间:2023年08月28日 09:56:34   作者:lipengxs  
这篇文章主要介绍了springcloud gateway高级功能之集成apollo后动态刷新路由方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

springcloud gateway集成apollo后动态刷新路由

springcloud集成apollo后动态刷新路由配置

官网给的demo如下

import com.ctrip.framework.apollo.enums.PropertyChangeType;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
/**
 * @author ksewen
 * @date 2019/5/175:24 PM
 */
@Configuration
public class GatewayPropertiesRefresher implements ApplicationContextAware,ApplicationEventPublisherAware {
    private static final Logger logger = LoggerFactory.getLogger(GatewayPropertiesRefresher.class);
    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;
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
    @ApolloConfigChangeListener(interestedKeyPrefixes = "spring.cloud.gateway.",value="recommend-facade.yml")
    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) {
        logger.info("Refreshing GatewayProperties!");
        preDestroyGatewayProperties(changeEvent);
        this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
        refreshGatewayRouteDefinition();
        logger.info("GatewayProperties refreshed!");
    }
    /***
     * GatewayProperties没有@PreDestroy和destroy方法
     * org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder#rebind(java.lang.String)中destroyBean时不会销毁当前对象
     * 如果把spring.cloud.gateway.前缀的配置项全部删除(例如需要动态删除最后一个路由的场景),initializeBean时也无法创建新的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) {
        logger.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.setRoutes(new ArrayList<>());
        }
        logger.info("Pre Destroy GatewayProperties finished!");
    }
    private void refreshGatewayRouteDefinition() {
        logger.info("Refreshing Gateway RouteDefinition!");
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        logger.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;
    }
}

这里有个坑

如果是没有用到默认的application.properties,这里我们就需要填写namespace了

如下,

需要配置value=“使用的namespace”

    @ApolloConfigChangeListener(interestedKeyPrefixes = "spring.cloud.gateway.",value="xxxx.yml")
    public void onChange(ConfigChangeEvent changeEvent) {
        refreshGatewayProperties(changeEvent);
    }

springcloud集成apollo的注意事项

apollo的集成注意事项

1、建立本地缓存目录(这里的本地指的是java应用程序所在的pc):/opt/data

本地缓存路径默认位于以下路径,所以请确保/opt/data或C:\opt\data\目录存在,且应用有读写权限。

  • Mac/Linux: /opt/data/{appId}/config-cache
  • Windows: C:\opt\data{appId}\config-cache

2、要在本地目录下设置连接apollo环境变量。

在下面的目录下面,建立一个server.properties文件

  • Mac/Linux: /opt/settings
  • Windows: C:\opt\settings

文件内容如下:(DEV是SpringColoud 要连接的 apollo 配置 )

env=DEV

3、如果使用 apollo 自带的 eureka 。

那么发布到 apollo 的yml文件需要指定配置(eureka注意不能省略)

eureka.client.service-url.defaultZone	http://【apollo所在的ip】:8080/eureka

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Maven中央仓库发布的实现方法

    Maven中央仓库发布的实现方法

    最近做了个项目,希望能够上传到maven中央仓库,给更多的人使用,于是就产生了这次项目发布经历。感兴趣的可以一起来参考一下
    2021-06-06
  • 分析Spring框架之设计与实现资源加载器

    分析Spring框架之设计与实现资源加载器

    Spring框架是由于软件开发的复杂性而创建的。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。今天来分析它的设计与实现资源加载器,从Spring.xml解析和注册Bean对象
    2021-06-06
  • 多线程下嵌套异步任务导致程序假死问题

    多线程下嵌套异步任务导致程序假死问题

    这篇文章主要介绍了多线程下嵌套异步任务导致程序假死问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 使用Java实现验证码程序

    使用Java实现验证码程序

    这篇文章主要为大家详细介绍了使用Java实现验证码程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 详谈java命令的本质逻辑揭秘

    详谈java命令的本质逻辑揭秘

    一个简单的java命令背后究竟做了些什么事情,很多朋友提出几个问题,下面带领大家一起学习Java命令的本质逻辑问题,感兴趣的朋友跟随小编一起看看吧
    2021-05-05
  • StringBuilder为什么线程不安全深入讲解

    StringBuilder为什么线程不安全深入讲解

    这篇文章主要给大家介绍了关于StringBuilder为什么线程不安全的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用StringBuilder线程具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • SpringBoot favicon Chrome设置问题解决方案

    SpringBoot favicon Chrome设置问题解决方案

    在本篇文章里小编给大家分享的是关于SpringBoot favicon Chrome设置问题实例内容,小的朋友们可以参考学习下。
    2020-02-02
  • springmvc中RequestMappingHandlerAdapter与HttpMessageConverter的装配讲解

    springmvc中RequestMappingHandlerAdapter与HttpMessageConverter的

    今天小编就为大家分享一篇关于springmvc中RequestMappingHandlerAdapter与HttpMessageConverter的装配讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • java实现简单图片上传下载功能

    java实现简单图片上传下载功能

    这篇文章主要为大家详细介绍了java实现简单图片上传下载功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • Java零基础讲解异常

    Java零基础讲解异常

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等
    2022-04-04

最新评论