apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)

【目录】

灰度实战(一):Apollo配置中心(1)

灰度实战(二):Apollo配置中心(2)

灰度实战(三):Apollo配置中心(3)

灰度实战(四):Apollo配置中心(4)

灰度实战(五):SpringCloud灰度(1)

灰度实战(六):SpringCloud灰度(2)

【前言】

在上一篇博文《灰度实战(二):Apollo配置中心(2)》中讲解了Apollo如何动态更改程序中通过@value配置值,在本篇博文中为大家带来如何通过Apollo动态更新程序和中间件的连接。

【实时推送演示】

一、程序和第三方组件连接动态更改(在此以连接redis为例)---失败版

1、演示代码(增加redis操作)

package com.zhanghan.grayapollo.controller;import com.zhanghan.grayapollo.util.wrapper.WrapMapper;import com.zhanghan.grayapollo.util.wrapper.Wrapper;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;import java.util.Map;@RestController@Api(value = "演示Apollo控制器",tags = {"演示Apollo控制器"})public class DynamicController {    @Value("${zh.int}")    private Integer zhInt;    @Autowired    private RedisTemplate strRedisTemplate;    @ApiOperation(value="测试通过@value注入数据",tags = {"演示Apollo控制器"})    @RequestMapping(value = "/test/value", method = RequestMethod.POST)    public Wrapper testValue() {        Map map = new HashMap();        map.put("zhTest", zhInt);        return WrapMapper.ok(map);    }    @ApiOperation(value="演示向redis中放数据",tags = {"演示Apollo控制器"})    @RequestMapping(value = "/post/rdb", method = RequestMethod.POST)    public Wrapper postDB() {        strRedisTemplate.opsForValue().set("zh-test",zhInt.toString());        Map map = new HashMap();        map.put("putZhTest", zhInt.toString());        return WrapMapper.ok(map);    }    @ApiOperation(value="演示从redis中获取数据",tags = {"演示Apollo控制器"})    @RequestMapping(value = "/get/rdb", method = RequestMethod.POST)    public Wrapper getDB() {        String getZhInt = strRedisTemplate.opsForValue().get("zh-test");        Map map = new HashMap();        map.put("getZhTest", getZhInt);        return WrapMapper.ok(map);    }}

2、访问swagger给redis设置值

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第1张图片

​ 3、访问swagger读取redis设置的值

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第2张图片

​ 4、用redis可视化工具查看,此时存储在redis的1库中(此时2库中没有值)

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第3张图片

​ 5、在Apollo上修改redis的库(由1改为2),并发布

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第4张图片

​ 6、查看系统的日志,发现将变动已经推送到程序

3fa678a342583d6b31aecadb58c60bd9.png

​ 7、此时再次访问swagger的从redis中读取值接口

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第5张图片

​ 8、小结:

竟然还可以读取到值,说明redis数据库并未切换;说明刚刚的配置变更只是推送到程序,而程序在第一次启动时已经和redis建立连接(其中含redis的database),推送并没有改变连接;

二、程序和第三方组件连接动态更改(在此以连接redis为例)---成功版

1、如何动态的更改那?

(1)增加Apollo的监听类并刷新程序配置

package com.zhanghan.grayapollo.refresh;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.context.scope.refresh.RefreshScope;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;@Componentpublic class RedisPropertiesRefresher implements ApplicationContextAware {    private static final Logger logger = LoggerFactory.getLogger(RedisPropertiesRefresher.class);    private ApplicationContext applicationContext;    @Autowired    private RefreshScope refreshScope;    //此处配置的value值为Apollo的namespace名称    @ApolloConfigChangeListener(value = "grayapollo")    public void onChange(ConfigChangeEvent changeEvent) {        boolean propertiesChanged = false;        for (String changedKey : changeEvent.changedKeys()) {            logger.info("===============================================================");            logger.info("changedKey:{} value:{}", changedKey, changeEvent.getChange(changedKey));            ConfigChange configChange = changeEvent.getChange(changedKey);            configChange.getOldValue();            propertiesChanged = true;            break;        }        refreshProperties(changeEvent);        if (propertiesChanged) {            refreshProperties(changeEvent);        }    }    private void refreshProperties(ConfigChangeEvent changeEvent) {        this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));        refreshScope.refreshAll();    }    @Override    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {        this.applicationContext = applicationContext;    }}

(2)redis工场增加@RefreshScope

package com.zhanghan.grayapollo.config;import com.zhanghan.grayapollo.properties.RedisProperties;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.annotation.EnableCaching;import org.springframework.cloud.context.config.annotation.RefreshScope;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;import org.springframework.data.redis.connection.RedisPassword;import org.springframework.data.redis.connection.RedisStandaloneConfiguration;import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.GenericToStringSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;import org.springframework.stereotype.Component;import redis.clients.jedis.JedisPoolConfig;@Component@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport {    @Autowired    private RedisProperties redisProperties;    @Bean    @RefreshScope  //此注解用于动态刷新    public JedisConnectionFactory jedisConnectionFactory() {        RedisStandaloneConfiguration rf = new RedisStandaloneConfiguration();        rf.setDatabase(redisProperties.getDatabase());        rf.setHostName(redisProperties.getHost());        rf.setPort(redisProperties.getPort());        rf.setPassword(RedisPassword.of(redisProperties.getPassword()));        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpb =                (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();        jedisPoolConfig.setMaxIdle(redisProperties.getMaxIdle());        jedisPoolConfig.setMinIdle(redisProperties.getMinIdle());        jedisPoolConfig.setMaxTotal(redisProperties.getMaxActive());        jedisPoolConfig.setMaxWaitMillis(redisProperties.getMaxWait());        jedisPoolConfig.setEvictorShutdownTimeoutMillis(redisProperties.getTimeout());        jpb.poolConfig(jedisPoolConfig);        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(rf, jpb.build());        return jedisConnectionFactory;    }    @Bean    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {        return new PropertySourcesPlaceholderConfigurer();    }    @Bean    RedisTemplate redisTemplate() {        RedisTemplate redisTemplate = new RedisTemplate<>();        redisTemplate.setConnectionFactory(jedisConnectionFactory());        return redisTemplate;    }    @Bean    RedisTemplate strRedisTemplate() {        final RedisTemplate template = new RedisTemplate<>();        template.setConnectionFactory(jedisConnectionFactory());        template.setKeySerializer(new StringRedisSerializer());        template.setHashValueSerializer(new GenericToStringSerializer<>(String.class));        template.setValueSerializer(new GenericToStringSerializer<>(String.class));        return template;    }    @Bean    RedisTemplate longRedisTemplate() {        final RedisTemplate template = new RedisTemplate<>();        template.setConnectionFactory(jedisConnectionFactory());        template.setKeySerializer(new StringRedisSerializer());        template.setHashValueSerializer(new GenericToStringSerializer<>(Long.class));        template.setValueSerializer(new GenericToStringSerializer<>(Long.class));        return template;    }    @Bean    RedisTemplate booleanRedisTemplate() {        final RedisTemplate template = new RedisTemplate<>();        template.setConnectionFactory(jedisConnectionFactory());        template.setKeySerializer(new StringRedisSerializer());        template.setHashValueSerializer(new GenericToStringSerializer<>(Boolean.class));        template.setValueSerializer(new GenericToStringSerializer<>(Boolean.class));        return template;    }    @Bean    RedisTemplate intRedisTemplate() {        final RedisTemplate template = new RedisTemplate<>();        template.setConnectionFactory(jedisConnectionFactory());        template.setKeySerializer(new StringRedisSerializer());        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));        return template;    }}

2、此时清空本地redis,再重新做实验,进行验证;(程序启动时Apollo配置的redis的数据库为1,程序启动后动态改成连库2)

3、访问swagger给redis设置值

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第6张图片

​ 4、访问swagger读取redis设置的值

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第7张图片

​ 5、用redis可视化工具查看,此时存储在redis的1库中(此时2库中没有值)

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第8张图片

​ 6、在Apollo上修改redis的库(由1改为2),并发布

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第9张图片

​ 7、此时再次访问swagger的从redis中读取值接口(惊喜出现了),说明换库了

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第10张图片

​ 8、究竟是换的是不是1库那?我们此时再在swagger上调用放入redis值接口

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第11张图片

​ 9、此时通过redis客户端查看库2中惊奇发现已经有刚才设置的值;说明已经成功的切库。

apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3)_第12张图片

​ 10、至此实验成功;

三、项目地址

灰度实战:https://github.com/dangnianchuntian/gray

【总结】

1、本节第一部分为大家证实,如果不配置Apollo监听以及redis连接工程的动态更新,不能动态的更改程序与中间件连接。

2、本节第二部分为大家演示如何接收Apollo动态更新连第三方中间件的连接池(以redis连接池为例)。

你可能感兴趣的:(apollo修改配置刷新bean_灰度实战(三):Apollo配置中心(3))