一、缘起
随着互联网业务的越来越复杂,用户量与流量越来越大, “服务化分层”是架构演进的必由之路 。
如上图:站点应用会调用服务,上游服务调用底层服务, 依赖关系会变得非常复杂 。
对于同一个服务,它有多个上游调用。为了保证高可用, 一个底层服务往往是若干个节点形成一个集群提供服务 。
如上图:用户中心服务 user-service 有三个节点, ip1/ip2/ip3 对上游提供服务,任何一个节点当机,都不影响服务的可用性。
那么 问题来了 ,当 服务集群增减节点的时候 ,是否存在“反向依赖”,是否“耦合”,是否 上游调用方需要修改配置重启 ,是否能做到上游无感知,即“配置的架构变迁”,是今天需要讨论的问题。
二、配置私藏
“配置私藏”是配置文件架构的最初级阶段,上游调用下游, 每个上游都有一个专属的私有配置文件 ,记录被调用下游的每个节点配置信息。
如上图:
1 )用户中心 user-service 有 ip1/ip2/ip3 三个节点
2 ) service1 调用了用户中心,它有一个专属配置文件 s1.conf ,里面配置了 us 的集群是 ip1/ip2/ip3
3 ) service2 也调用了用户中心,同理有个配置文件 s2.conf ,记录了 us 集群是 ip1/ip2/ip3
4 ) web2 也调用了用户中心,同理 w2.conf ,配置了 us 集群是 ip1/ip2/ip3
是不是很熟悉?
没错,绝大部分公司,初期都是这么玩的。
来看一个容量变化的需求:
1 )运维检测出 ip1 节点的硬盘性能下降,通知研发未来要 将 ip1 节点下线
2 )由于 5 月 8 日要做大促运营活动,未来流量会激增,研发准备 增加两个节点 ip4 和 ip5
需要 用户中心的负责人通知所有上游调用者 , 修改“私藏”的配置,并重启上游 ,连接到新的集群上去。 在 ip1 上没有流量之后 , 通知运维将 ip1 节点下线 ,以完成整个缩容扩容过程。
大伙是这么做的么?当业务复杂度较高,研发人数较多,服务依赖关系较复杂的时候,就没这么简单了。
问题一 : 调用方很痛 , 容量变化的是你,凭啥修改配置重启的是我 ?这是一个典型的“反向依赖”架构设计,上下游通过配置耦合,值得优化(特别是上层服务, ta 依赖的服务很多的时候,可能每周都有类似的配合重启需求)。
问题二 : 服务方很痛 , ta 不知道有多少个上游调用了自己 (特别是底层基础服务,像用户中心这种,调用 ta 的上游很多),往往只能通过以下方式来定位上游:
a ) 群里吼
b ) 发邮件询问
c ) 通过连接找到 ip ,通过 ip 问运维,找到机器负责人,再通过机器负责人找到对应调用服务
(似曾相识的请转发 =_= )
不管哪种方式,都很有可能遗漏,导致 ip1 一直有流量难以下线, ip4/ip5 的流量难以均匀迁移过来。 该如何优化呢?
三、全局配置
架构的升级并不是一步到位的,先来用最低的成本来解决上述“修改配置重启”的问题一。
“全局配置”法:对于通用的服务, 建立全局配置文件,消除配置私藏 :
1 ) 运维层面制定规范 , 新建全局配置文件 ,例如 /opt/globalconf/global.conf ,如果配置较多,注意做好配置的垂直拆分
2 ) 对于服务方 ,如果是通用的服务, 集群信息配置在 global.conf 里
3 ) 对于调用方 ,调用方禁止配置私藏, 必须从 global.conf 里读取通用下游配置
这么做的 好处 :
1 )如果下游 容量变化 , 只需要修改一处 配置 global.conf ,而不需要各个上游修改
2 ) 调用方下一次重启的时候 , 自动迁移 到扩容后的集群上来了
3 ) 修改成本非常小 , 读取配置文件目录变了
不足 :
如果调用方一直不重启,就没有办法将流量迁移到新集群上去了
答案是肯定的,只需要实现 两个并不复杂的组件 ,就能实现调用方的流量自动迁移:
1 ) 文件监控组件 FileMonitor
作用是监控文件的变化,起一个 timer ,定期监控文件的 ModifyTime 或者 md5 就能轻松实现,当文件变化后,实施回调。
2 ) 动态连接池组件 DynamicConnectionPool
“连接池组件”是 RPC-client 中的一个子组件,用来维护与多个 RPC-server 节点之间的连接。所谓 “动态连接池” ,是指 连接池中的连接可以动态增加和减少 (用锁来互斥或者线程安全的数据结构很容易实现)。
这两个组件完成后:
1)一旦全局配置文件变化,文件监控组件实施回调
2)如果动态连接池组件发现配置中减少了一些节点,就动态的将对应连接销毁,如果增加了一些节点,就动态建立连接, 自动完成下游节点的增容与缩容 。
四、配置中心
全局配置文件 是一个能够快速落地的, 解决“修改配置重启”问题 的方案,但它仍然 解决不了 ,服务提供方 “不知道有多少个上游调用了自己”这个问题 。
如果不知道多少上游调用了自己,
“按照调用方限流”
“绘制全局架构依赖图”
等需求便 难以实现 ,怎么办,可以 采用“配置中心”来解决 。
对比“全局配置”与“配置中心”的架构图,会发现 配置由静态的文件 升级为 动态的服务 :
1 )整个 配置中心子系统 由 zk 、 conf-center 服务, DB 配置存储与, conf-web 配置后台组成
2 )所有 下游服务的配置 , 通过后台设置在配置中心里
3 )所有 上游需要拉取配置 ,需要 去配置中心注册,拉取 下游服务配置信息( ip1/ip2/ip3 )
当下游服务需要扩容缩容时 :
4 ) conf-web 配置后台进行设置 ,新增 ip4/ip5 ,减少 ip1
5 ) conf-center 服务将 变更的配置推送给已经注册关注相关配置的调用方
6 )结合 动态连接池组件 ,完成 自动的扩容与缩容
配置中心的 好处 :
1 ) 调用方不需要再重启
2 )服务方从配置中心中很 清楚的知道上游依赖关系 ,从而实施按照调用方限流
3 )很容易从配置中心 得到全局架构依赖关系
痛点一、痛点二同时解决 。
不足 :系统复杂度相对较高,对配置中心的可靠性要求较高, 一处挂全局挂 。
五、总结
配置导致系统耦合,架构反向依赖。
上游痛: 扩容的是下游,改配置重启的是上游
下游痛: 不知道谁依赖于自己
一、配置私藏
二、全局配置文件
三、配置中心
大伙的配置架构进化到第几个步骤啦?欢迎留言。
若有收获,帮忙 转发 。
==【完】==
推荐阅读:
换IP的是你,凭啥重启的却是我?
来源: http://www.tuicool.com/articles/2QN7RfR