假设你负责一个核心交易服务,同时面临一组运维需求:新版本需要金丝雀发布;调用方希望同可用区优先路由;大客户要求流量走专属实例;核心与非核心业务流量必须隔离。
这四个需求单独看都不复杂。但当它们同时存在时,问题的性质就变了:你需要的不是简单分组,而是“分组的分组的分组”。这正是服务分组从百万QPS演进到千万QPS时面临的核心矛盾。
什么是服务分组?
服务分组的本质,是将一个服务的全量实例集合按特定维度划分成若干子集,使流量调度、故障隔离和运维操作可以在更细的粒度上进行。
当一个服务只有几十个实例时,所有实例放在一个池子里,负载均衡器一视同仁。但随着实例规模增长到数百乃至数千,一个大池子的模式逐渐暴露瓶颈:发布时的爆炸半径无法控制,不同业务的流量互相干扰,故障时缺乏有效的隔离手段。分组就是对这些问题的回应。
不同QPS量级下,对分组的诉求有着显著差异:

从十万到百万:单维度分组的建立
在十万QPS量级,实例数量通常在几十到一两百之间,所有实例注册到同一个服务名下,调用方通过服务发现拿到完整列表,客户端负载均衡直接选择。这一阶段的核心矛盾不在分组,而在服务发现本身的可用性。
进入百万QPS量级,实例规模增长到数百甚至上千,问题开始凸显。发版时全量滚动更新,一旦新版本有缺陷,影响面就是全部流量。核心业务与非核心业务共用同一个服务池,非核心业务的突发流量可能挤占核心业务的资源。
百万QPS阶段通常引入单维度分组,即按某一个属性对实例进行划分:

实现方式相对直观:服务注册时为实例打上标签(如 group=canary),服务发现层按标签过滤,调用方只拿到目标子集。以发布阶段为分组维度为例:

这种方式在百万QPS量级运作良好:分组数量有限,通常不超过十几个,注册中心的压力可控,路由规则也比较简单。
百万到千万:单维度的结构性困境
驱动力:不只是QPS增长
需要先澄清一个认知:驱动分组策略从单维走向多维的,并不纯粹是QPS数字的增长,而是随着系统规模扩大,独立运维关切的数量在同步增加。
在百万QPS阶段,一个服务通常由一个团队维护,发布节奏统一,部署环境相对单一。但当系统向千万QPS演进时,往往伴随着:多可用区甚至多地域部署,多个业务线共用同一个基础服务,大客户要求独立的SLA保障,全链路灰度发布成为常态。这些运维关切各自独立,却需要同时作用于同一个实例池,这才是多维分组的真正驱动力。
笛卡尔积:单维思路的尽头
回到开篇的场景。如果只能按单一维度分组,要同时满足可用区调度、业务隔离、金丝雀发布和租户隔离,就不得不做分组的笛卡尔积:为每一种组合创建独立的分组。
在3个可用区、2个业务优先级、2个发布阶段、2种租户类型的场景下,理论上需要 3×2×2×2 = 24个分组。如果再加一个集群维度(比如同城双活的2个集群),就变成48个。

笛卡尔积分组的问题不仅仅是分组数量多,它带来的是一系列连锁的运维困境:

这就是单维分组思路的尽头:当需要同时满足的运维维度超过两个时,静态组合的方式在管理成本上不可持续。
多维分组的设计
核心思想:维度独立,路由时组合
多维分组的核心思想是:每个维度独立管理,路由时按优先级依次过滤,而不是预先组合成静态分组。
每个服务实例携带多个标签,每个标签对应一个维度。路由决策时,按照预定义的维度优先级依次缩小候选集,最终得到满足所有条件的实例子集:

与笛卡尔积式分组相比,这种方式在管理复杂度上是加法(各维度之和)而非乘法(各维度之积)。新增一个维度只需要定义该维度的标签和过滤规则,不影响已有维度的配置。
硬维度与软维度
多维过滤面临的第一个设计问题是:如果某一层过滤后候选集为空或过小怎么办?
不是所有维度都具有同等的刚性。在实际系统中,维度可以分为两类:
- 硬维度:必须严格满足的约束,过滤后即使候选集为空也不允许放松,典型如发布阶段隔离(金丝雀流量绝不能泄漏到正式组)。
- 软维度:尽力满足的偏好,过滤后如果候选集过小可以降级放宽,典型如同可用区优先(当本AZ实例不足时允许跨AZ调用)。

区分硬维度和软维度的意义在于:它决定了过滤链中每一步的退路。硬维度构成了不可逾越的隔离边界,软维度提供了弹性调度的空间。
级联降级:过滤链的回退路径
真实系统中的降级往往不是简单的“放开这一层”,而是有优先序的级联过程。当多个软维度同时参与过滤时,需要明确先放松哪一个。
以下流程展示了过滤链中遇到候选集不足时的级联回退逻辑:

级联降级的顺序设计需要结合业务语义。一般原则是:硬维度不参与降级,软维度按对业务影响从小到大的顺序依次放松。比如同AZ优先通常是最先被放松的维度(跨AZ调用仅增加几毫秒延迟),而租户隔离的降级虽然允许,但通常排在更靠后的位置(涉及SLA承诺)。
路由计算的性能考量
多维过滤在逻辑上是逐层缩小候选集的过程。在百万QPS阶段,实例数量有限,即使全量遍历过滤也不是瓶颈。但在千万QPS阶段,单个服务的实例数可能达到数千,调用方每秒需要做大量路由决策,过滤过程的效率就变得重要了。
常见的优化思路是将过滤计算从请求路径移到数据变更路径:当实例列表或标签发生变化时,在本地Agent侧预先按常见的维度组合构建索引,路由时直接查表而非实时过滤。

这里有一个粒度选择的问题。如果对所有可能的维度组合都预计算,本质上又回到了笛卡尔积。实际做法通常是只对高频请求路径(即真实流量中常见的维度组合)预建索引,低频组合仍然走实时过滤。这样既保证了热路径的性能,又避免了索引膨胀。
多维分组的典型应用
多维分组并不是所有场景都需要。它的价值主要体现在以下几类典型场景中。
全链路灰度发布是多维分组最经典的应用。在微服务架构下,一次功能发布往往涉及多个服务的联动更新。全链路灰度要求一条请求链路上的所有服务都使用同一泳道内的实例。泳道本质上是一个跨服务的分组维度,它需要与可用区、业务优先级等已有维度共存:

多租户隔离在SaaS类产品中尤为常见。大客户要求资源隔离,租户维度需要与可用区维度结合,确保大客户流量既走专属实例,又能就近调度。
混合云与多集群调度场景下,集群本身是一个新的分组维度。当服务部署在多个集群或混合云环境中时,集群维度需要与业务优先级、发布阶段等维度协同工作。
代价与取舍
多维分组不是没有成本的。在决定引入之前,需要清楚它带来的额外复杂度。
- 概念复杂度上升:运维人员需要理解维度、标签、过滤优先级、硬软维度、降级策略等一整套概念体系。“这个实例属于A组”的直觉,变成了“这个实例在可用区维度属于AZ-A,在优先级维度属于核心,在发布维度属于正式”,认知负担明显增加。
- 容量规划更复杂:单维分组时,只需要保证每个分组内有足够的实例。多维分组时,需要确保在各种维度组合下都有合理的实例覆盖,尤其要避免某些组合变成空集触发降级。
- 可观测性要求更高:当流量经过多层维度过滤时,排查问题需要知道每一层过滤的决策结果。如果缺乏相应的观测手段,多维分组反而会让故障定位更困难。
对于大多数百万QPS级别的系统,单维度分组配合合理的运维流程已经足够。多维分组的引入时机,通常是当你发现自己不得不维护大量笛卡尔积式的静态分组,或者频繁出现“改一个维度的策略需要同步修改十几个分组”的情况时。
演进路线总结
服务分组的演进,本质上反映了流量治理从粗放走向精细化的过程:

从百万到千万的演进中,服务分组的变化可以概括为一句话:从为每种场景预设一个静态分组,转变为为每个维度定义规则,由路由层动态组合。
分组数量的管理复杂度,从维度之积变成了维度之和,这是多维分组最本质的架构收益。
本文探讨了服务分组在应对高并发复杂场景时的演进思路,更多关于分布式系统与架构设计的深度讨论,欢迎访问云栈社区进行交流。