配置中心设计与实践
配置中心定义
服务集群的统一配置存储和管理系统,配置中心的特点:
- 独立于程序的只读变量
- 伴随应用这个生命周期
- 多种加载方式
- 权限控制,环境选择
解决的问题
- 配置热刷新,减少服务重启
- 随着业务和功能的复杂,需要配置的参数越来越多,不同服务依赖同一变量
- 对配置项的管理:环境,权限,生效时间等
可选方案
ZooKeeper、etcd可以作为配置中心,但二者直接作为配置中心缺少便捷的管理工具,缺乏权限管理机制。
开源产品
- Spring Cloud Config
- 淘宝的Diamond(阿里内部使用,针对Spring框架定制)
- 百度Disconf(针对Spring项目,依赖ZooKeeper)
- 携程Apollo(默认依赖Eureka做服务发现,存储依赖MySQL)
通过比较分析Apollo的功能最为丰富
Apollo详解
核心概念:
- application(应用):通过appId标识应用自身
- environment(环境):Apollo客户端获取当前应用运行的环境,例如:server.properties.env
- cluster(集群):不同的服务集群中同一个配置项可以有不同的值,例如:Zookeeper的地址
- namespace(命名空间):类似Spring Cloud Config的application.yml为公共配置,其他配置项都引入这个配置,命名空间可以设置多层。
架构设计
服务端设计
image.png图中从下向上看:
- Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端
- Admin Service提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面)
- Config Service和Admin Service都是多实例、无状态部署,所以需要将自己注册到Eureka中并保持心跳
- 在Eureka之上增加一层Meta Server用于封装Eureka的服务发现接口
- Client通过域名访问Meta Server获取Config Service服务列表(IP+Port),然后直接通过IP+Port访问服务,同时在Client侧会做Load balance、错误重试
- Portal通过域名访问Meta Server获取Admin Service服务列表(IP+Port),然后直接通过IP+Port访问服务,同时在Portal侧做Load Balance、错误重试
- 为了简化不是,时间上会把Config Service、Eureka和Meta Server三个逻辑上的角色部署在同一个JVM进程中
客户端设计
image.png实现原理:
- 客户度和服务端保持一个长连接,从而能够第一时间获得配置更新的推送
- 客户端还会定时通Apollo配置中心服务端拉取应用的最新配置:
- 防止推送机制失效导致配置不更新
- 客户端定时拉取时会上报本地版本,所以一般情况下拉取操作,服务端都会返回304-Not Modified
- 定时频率默认5分钟,可以配置修改
- 客户端从Apollo配置中心服务端获取到应用的最新配置后,会保存在内存中
- 客户端会把服务端获取到的配置在本地文件系统缓存一份:
- 在遇到服务不可用、网络不通时,依然能从本地恢复配置
- 应用程序从Apollo客户端获取最新的配置、订阅配置更新通知
Apollo配置更新推送实现
长连接实际上通过HTTP Long Polling实现:
- 客户端发起一个HTTP请求到服务端
- 服务端保持住这个链接60秒
- 如果在60秒内有客户端关心的配置变化,被保持住的客户端请求会立即返回,并告知客户端有配置变化的namespace信息,客户端会据此拉取对应namespace的最新配置
- 如果在60秒内没有客户端关心的配置变化,那么会返回HTTP状态码304给客户端
- 客户端收到服务端请求后立即重新发起连接,回到第一步
- 考虑到会有输完客户端向服务端发起长连接,在服务端使用了async server(Spring DeferredResult)来服务HTTP Long Polling请求
消息队列设计与实践
消息队列定义
消息队列技术是分布式应用间交换信息的一种技术:
- 消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序取走
- 通过消息队列,应用程序可独立地执行,不需要直达彼此的配置或再继续执行前不需要等到消费方接受此消息
应用场景:
- 异步通信
- 业务解耦:基于消息模型,关注“通知”,而非关注“处理”
- 错峰与流量控制
- 广播
- 保证时序
消息队列模型
- Pub/Sub发布订阅(广播):使用Topic作为通信载体
- P2P(点对点):使用Queue作为通信载体
业界产品
- RabbitMQ(Erlang)
- ZeroMQ(传输层,C语言)
- Apache ActiveMQ(Java)
- Redis
- Apache Kafaka(Scala,高可用:Zookeeper)
- Apache RocketMQ
- NSQ(Go)
- beanstalkd
生产环境推荐
高吞吐、可靠性可容忍场景,如日志处理:Kafaka
高可靠场景,如电商订单消息:RocketMQ
RocketMQ
包括四个部分:
- NameServer集群:提供轻量级的服务发现和Topic路由信息。Broker定时发送路由信息到NameServer中
- Broker:提供轻量级Topic和Queue机制。支持push和pull两种模式,有自身容错机制(2 Copies 或 3 Copies)
- Producer集群:通过负载均衡,向Broker集群发送消息。发送过程中支持快速衰竭和低延迟。拥有相同的Producer Group
- Consumer集群:消费者,支持分布式部署的push和pull模式,同时也支持几圈消费和消息广播
分布式请求跟踪系统设计与实践
实现方案:
基于日志的分布式请求跟踪系统:
- 业务侵入小
- 将每个系统分散的日志聚合起来,进行海量日志分析,生成有价值的数据
核心调用链:
- 每次请求都生成一个全局唯一的ID(TraceID),通过它将不同系统生成的日志串联在一起,重组成调用链
- 开发人员通过分布式请求跟踪链排查问题,也可以对多个请求进行统计和分析
应用场景:
- 调用链追踪:以图形化的方式梳理出各个Server端集群之间的调用关系,并记录整个调用过程的耗时,协助开发人员分析系统瓶颈与热点。
- 调用链路分析:整理集群之间的调用关系,计算出整个调用链路的关键节点、直接依赖、间接依赖、依赖强度等
- 调用来源分析:针对某一特定集群,整理出其他集群对其调用情况,防止错误调用情况的发生
- 调用量统计:实时统计各个集群的调用次数、QPS、平均耗时、最大耗时等信息,可以根据相关信息进行容量规划
网友评论