方案设计
参见:https://github.com/lewiszlw/dcc
设计
dcc架构图
配置设计
配置五元组
application:应用标识(唯一)
env:环境
group:分组,将配置进行分组,默认为default
key:配置项名称
version:版本,配置的版本,从1开始递增
客户端拉取配置:
application、env初始化Client时传入,group在初始化Client传入或者获取配置时指定,两者都没有则默认为default分组,key在获取配置时传入(注解时传入或者直接获取变量名称作为key),version都是拉取最新版本。
功能设计
Http接口
配置增删改查
管理员增删改查
接口加密:增删改接口RSA加密(需要提前配置公钥私钥)
写接口限流
接口加密方案:
// TODO
写接口限流原因:
zookeeper写性能较差,所以选择只支持http接口写入而不支持rpc接口写入,同时限制写入的qps。
推拉模式
Dubbo定时全量查询
基于zookeeper监听配置变化
Dubbo服务鉴权:
// TODO
抛弃Http长轮询(每180s全量拉取配置),选择RPC服务来全量查询
优点:RPC服务较为稳定,性能高
缺点:RPC服务依赖重些,需要Dubbo、注册中心,Http较为轻量,无三方依赖
客户端获取配置
使用sdk提供的client的get方法:从本地缓存拿数据
使用注解:全量拉取或者基于zookeeper监听,set值到字段
操作记录
基于配置的操作记录,主要用于http接口查询
配置增、删、改、查记录
配置自检
判断配置推送成功
自检方案:
// TODO
配置回滚
选择历史版本中的一项回滚,回滚后在原有版本号上递增一位(类似Git的revert)
回滚方案:
用户在页面(http接口)选择一个版本配置进行回滚(前端调用回滚接口指定版本号)
后端接到回滚通知后,从数据库获取指定版本数据,然后更新zookeeper节点,然后插入(加锁)数据库配置表(版本递增一位),插入数据库之前会检查
权限管理
超级管理员
新增、修改、删除application
管理员权限
新增、修改、删除自己应用的配置
新增、修改、删除自己应用的配置
为自己应用新增、修改、删除管理员
非管理员权限
查询配置
权限管理方案:
初步方案,使用注解配合aop管理http接口,使用dubbo filter管理rpc接口。
具体实现
存储设计
ZooKeeper
ZooKeeper特点:用于保证强一致性,代价是写入速度慢,只适合存储元数据。
选择zookeeper存储配置原因:
监听节点修改
在服务端使用集群情况下,利用zookeeper能更好的同步数据到每个节点,也能更好的做容灾处理(一个节点挂掉不影响集群使用)
使用ZooKeeper存储配置,存储路径path:/config/{application}/{env}/{group}/{key}
存储数据格式:JSON
{
"application": "com.github.lewiszlw.dcc",
"env": "TEST",
"group": "default",
"key": "config1",
"value": "***",
"version": 12,
"comment": "配置解释"
}
创建/更新配置先从zookeeper创建/更新,成功后记录到MySQL的配置表(方法加锁),同时版本递增。
MySQL
MySQL存储配置数据、操作记录、权限数据等。
1.管理员表
CREATE TABLE `dcc_admin` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '表自增主键',
`application` varchar(50) NOT NULL UNIQUE COMMENT '应用配置空间',
`admin_type` tinyint(2) NOT NULL DEFAULT 'UNKNOWN' COMMENT '管理员类型',
`admin_id` varchar(20) DEFAULT NULL COMMENT '管理员标识',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='管理员表';
2.操作记录表
CREATE TABLE `dcc_record` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '表自增主键',
`record_type` tinyint(2) NOT NULL DEFAULT 'UNKNOWN' COMMENT '操作类型',
`application` varchar(50) NOT NULL UNIQUE COMMENT '应用配置空间',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='管理员表';
3.配置表
CREATE TABLE `dcc_config` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '表自增主键',
`application` varchar(50) NOT NULL DEFAULT '' COMMENT '应用配置空间',
`env` varchar(10) NOT NULL DEFAULT 'UNKNOWN' COMMENT '环境',
`group` varchar(20) NOT NULL DEFAULT '' COMMENT '分组',
`key` varchar(50) NOT NULL DEFAULT '' COMMENT '配置key',
`version` int(10) NOT NULL DEFAULT '0' COMMENT '版本',
`value` text COMMENT '分组',
`comment` varchar(500) COMMENT '注释',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='配置表';
缓存
Redis:缓存热点配置
定时任务
选择:
Timer
ScheduledExecutor
Quartz/JCronTab
方案:
选择ScheduledExecutor,比较轻量级,无其他依赖,同时相较于Timer更好。Timer缺点:同一个线程来调度,任务串行执行,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务,p3c不推荐用Timer。Quartz/JCronTab适合复杂的调度任务,不适合本项目。
https://www.ibm.com/developerworks/cn/java/j-lo-taskschedule/index.html
日志
存储在 /opt/logs/dcc
目录,需确保拥有权限
nginx
外网不可访问、负载均衡
Last updated