作者简介
sh, 携程软件技术专家,关注性能优化、技术架构等领域。
团队热招岗位:软件技术专家
导读:本文来自携程刚刚上市的《全球化技术架构与实战》一书。携程集团自2016年起启动全球化战略,在全球化进程中,技术团队在挑战中学习,在磨砺中成长,积累了许多值得借鉴的经验。
全书以“全球化业务落地”为主线,深入剖析了从架构设计、流量调度、数据合规、基础设施,到体验优化、支付建设、客服系统及IT运维的完整技术实践,希望帮助出海企业规避技术陷阱,助力业务在海外平稳落地。
本月起,我们将推出4篇出海主题系列文章,带大家一起抢先看看新书中的部分精华内容。

一、引言
二、用户流量合规调度
三、调度模型
四、UCS系统的总体架构
五、小结
一、引言
绝大多数应用都依赖流量调度组件实现其核心功能。在业务全球化部署的过程中,各层流量调度组件都需要进行改造以应对全球化架构演进带来的挑战。作为全球化架构的“大脑”,UCS(Universal Control Service)的主要职责是为全球流量调度提供全局决策。UCS 作为总控组件,一方面需要考虑来自于各种业务场景的各类复杂流量调度需求,另一方面还需要为Region故障、迁移等全局场景提供统一的解决方案。
二、用户流量合规调度
用户会从全球各地发起访问,但是相关数据必须在该用户所属的合规区内封闭处理。UCS 需要具备根据用户当前请求的信息获得可以合规处理该用户数据的 Region 的能力,从而支持用户流量全球合规调度的语义。

根据用户会话状态的差异可以将用户请求大体分为两个场景:已登录请求以及未登录请求。
在已登录场景下,请求可以直接关联到用户账号,基于用户数据合规归属地进行调度,可以很好地满足已登录用户的流量调度需求。
用户数据合规归属地 (User Data Location,UDL) 是一个逻辑的概念,并不直接与物理部署相绑定;具有相同 UDL的账号遵循相同的法律法规,需要一致的行为。每个用户具有唯一确定的 UDL。基于 UDL 建立路由,可以确保请求在对应的合规区内处理。为满足容灾需求,每个合规区内会部署多个Region。通常情况下,为了保证数据的一致性,会指定UDL到就近Region的映射。
用户未登录时没有对应的账号信息,自然无法关联到对应的 UDL。此时,针对不同的场景可以采用不同的方式。
无状态的场景下(比如商品浏览或者一些本地化站点数据)可以采用就近访问的策略以获得最好的体验。
有部分业务流程是有状态的,为了保证用户体验的一致,在同一次会话内请求需要稳定路由到同一个 Region 进行处理。为了满足这样的场景,UCS 可以进一步以会话ID(会话ID是用于标记单次用户访问流程的唯一会话标识符。每次访问流程都拥有唯一的会话ID,便于追踪和管理单次会话内的访问请求)作为路由因子,来满足同一个用户单次会话时粘滞访问的需求。
此外,全球化架构会带来更为复杂的场景。UCS 还需要支持 Region 级的迁移以满足系统对稳定性与可用性的要求:
Region 故障:当Region故障时,为了保证业务的可用性,需要快速从故障Region切离。
合规区调整:当法律法规等影响合规区划分的因素变化时,若某些用户数据无法继续在当前合规区处理时,需要及时把对应的用户数据从该合规区迁出到新的合规区。
业务扩展:当业务扩张而需要在某个合规区内新增Region时,需要具备跨Region数据迁移和流量切换的能力。
三、调度模型
合规需求是全球化流量调度的核心,UCS系统维护了各合规区与对应的Region的映射关系,并确保每个Region名称在全局范围内唯一。如下面例子所示:
ComplianceArea_1=REGION_A,REGION_BComplianceArea_2=REGION_D,REGION_E
为了实现流量的合规调度,UCS的流量策略模型需要关注UDL到Region的映射。
以下是一个基础的 UDL 策略模型,它描述的调度场景是:在ComplianceArea_1所标记的合规区下,目前包含两个Region(REGION_A、REGION_B)和四组UDL(UDL_A、UDL_B、UDL_C、UDL_D)的用户数据,其中所有来自 UDL_A 与 UDL_B 的用户都路由到 REGION_A ,来自 UDL_C 与 UDL_D 的用户都路由到 REGION_B。
{ "input": [ "udl", "uid" ], "output": [ "region" ], "routes": [ { "key": "udl", "values": [ "UDL_A", "UDL_B" ], "partition": [ { "key": "uid", "range": "0-99", "output": [ "REGION_A" ] } ] }, { "key": "udl", "values": [ "UDL_C", "UDL_D" ], "partition": [ { "key": "uid", "range": "0-99", "output": [ "REGION_B" ] } ] } ]}
策略模型整体由三个部分组成:
"input" :表示策略的输入,UDL 策略会接收 UDL 与 UID 作为模型参数 ;
"output" :定义了策略的计算结果,在全球流量调度的场景下主要输出当前请求应该去往哪个Region;
"routes" :定义了一系列的匹配条件和路由计算规则。
在routes中,每条route的结构如下:
{ "key": "udl", "values": [ "UDL_C", "UDL_D" ], "partition": [ { "key": "uid", "range": "0-99", "output": [ "REGION_B" ] } ]}
对上述代码中相关参数解读如下。
"key" 和 "values" :指定了路由的匹配条件。上述例子的含义:从入参(可以来自请求头和全链路上下文,也可以来自API调用方的传参等)中获取 “udl”,当 “udl” 值包含在 "values" 内,则命中本路由。
"partition" :指定路由计算规则。上述例子的含义:以入参中的 “uid” 为分片键,通过哈希取模的方式计算该用户所在的分片,若计算得到的分片在 range 范围内,则返回对应的 Region。通过分片逻辑,UCS 既可以实现单用户的请求粘滞,也可以支持流量的逐步切换。
除UDL策略模型外,会话ID等策略模型也可以通过类似模型结构进行描述。
进一步考虑这样的场景:由于业务扩张,需要在ComplianceArea_1 内新建 REGION_C,REGION_C 在地理位置上与 UDL_A 所在的地区更近。为了提升用户体验,需要将 UDL_A 的用户流量逐步迁移到 REGION_C 处理。
首先,需要更新合规区和Region的映射关系,具体如下。
ComplianceArea_1=REGION_A,REGION_B,REGION_CComplianceArea_2=REGION_D,REGION_E
在 REGION_C 完成基础设施建设以及数据同步后,可以通过调整策略比例先将 10% 的 UDL_A 的用户迁移到 REGION_C 处理。模型配置如下:
{ "input": [ "udl", "uid" ], "output": [ "region" ], "routes": [ { "key": "udl", "values": [ "UDL_A" ], "partition": [ { "key": "uid", "range": "0-89", "output": [ "REGION_A" ] }, { "key": "uid", "range": "90-99", "output": [ "REGION_C" ] } ] }, { "key": "udl", "values": [ "UDL_B" ], "partition": [ { "key": "uid", "range": "0-99", "output": [ "REGION_A" ] } ] }, { "key": "udl", "values": [ "UDL_C", "UDL_D" ], "partition": [ { "key": "uid", "range": "0-99", "output": [ "REGION_B" ] } ] } ]}
整个灰度过程可以通过不断调整两个Region的"range"范围来完成。灰度完成后,最终配置如下:
{ "input": [ "udl", "uid" ], "output": [ "region" ], "routes": [ { "key": "udl", "values": [ "UDL_A" ], "partition": [ { "key": "uid", "range": "0-99", "output": [ "REGION_C" ] } ] }, { "key": "udl", "values": [ "UDL_B" ], "partition": [ { "key": "uid", "range": "0-99", "output": [ "REGION_A" ] } ] }, { "key": "udl", "values": [ "UDL_C", "UDL_D" ], "partition": [ { "key": "uid", "range": "0-99", "output": [ "REGION_B" ] } ] } ]}
上述例子通过一个简单的迁移场景介绍了 UCS 的调度能力,同样的机制也可以用在日常业务迁移、Region 故障降级等场景,如下表所示。

四、UCS系统的总体架构
UCS 的总体架构如下图所示:

其中:
UCS 控制台为 UCS 策略模型提供了完善的管理平台,包括策略的更新、发布以及各种故障场景的预案管理,并提供了 OpenAPI 以支持外部系统的对接。
配置中心提供了高效的配置推送通道,利用配置中心的能力可以支持策略的动态下发。
UCS 客户端支持了流量调度的核心功能,各组件与系统通过响应 UCS 客户端的决策实现业务应用的全球流量调度。UCS 客户端提供了以下的核心功能。
策略本地缓存:从配置中心按需加载应用使用到的路由策略到本地内存,并通过配置中心变更订阅机制及时同步最新版本。
策略路由计算:提供根据传入参数计算各种路由策略的API,供各个基础组件、中间件以及应用代码直接调用,统一各种路由策略的计算逻辑。
策略变更通知:提供路由策略变更通知订阅机制,供各个基础组件、中间件以及应用感知路由策略调整策略变更,以便在策略变更时做一些定制化的处理。如,消息系统在感知到策略变更时会对消费进度进行调整,避免消息的遗漏消费。
针对 Region 级故障降级的场景,可以再做实现上的优化。遇到 Region 级故障的时候,当前 Region 内的所有业务都需要进行可用 Region 的切换,此时需要对所有在故障Region有流量的策略进行降级操作。UCS 系统需要找到所有需要降级的策略进行变更,并推送变更到所有UCS使用方。这样的批量变更和推送会导致配置中心承受巨大压力,最终导致切换时间过长。是否能进一步优化这样的场景呢?答案是肯定的。为故障降级场景,UCS 引入了一个 Region 间降级映射蒙板,如下图所示。

蒙版的配置样例如下:
{ "source": "REGION_A", "targets": [ { "region": "REGION_C", "weight": 50 }, { "region": "REGION_D", "weight": 50 } ]}
Region 降级蒙版可以在不影响原有策略的基础上实现降级与回切逻辑,同时还能极大缩短切换时间。
故障发生时,UCS 无需分析受影响策略,消除不必要的计算
蒙版文件大小远小于策略模型文件大小,极大降低了配置中心的压力
五、小结
为了满足全球化架构下的流量调度需求,UCS 实现了灵活的策略模型,具备了描述全球流量调度策略的能力。各系统与组件通过与 UCS 的集成,支持业务实现更透明的全球化流量调度。整体的流量调度架构如下图所示。

【有奖互动】你所在的企业在出海过程中,遇到过哪些技术挑战?欢迎在评论区留言,点赞最高的评论将获得新书一本,截至12月26日24点。

【推荐阅读】

“携程技术”公众号
分享,交流,成长
2844

被折叠的 条评论
为什么被折叠?



