配置文件与配置中心实现人工开关降级

第十章 配置文件与配置中心实现人工开关降级

通过监控发现生产环境中一些服务的问题,需要将这些服务暂时摘除掉。有的时候,比如:服务调用量大,需要同步转异步;数据库存在,但是查询速度慢,这时需要暂停服务,立即修复;新开发的功能上线进行灰度测试,不确定新的功能是否有影响,一旦有影响就直接切回老的版本。配置可以存放在配置文件,redis/zookeeper或者数据库等。

1.配置文件实现开关配置

配置文件:switcher.properties

#不调用分片缓存
user.not.call.sharding.redis.cache=true
1.1.通过JDK7提供的WatchService,来监听本地文件系统中配置文件的变化,代码片段如下:
  public void startWatch() throws Exception {
        //监控文件
        WatchService watchService = FileSystems.getDefault().newWatchService();
        String fileName = "switcher.properties";
        Resource resource = new ClassPathResource(fileName);
        String watchPath = resource.getFile().getParent();
        Paths.get(watchPath).register(watchService,
                StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_DELETE,
                StandardWatchEventKinds.ENTRY_MODIFY);
        properties = PropertiesLoaderUtils.loadProperties(resource);
        Thread watchThread = new Thread(() -> {
            while (true) {
                try {
                    WatchKey key = watchService.take();
                    key.pollEvents().forEach(watchEvent -> {
                        if (Objects.equals(watchEvent.context().toString(), fileName)) {
                            try {
                                properties = PropertiesLoaderUtils.loadProperties(resource);
                            } catch (IOException e) {
                                logger.warn(e.getMessage());
                            }
                        }
                        logger.info(watchEvent.context() + " comes to " + watchEvent.kind());
                    });
                    boolean valid = key.reset();
                    if (!valid) {
                        break;
                    }
                } catch (InterruptedException e) {
                    logger.warn(e.getMessage());
                }
            }
        });
        watchThread.setDaemon(true);
        watchThread.start();
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                watchService.close();
            } catch (IOException e) {
                logger.warn(e.getMessage());
            }
        }));
    }
1.2.新建一个Switchs类封装
public class Switchs {

    public static class USER {
        public static boolean notCallInFile() {
            return Boolean.valueOf(WatchServiceManager.properties.getProperty("user.not.call.sharding.redis.cache"));
        }
    }
}
1.3.使用开关
if (Switchs.USER.notCallInFile()) {
    //业务逻辑
}

总结:通过配置文件实现开关配置,不具有一定的灵活性,一旦系统太多,配置文件的管理维护就变得过于繁杂,需要投入更多的成本,最好的方式还是通过配置中心统一管理。

2.配置中心实现开关配置

可以通过zookeeper,disconf、Apollo、Spring Cloud Config、Consul等作为配置中心,笔者通过Consul作为讲解,主要是Consul提供多数据中心、KV存储、服务发现等特性,拥有简单的Web UI。

2.1.下载和安装Consul

下载地址:https://www.consul.io/downloads.html

笔者下载的是consul_1.0.2_linux_386.zip,解压zip文件到指定目录,你会看到目录中有一个consul文件

# uzip consul_1.0.2_linux_386
2.2.启动consul
 ./consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -bind 0.0.0.0 -client 0.0.0.0 -ui &
2.3.在Consul新增/创建开关值
curl -XPUT -d 'true' http://localhost:8500/v1/kv/switchs/user.not.call.sharding.redis.cache

备注:也可以直接通过访问web ui直接新增/修改

2.3.在应用中代码中引入配置中心
    pulic void startWatch() {
        final String system = "switchs";
        Consul consul = Consul.builder()
                .withHostAndPort(HostAndPort.fromString("本机ipd地址:8500"))
                .withConnectTimeoutMillis(1000)
                .withReadTimeoutMillis(30 * 1000)
                .withWriteTimeoutMillis(5000)
                .build();
        final KeyValueClient keyValueClient = consul.keyValueClient();
        final AtomicBoolean needBreak = new AtomicBoolean(true);
        Thread watchThread = new Thread(() -> {
            BigInteger index = BigInteger.ZERO;
            while (true) {
                Properties _properties = new Properties();
                try {
                    List<Value> values = keyValueClient.getValues(system, QueryOptions.blockSeconds(30, index).build());
                    for (Value value : values) {
                        _properties.put(value.getKey().substring(system.length() + 1), value.getValueAsString());
                        logger.info("key:{}, value:{}",
                                value.getKey().substring(system.length() + 1),
                                value.getValueAsString().get());
                        index = index.max(BigInteger.valueOf(value.getModifyIndex()));
                    }
                    properties = _properties;
                } catch (ConsulException e) {
                    logger.warn(e.getMessage());
                    //如果没有key,就休眠5秒钟
                    if (e.getCode() == 404) {
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e1) {
                            logger.error(e.getMessage());
                        }
                    }
                }
                if (needBreak.get()) {
                    break;
                }
            }
        });
        watchThread.run();
        needBreak.set(false);
        watchThread.setDaemon(true);
        watchThread.start();
    }

备注:使用方式跟配置文件实现开关配置一样使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值