方案设计

参见:https://github.com/lewiszlw/dcc

设计

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)

回滚方案:

  1. 用户在页面(http接口)选择一个版本配置进行回滚(前端调用回滚接口指定版本号)

  2. 后端接到回滚通知后,从数据库获取指定版本数据,然后更新zookeeper节点,然后插入(加锁)数据库配置表(版本递增一位),插入数据库之前会检查

权限管理

超级管理员

  • 新增、修改、删除application

管理员权限

  • 新增、修改、删除自己应用的配置

  • 新增、修改、删除自己应用的配置

  • 为自己应用新增、修改、删除管理员

非管理员权限

  • 查询配置

权限管理方案:

初步方案,使用注解配合aop管理http接口,使用dubbo filter管理rpc接口。

具体实现

存储设计

ZooKeeper

ZooKeeper特点:用于保证强一致性,代价是写入速度慢,只适合存储元数据。

选择zookeeper存储配置原因:

  1. 监听节点修改

  2. 在服务端使用集群情况下,利用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