包阅导读总结
1. 关键词:携程注册中心、微服务、整体架构、设计取舍、性能挑战
2. 总结:本文介绍了携程注册中心的整体架构与设计取舍,包括两层结构、多分片方案、单点故障应对、集群自发现等,还提到了应对突发流量、流量不均衡和全局风险的措施,以及后续规划,强调其稳定支撑业务复苏与扩张。
3. 主要内容:
– 背景
– 携程大部分业务完成微服务改造,注册中心面临性能挑战。
– 整体架构
– 分为数据层和会话层,数据层负责存放元信息等,会话层负责扛连接数等。
– 采用定时心跳、事件推送/保底轮询和多分片方案。
– 单点故障
– Data单点故障:心跳请求复制到多台Data,保证数据完整性和可用性。
– Session单点故障:任一Session故障,SDK切换到其他Session。
– 集群自发现
– 基于Redis,上线强依赖,运行时不依赖。
– 设计考量
– 选择普通哈希而非一致性哈希。
– Data用Java实现而非Redis。
– 注意场景
– 突发流量:做聚合与去重降低资源开销。
– 流量不均衡:引入全局调控保证Data流量均衡。
– 全局风险:对Data引入业务语义分组。
– 后续规划
– 优化单机性能,支持弹性扩缩容。
思维导图:
文章地址:https://mp.weixin.qq.com/s/X4yCtcrIOAWQaqwl7b3b7w
文章来源:mp.weixin.qq.com
作者:Siegfried
发布时间:2024/6/20 8:05
语言:中文
总字数:5319字
预计阅读时间:22分钟
评分:93分
标签:微服务,注册中心,架构,设计
以下为原文内容
本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com
Siegfried,携程软件技术专家,负责携程注册中心的研发。
目前,携程大部分业务已经完成了微服务改造,基本架构如图。每一个微服务的实例都需要和注册中心进行通讯:服务端实例向注册中心注册自己的服务地址,客户端实例通过向注册中心查询得知服务端地址,从而完成远程调用。同时,客户端会订阅自己关心的服务端地址,当服务端发生变更时,客户端会收到变更消息,触发自己重新查询服务端地址。
疫情刚过去那会,公司业务回暖迹象明显,微服务实例总数在1个月左右的时间里上涨30%,个别服务的单服务实例数在业务高峰时可达万级别。按照这个势头,预计全公司实例总数可能会在短时间内翻倍。
实例数变大会引起连接数变大,请求量变高,网络报文变大等一系列现象,对注册中心的性能产生挑战。
如果注册中心遇到性能瓶颈或是运行不稳定,从业务视角看,这会导致新增的实例无法及时接入流量,以至被调方紧急扩容见效慢;或者导致下线的实例不能被及时拉出,以至调用方业务访问到已下线的实例产生报错。
如今,业务回暖已经持续接近2年,携程注册中心稳定运行,强劲地支撑业务复苏与扩张,特别是支撑了业务日常或紧急情况下短时间内大量扩缩容的场景。今天就来简单介绍一下携程注册中心的整体架构和设计取舍。
二、整体架构
携程注册中心采用两层结构,分为和数据层(Data)和会话层(Session)。Data负责存放被调方的元信息与实例状态、计算RPC调用相关的路由策略。Session与SDK直接通讯,负责扛连接数,聚合转发SDK发起的心跳/查询请求。
注册 – 定时心跳
微服务架构下,服务端的一个实例( 被调方)想要被客户端(调用方)感知,它需要将自己注册到注册中心里。服务端实例会发起5秒1次的心跳请求,由Session转发到对应分片的Data。如果数据层能够持续不断的收到一个实例的心跳请求,那么数据层就会判断这个实例是健康的。
与此同时,数据层会对这一份数据设置TTL,一旦超过TTL没有收到后续的心跳请求,那么这份数据也就会被判定为过期。也就是说,注册中心认为对应的这个实例不应再被调方继续访问了。
发现 – 事件推送/保底轮询
当收到新实例的第一个心跳时,数据层会产生一个NEW事件,相对应地,当实例信息过期时,数据层会产生一个DELETE事件。NEW/DELETE事件会通过SDK发起的订阅连接通知到调用方。
由于网络等一些不可控的因素,事件推送是有可能丢失,因而SDK也会定时地发起全量查询请求,以弥补可能丢失的事件。
多分片方案
如图所示,Data被分成了多分片,不同分片的数据互不重复,从而解决了单台Data的垂直瓶颈问题(比如内存大小、心跳QPS等)。
Session会对服务ID进行哈希,根据哈希结果将心跳请求、订阅请求、查询请求分发到对应的Data分片中。调用方SDK对多个被调方进行信息查询时,可能会涉及到多个Data分片,那么Session会发起多个请求,并最终负责将所有必要信息聚合起来一并返回给客户端。
与很多其他系统类似,注册中心也会遇到故障/维护等场景从而遭遇单点故障。我们把具体情况分为Data单点故障和Session单点故障,在两种情况下,我们都需要保证系统整体的可用性。
单点故障 – Data
如图所示,SDK发起的心跳请求会被复制到多台Data上,以保证同一分片中每一台Data的数据完整性。也就是说,同一个分片的每台Data都会拥有该分片对应的所有服务的数据。当任一Data出现故障,或是参与到日常运维被踢出集群的情况下,其他任一Data能够很好的接替它的工作。
这样的多写机制相比于之前版本注册中心采用的Data间复制机制更加简单。在Data层发生故障时,当前方案对于集群的物理影响会更小,可以做到无需物理切换,因而也更加可靠。
在当前多写机制下,Data层的数据是最终一致的。心跳请求被分成多个副本后是陆续到达各个Data实例的,在实例发生上线或者下线时,每台data变更产生的时间点通常会略有不同。
为了尽可能避免上述情况对调用方产生影响,每台Session会在每个Data分片中选择一台Data进行粘滞。同时,SDK对Session也会尽可能地粘滞。
单点故障 – Session
参考上文提到Data分片方案,任一Session都可以获取到所有Data分片的数据,所有Session节点都具备相同的能力。
因此,任一Session故障时,SDK只需要切换到其他Session即可。
集群自发现
四、需要注意的场景
突发流量
在遇到节假日,或是公司促销活动,亦或是友商故障的情况下,公司集群会因为业务量急剧上升而迅速自动扩容,因而注册中心会受到强劲的流量冲击。
期间因为系统资源被榨干,注册/发现请求可能会偶发失败,事件推送延迟和丢失率会上升。严重时,部分调用方业务会无法及时感知到被调方的变动,从而导致请求失败,或流量无法被分摊到新扩容的被调方实例。
我们发现,这些场景产生的流量有着很高的重复度,比如某个被调方实例扩容,调用方的众多实例需要知道的信息是完全一样的,又比如调用方实例扩容,这些新扩的实例部署着相同的代码,它们依赖的被调方信息也是完全一样的。
因此我们针对性的做了不少聚合与去重,大大降低了突发流量情况下的资源开销。
流量不均衡
关于Data粘滞,这里有一个细节。那么多Data机器,Session选谁呢?目前Session是用类似随机的方式选择Data的。那就会有一个场景,我们对Data层进行版本更替,逐个实例重新发布,当一个实例被重置时,Session就会因为丢失粘滞对象而重新随机选择。
我们会发现,最后一个Data实例完成发布时,它不会被任何Session选中。而第一个发布的Data实例,它倾向于被更多的Session选中。
通常来说,越早发布的Data实例,就会被越多的Session选中。也正因为如此,更早发布的Data会承担更多的流量,而最后发布的Data一般不承担流量。这显然是不合理的。
解决这个问题的方法也很简单,我们引入拥有全局视角的第三者,整体调控Session的粘滞,保证Data尽可能地被相同数量的Session选中。
全局风险
前面也提到,Data层被分成了多分片,Session会对服务ID进行哈希,将心跳请求、订阅请求、查询请求分发到对应的Data层分片中。
当程序出现预期外的问题(程序bug,OOM等等)导致某个Data无法正常的履行功能职责时,那些被分配到这个Data实的服务就会受到影响。
如果调配方式是对服务ID做哈希,那么所有业务线的任意服务都可能参与其中,从业务视角去看,就是整个公司都受到了影响。
对服务ID做哈希是有它的优势的,它无需引入过多的外部依赖,只需要一小段代码就能工作。但我们还是认为避免全局故障更加重要。
因此我们最近对Data引入了业务语义,将Data分为多个组,以各个业务线命名。且我们可以按服务粒度对数据进行分配。默认情况下,我们会将服务分配到自己BU的分组上。
这样,我们就具备了以下能力:
1)不同业务线的数据可以被很好的隔离,任一业务线的Data数据出现问题,不会影响到其他业务线。
2)注册中心将获得故障切换的能力,当个别服务的数据出现问题时,我们可以将它单独切走。
3)我们可以将一些不重要的应用单独隔离到一个灰度分组,新代码可以先发布到灰度分组上,尽可能避免新代码引入的问题直接影响核心业务分组。
4)注册中心将获得应用粒度的部署能力。在集群分配上,具备更强的灵活度,针对业务规模的大小合理分配系统资源。
从图中可以看到,我们在引入分组逻辑的同时也兼容老的分片逻辑,这样做是为了在分组逻辑上线过程初期,服务信息在Data层的分布可以尽可能保持不变,可以让少数的服务先灰度切换到新增的分组上进行验证。
当然,从去复杂度的角度考虑,最终分片逻辑还是要下线,垂直扩容的能力也可以由分组实现。
五、后续规划
因为注册中心引入了分组机制,并对各个业务线数据进行了隔离,注册中心的集群规模也在因此膨胀,分组数量较多,运维成本也随之上升。
后续我们计划进一步优化优化单机性能,精简优化一些不必要的机制,降低机器数量。
【推荐阅读】