分布式配置中心 duic - 设计&实现

什么是配置?

配置(Configuration)对于技术人员来说应该都不陌生,通常配置都是以 key-value 的形式存在于配置文件当中。例如线程池大小、数据库连接、逻辑开关及业务参数等等。

那么为什么我们需要提供各种各样的配置呢?其本质原因是我们无法在开发时决定软件在运行时的一切,为保证程序的灵活性我们需要在开发过程中提供各种配置,以便软件在运行时能动态调整程序的行为。

配置即程序在运行时动态调整行为的能力!

灵感

之前我们一直是使用 spring-cloud-config 来管理服务端配置,但是 spring-cloud-config 并不支持热加载,按需获取配置,且因为是 spring 体系中的项目对于其它语言或非 spring 体系的项目支持较弱。

建立在这种基础之上,我们借鉴了 spring-cloud-config 的配置管理方式以及应用环境管理方式开发了全新的分布式配置中心 duic。

简介

duic 简介

项目地址:https://github.com/zhudyos/duic

duic 的诞生从来都不只是为了解决服务端的配置问题,你同样可以使用它对 APP、WEB 应用的配置进行管理。因采用 HTTP 的方式拉取配置数据,对于多语言,多应用类型的配置支持非常的好。

如果你的 APP、WEB、Server 有一部分公共配置,你也可以完全使用 duic 来解决,而不需要在每个应用单独配置(冗余),修改一处配置对于所有应用都有效。并且 duic 支持多配置合并功能,你可以将公共配置与私有配置分开管理,在拉取配置时进行合并,能有效的进行配置权限管理。同时 duic 支持按需获取配置,这个功能对于 WEB、APP 非常有用,有时你可能只需要某个配置参数,而不是拉取整个配置数据。

设计目标是统一不同应用的配置管理方式,打造更人性化的配置编辑方式,提供更灵活的配置获取方式。

另外 duic 完全兼容 spring-boot 及 spring 并且对代码没有任何浸入

duic 配置管理方式与其它配置中心是完全不一样的,我们放弃采用 key-value 两个输入框来编辑配置的方式。转而采用 YAML 语法 + 在线编辑器的方式来管理编辑配置。这样可以轻松支持结构化配置并且你可以得到高度可视化配置编辑方式,如下图:

配置示例

这种管理方式所带来的好处是:

  • 配置可读性高
  • 支持语法高亮
  • 支持数据类型
  • 支持文档注释
  • 结构化配置为按需获取配置提供了基础

通常配置都是以 key-value 的形式存在,比如 VIP 的价格 vip.price=100,是否启用某个功能 game.enabled=true。大多数情况是如此,但是实际情况中还是有很多场景需要结构化的配置支持,目前使用较多来处理这种场景的方法是使用 key=json string 来解决。 例:将图标和点击的 URL 采用 JSON 的方式配置,可以在数据结构中维持配置的关系且配置易于理解。

{
  "logo": {
    "top": {
      "icon": "icon url",
      "url": "link url"
    },
    "special": {
      "icon": "icon url",
      "url": "link url"
    },
    "goddess": {
      "icon": "icon url",
      "url": "link url"
    }
  }
}

特性

  • 集中配置管理,多应用多环境配置
  • 配置实时更新
  • 支持配置数据类型/数据格式
  • HTTP 方式拉取配置
  • 配置状态检查
  • 配置状态监控
  • 多配置合并
  • 按需获取配置
  • 配置权限管理
  • 支持配置 IP 访问限制
  • 支持配置 TOKEN 校验
  • 支持 MySQL 存储配置
  • 支持 Oracle 存储配置
  • 支持 PostgreSQL 存储配置
  • 支持 MongoDB 存储配置
  • 支持 Docker 部署
  • 完美支持 Spring Boot如果你的项目是采用 spring-boot 开发,那 duic 不仅能管理你业务的配置,还能管理所有 spring-boot 相关的配置,配置方式与 application.yml 文件编辑无差异

系统架构

部署

基本部署方案

duic 支持 MySQL、PostgreSQL、Oracle、MongoDB 存储配置信息,你可以灵活的选择配置存储方式。依照上图部署 duic 就能使用配置中心的全部功能,部署的方式和网络组织架构都非常的简单。

在设计时为了能简化部署,将 Admin 与获取配置相关的 API 集成在一个服务当中,降低部署的复杂性。

高可用部署架构方案

duic 对于数据库的压力非常的小,所以基本上数据库你只需要 master/salve 部署模式即可实现服务高可用。duic 服务你可以根据自身业务的压力情况部署 N 个。前面可以采用 nginx 做负载均衡利用 keepalived 避免单点问题。这是我们目前使用 duic 高可用的部署方案(仅供参考)。

实现

duic 是完全采用 Reactive Programming 实现。使用技术主要有 kotlin、spring-webflux、spring-boot、vue.js、gradle。

特性

配置实时更新实现方式

配置实时更新实现方式
  • 客户端启动时获取配置及配置状态。
  • 使用 /apps/watches/{name}/{profiles} 接口监控服务端配置状态变化。
    • 调用 watches 接口时需要传入客户端当前状态,服务端根据客户端传入的状态判断。
    • 如果与服务端的配置状态不一致会立即响应最新的状态。
    • 如果状态一致请求则会延迟返回(最长30秒)。在30秒内配置状态发生变化,服务端会立即响应。在30秒配置状态未发生变化,服务端也会响应当前最新状态给客户端。
  • 接收到服务端的状态响应时客户端需要判断状态是否与客户端当前的一致,如果一致则继续 watch 配置状态,如果不一致则重载配置。

配置重载完全是由客户端发起的,这是长轮询(Long Polling)实现,利用 HTTP 长连接无需担心重复建立链接问题,带来的好处就是实现简单可用性高。

配置&内存

在 duic 服务启动时会将数据库存储的配置数据全部加载在 JVM 内存中,当你通过 HTTP 接口访问配置数据时,duic 会直接将内存中的配置返回,中间不会有任何查询数据库的操作,所以你使用 duic 获取配置时响应速度非常的快(具体请看后面的性能测试报告)。

集群管理

在 duic 服务启动时会将启动服务的主机名与端口注册到数据库的 DUIC_SERVER 表中。当有人在控制台修改配置时,duic 会通知 DUIC_SERVER 表中的所有服务重载最新配置。同时 duic 内部还会轮询机制保证 JVM 内存永远都是最新的配置数据。

RESTful API

获取配置状态

GET /apps/states/{name}/{profiles}

监控配置状态

GET /apps/watches/{name}/{profiles}

获取配置

GET /apps/{name}/{profiles}

按需获取配置

GET /apps/{name}/{profiles}/{key}

性能报告

服务器配置:E5-2620V3(12核24线程 主频2.4GHz) / 16G
操作系统:Ubuntu 16.04
测试工具: wrk
Java 版本:1.8.0_161
JVM 参数

java -server -XX:+UseG1GC -Xms8g -Xmx8g -XX:MetaspaceSize=128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/ -XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:logs/gc.log

测试结果,每秒 duic 可达到 24760tps,服务的每个工作线程 CPU 已经达到 97% 以上,在这台设备中性能已经无法在继续提高了,这是我目前手上最好的服务器。

Running 1m test @ http://192.168.31.164:7777/api/v1/apps/meme/test-public
  12 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.91ms    1.01ms  38.21ms   93.70%
    Req/Sec     2.07k    92.01     2.71k    83.65%
  1486594 requests in 1.00m, 4.52GB read
Requests/sec:  24760.93
Transfer/sec:     77.10MB

CPU 报告

CPU报告

GC 报告

GC 报告

结语

duic 配置中心源码仓库 https://github.com/zhudyos/duic 欢迎大家提供任何意见,建议和吐槽。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355