基于Spring Cloud Bus + RocketMQ实现配置管理中心

发表于:2022-9-07 09:39

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:法号弗兰克    来源:今日头条

  要搭建一套微服务管理平台,根据微服务管理12项原则,微服务应用代码和应用配置要分开管理和部署。通常的做法是实现一套配置管理中心。业界有挺多流行的配置管理中心。比如Nacos,Apollo,Spring Could Config等。今天为大家介绍一种利用Spring Cloud 家族中的Spring Cloud Config Bus加上RocketMQ 搭建配置管理中心并实现动态刷新。原创不易。喜欢的点赞收藏哈。
  整体架构
  首先看下整体架构,在这里多说一句,在实现一套系统之前一定要把架构设计好,在前期设计过程中尽可能的避免一些因为缺少设计导致的后面的繁重的重构工作。那么一个配置管理中心的几个要素要先梳理清楚:
  配置管理服务端:承载配置管理,配置动态下发,配置拉取等功能。
  应用客户端:启动依赖远程配置的微服务应用。
  中间件:配置刷新依赖的中间件,这里我们选择RocketMQ。
  配置存储介质:配置内容存储的地方,一般是代码仓库或者数据库,这里我们选择MySql数据库存储配置。
配置管理中心
  平台管理员(一般是运维人员)通过配置管理服务管理应用配置内容,应用启动通过Restful请求从而配置管理服务拉取远程配置,当配置需要更改时,通过配置管理服务端触发动态刷新,配置内容以RocketMQ消息形式被应用客户端消费并更新应用上下文,无需重启应用。
  实现细节
  配置服务端添加以下maven依赖,建议根据情况自定义rocketmq-client版本:
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-bus-rocketmq</artifactId>
      <version>${spring.cloud.bus.rocketmq.version}</version>
      <type>pom</type>
      <scope>import</scope>
  </dependency>
  <dependency>
      <groupId>org.apache.rocketmq</groupId>
      <artifactId>rocketmq-client</artifactId>
      <version>${rocketmq.version}</version>
      <type>pom</type>
      <scope>import</scope>
  </dependency>
  spring cloud bus已经实现了一些默认的event, 本质上是RocketMQ消息来实现server和client端通信来动态刷新配置,如果想要应用能够启动的时候从远程拉取配置,服务端需要引入下面依赖。
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-config-server</artifactId>
      <version>${spring-cloud.version}</version>
      <type>pom</type>
      <scope>import</scope>
  </dependency>
  服务端配置如下:
  server.port=8080
  spring.application.name=config-server
  spring.cloud.bus.enabled=true
  spring.cloud.bus.destination=springCloudBus
  rocketmq.name-server=127.0.0.1:9876
  然后客户端需要添加下面的依赖:
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-config-client</artifactId>
      <version>${spring-cloud.version}</version>
      <type>pom</type>
      <scope>import</scope>
  </dependency>
  客户端配置application.propeties在resource目录下:
  spring.application.name=config-client-app
  server.port=8090
  rocketmq.name-server=127.0.0.1:9876
  客户端配置bootstap.properties在resource目录下,spring cloud config client会优先根据bootstrap配置从远程加载应用配置。
  spring.application.name=config-client-app
  //接口URL可以是config server自己实现的接口地址
  spring.cloud.config.server.uri=http://127.0.0.1/dev/config-client-app
  spring.cloud.config.server.username=接口认证账号
  spring.cloud.config.server.password=接口认证密码
  服务端发布事件
  由于 Spring Cloud Bus传输消息基于 pub&sub 模型,因此我们需要定义一个反映应用程序配置修改的事件。该事件需要是 RemoteApplicationEvent 的子类,它将被 spring cloud bus 注册到 spring 上下文中。我们可以为实例化事件创建一个特定的endpint,并通过ApplicationEventPublisher.class 发布事件,以便将相应的事件消息发送到RocketMQ 消息通道。
  public class ConfigRemoteApplicationEvent extends RemoteApplicationEvent {
      private Map<String, String> configMap;
   
      public ConfigRemoteApplicationEvent() {
          this.configMap = null;
      }
   
      public ConfigRemoteApplicationEvent(Object source, String originService, String destinationService, Map configMap) {
          super(source, originService, destinationService);
          this.configMap = configMap;
      }
   
      public Map<String, String> getConfigMap() {
          return configMap;
      }
   
      public void setConfigMap(Map<String, String> configMap) {
          this.configMap = configMap;
      }
  }
  客户端监听事件
  应用客户端一旦接收到来自 RocketMQ 的事件消息,就可以相应地处理事件并刷新配置。有两种方式来处理远程应用程序事件,第一种是定义一个自定义的事件监听器,它继承了 ApplicationListener.class 并实现了 onApplicationEvent 方法。
  @Component
  public class ConfigRemoteApplicationEventListener implements ApplicationListener<ConfigRemoteApplicationEvent> {
      @Override
      public void onApplicationEvent(ConfigRemoteApplicationEvent configRemoteApplicationEvent) {
          System.out.printf("Received message %s", configRemoteApplicationEvent.getConfigMap().toString());
      }
  }
  另一种是方法上加上@EventListner注解:
  @EventListener
  public void onConfigEvent(ConfigRemoteApplicationEvent event){
      Map<String, String> configs = event.getConfigMap();
      System.out.printf("Server received config to updated : %s\n",event.getConfigMap().toString());
      Iterator configIterator = configs.entrySet().iterator();
   
      while(configIterator.hasNext()) {
          Map.Entry<String, String> entry = (Map.Entry)configIterator.next();
          environmentManager.setProperty(entry.getKey(), entry.getValue());
      }
  }
  结束!
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号