SpringCloud学习之Config—动态更新配置

Posted 枕微凉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud学习之Config—动态更新配置相关的知识,希望对你有一定的参考价值。

文章目录

1.Config的简介

springCloud Config 是一个解决分布式系统的配置管理方案,是SpringCloud的配置中心组件,可集中管理配置文件,是客户端和服务器端CS模式,其配置文件基于Git的。

2.Config的使用

1.创建一个新仓库存放各项目的Config配置

2.新建本次项目的文件夹,在git仓库中提交mysql-product-service服务的配置文件mysql-product-service-dev.properties

命名规则:服务名称-profile名称(dev/test/prod).properties或yml

server.port=9003

#设置jdbc配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/feign_product?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root

#映射文件
mybatis-plus.mapper-locations= classpath:mapper/*.xml
#开启驼峰转换
mybatis-plus.configuration.map-underscore-to-camel-case=true
#开启别名
mybatis-plus.type-aliases-package=com.blb.mysql_product_service.entity
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#服务名称
spring.application.name=mysql-product-server
#配置是否注册到Eureka
eureka.client.register-with-eureka=true
#配置是否从Eureka拉取服务清单
eureka.client.fetch-registry=true
#配置地址
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8888/eureka/

3.搭建Config服务器

1) 在config-service模块引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2)启动类上加上@EnableDiscoveryClient(加入eureka注册中心)以及@EnableConfigServer注解

3)编写配置文件

server.port=6666
spring.application.name=config-server
#是否从注册中心获得数据
eureka.client.fetch-registry=true
#是否注册到注册中心上
eureka.client.register-with-eureka=true
#配置注册中心的地址
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8888/eureka/
#配置中心git相关配置
spring.cloud.config.server.git.uri=自己的git仓库URL
spring.cloud.config.server.git.username=自己的账号
spring.cloud.config.server.git.password=自己的密码
#配置文件存放的目录,如果是根目录可以不配置
spring.cloud.config.server.git.search-paths=20220808_springcloud
#分支名称
spring.cloud.config.label=master

4.搭建Config客户端

1)在需要config的模块引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-client</artifactId>
</dependency>

2)将原本application改名为bootstrap(bootstrap会优先于application加载,这是约定大于配置)

server.port=9003
#应用程序名
spring.application.name=mysql-product-service
#是否从注册中心获得数据
eureka.client.fetch-registry=true
#是否注册到注册中心上
eureka.client.register-with-eureka=true
#配置注册中心的地址
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8888/eureka/

#配置中心服务器的配置
spring.cloud.config.discovery.service-id=config-server
#启动配置中心的发现机制
spring.cloud.config.discovery.enabled=true
#配置profile  不写profile 填default
spring.cloud.config.profile=dev
#配置分支
spring.cloud.config.label=master

#开启全部端点
management.endpoints.web.exposure.include=* 

3) 新增controller层文件,注入配置内容(用于测试)

访问 http://服务ip:端口/product/config查看Config是否生效

@RestController
@RefreshScope
public class ConfigController 
    @Value("$spring.datasource.driver-class-name")
    private String driverName;

    @Value("$spring.datasource.url")
    private String url;

    @Value("$spring.datasource.username")
    private String username;

    @Value("$spring.datasource.password")
    private String password;

    @GetMapping("/product/config")
    public String config()
        return driverName + " " + url;
    

5.动态更新配置

配置文件更新后,客户端需要获得最新的配置

5.1手动更新

1)客户端引入依赖 actuator

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2)在需要进行动态更新配置的类上加 @RefreshScope

3)开启端点,在配置文件中加入配置

#开启全部端点
management.endpoints.web.exposure.include=* 

4)修改git配置文件,发送post请求进行手动更新

http://服务ip:端口/actuator/refresh

5)访问 http://服务ip:端口/product/config查看手动更新是否生效

5.2自动更新

使用自动更新后,无需每次都发送post请求进行手动更新即可获得最新配置

1) 在git仓库中配置Webhook,使用内网穿透进行测试,按个人喜好选择穿透工具即可。

此时git会自动发送一个请求到当前路径,会报错400,因为码云的钩子有问题

解决方案:

  • 启动类加@ServletComponentScan
  • 在客户端编写CustometRequestWrapper与Filter配置文件
public class CustometRequestWrapper extends HttpServletRequestWrapper 
    public CustometRequestWrapper(HttpServletRequest request) 
        super(request);
    

    @Override
    public ServletInputStream getInputStream() throws IOException 
        byte[] bytes = new byte[0];
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        return new ServletInputStream() 
            @Override
            public boolean isFinished() 
                return byteArrayInputStream.read() == -1 ? true:false;
            

            @Override
            public boolean isReady() 
                return false;
            

            @Override
            public void setReadListener(ReadListener readListener) 

            

            @Override
            public int read() throws IOException 
                return byteArrayInputStream.read();
            
        ;
    


@WebFilter(filterName = "bodyFilter", urlPatterns = "/*")
@Order(1)
public class MyFlter  implements Filter 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException 

    

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException 
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        String url = new String(httpServletRequest.getRequestURI());
        //只过滤/actuator/refresh请求
        if (!url.endsWith("/actuator/refresh")) 
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        
        //使用HttpServletRequest包装原始请求达到修改post请求中body内容的目的
        CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest);
        filterChain.doFilter(requestWrapper, servletResponse);
    

    @Override
    public void destroy() 

    

2)配置完成后重新在Webhook进行测试,此时请求成功

3) 测试

​ 在远程仓库修改配置文件,然后访问 http://服务ip:端口/product/config查看自动更新是否生效。

5.3使用消息总线Bus+RabbitMQ实现自动更新

当有好几个服务器都需要拉取Config时,如果用普通的自动更新则需要每个都配置Webhook来拉取,比较麻烦,所以可以使用消息队列来统一拉取。
Bus是SpringCloud的消息总线,可以借助消息队列(RabbitMQ)进行消息广播,在Config服务端拉取各自所需的最新配置。

  1. 安装RabbitMQ,并启动。安装教程点击查看

2)Config服务端跟客户端都需要添加以下依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

注意:服务端还需要actuator依赖

3)Config服务和客户端都添加配置(默认为以下配置)

spring:
	rabbitmq:
		host: 127.0.0.1
		port: 5672 
		username: guest 
		password: guest

4)Config服务暴露端点(客户端可以不暴露)

management.endpoints.web.exposure.include=* 

5) Webhook 向Config服务发送post请求

http://内网穿透Config服务端端口/actuator/bus-refresh

出现400错误同之前一样处理

  • 服务端启动类加@ServletComponentScan(由于是统一拉取,所以之前在客户端上的这个注解可以删掉)
  • 在服务端编写CustometRequestWrapper与Filter配置文件(之前在客户端的配置文件也可以注释)
    注意: 修改过滤器中 url.endsWith(“/actuator/bus-refresh”))

===========以上就是本人整理的Config配置中心的使用,感谢查阅~ ==============

以上是关于SpringCloud学习之Config—动态更新配置的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud学习之五配置中心

SpringCloud学习之feign

flask学习之配置文件的加载和动态url的使用

SpringCloud gateway学习之helloWorld

SpringCloud学习之整合eureka

SpringCloud学习之Stream消息驱动自定义通道