SpringCloud Config客户端通过代码和接口刷新配置

5 篇文章 0 订阅
4 篇文章 0 订阅

转载请著名出处:https://blog.csdn.net/yy1098029419/article/details/80668931

应用场景

    在微服务架构中,我们经常使用一个配置中心管理各个服务的配置信息,如此可以方便我们对微服务集群的配置修改。可是在配置中心的配置更新后,客户端只有重启后才可以获取最新的配置,为了避免服务的重启SpringCloud给出了自己的解决方案。

具体方案

    在配置之前先添加依赖,具体依赖如下:

<!-- 动态刷新配置 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

    找到引用了远程配置的类,添加@RefreshScope注解。代码如下:

@RestController
@Configuration
@RefreshScope
public class MainController {
    @Value("${foo}")
    private String foo;

    @RequestMapping("foo")
    public String foo() {
    return foo;
    }

一.对外暴露Web接口

     如果是SpringBoot 2.x,需要在application.properties中添加配置,启用我们需要的Web接口:

management.endpoints.web.exposure.include=*

    启动项目,如果是SpringBoot2.x项目则可以看到如下日志,红色文字为暴露的接口路径:

2018-06-12 18:06:25.364  INFO 5272 --- [           main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/refresh],methods=[POST],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)

    SpringBoot1.x则是/refresh或/admin/refresh

测试

    打开浏览器输入http://localhost:8080/foo输出初始的foo数据;随后修改foo的配置,并使用工具以POST方式请求http://localhost:8080/actuator/refresh;最后再次使用浏览器查看foo数据,可以看到foo数据已经更新为最新。

二.使用代码自动刷新

    通过追踪/refresh接口的源码,可以在GenericPostableMvcEndpoint类中发现如下代码:

@ManagedOperation
public String[] refresh() {
    Set<String> keys = contextRefresher.refresh();
    return keys.toArray(new String[keys.size()]);
}
@Override
public Collection<String> invoke() {
    return Arrays.asList(refresh());
}

    程序会调用该类的invoke方法,实际调用的是contextRefresher.refresh()方法,继续追踪refresh()方法:

public synchronized Set<String> refresh() {
                Map<String, Object> before = extract(
                this.context.getEnvironment().getPropertySources());
                //重新拉取最新配置
                addConfigFilesToEnvironment();
                //获取发生更新的配置名
                Set<String> keys = changes(before,
                extract(this.context.getEnvironment().getPropertySources())).keySet();
                this.context.publishEvent(new EnvironmentChangeEvent(context, keys));
                //刷新所有配置
                this.scope.refreshAll();
                return keys;
	}

    通过以上代码可以确定refresh()方法是刷新配置的控制者,所以我们不需要深入了解它到底做了什么,如果我们可以主动调用refresh()方法就可以实现目标。

    首先我们需要获取contextRefresher对象,直接new一个新的对象显然是不可取的,那么会不会存放在Spring的IOC容器呢。经过测试发现在IOC容器中可以成功获取到一个ContextRefresher类的实例,具体代码如下:

@Component
public class ConfigTask {
        @Autowired
        private ContextRefresher contextRefresher;

    随后在需要刷新配置的位置调用contextRefresher.refresh()即可完成刷新。


    最后需要注意,由于实现原理的影响,使用ContextRefresher的类不可以拥有@RefreshScope,否则程序会出现不可预期的异常,具体原因将在之后补充。


如果有用请关注我,谢谢
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值