
前阵子有个做百度竞价的老哥来找我看数据,说他们那边同时在跑斗篷分流和落地页A/B测试,结果A/B测试的转化数据一会儿高一会儿低,同一个版本放在不同时段跑出来的差距能拉到两成往上。可只要把斗篷关掉,单独跑A/B测试,数据又稳得跟条直线似的。他一开始怀疑是A/B测试工具本身有问题,查了半天也没查出个所以然。后来一起捋了一遍请求链路才发现,问题压根不在A/B测试那里——是斗篷分流和A/B测试共用了同一套流量标记和规则判定链路,两组变量搅在一起互相打架了。要治这个毛病,得在准备、执行、复盘这三个阶段分别把变量隔离开。
先分清两套逻辑各自在读写什么变量
斗篷分流和A/B测试都涉及流量切分,这个没错,但它们操作的对象根本不是一回事。斗篷那边读写的是访问来源特征、请求环境信号、放行条件这些东西;A/B测试读写的是页面版本标识、实验分组、转化事件归属。麻烦就麻烦在,这两套逻辑在同一个请求生命周期里跑的时候,会共用一部分中间变量。
共用变量主要出在三个地方:
- 流量标记这一块,斗篷分流一般会给请求打个来源标记,A/B测试也可能给同一个请求打实验分组标记。要是两个标记写进了同一个字段或者同一个Cookie键,那后写的就会把先写的盖掉。
- 规则触发顺序也是重灾区。斗篷的放行判定和A/B测试的分组判定如果都塞在服务端中间件里执行,谁先谁后直接决定最终跳转目标。
- 还有决策日志。两套逻辑如果往同一份日志里写,分流结果和实验分组就混成一锅粥了,复盘的时候你根本分不清到底是哪个变量把转化差异带出来的。
准备阶段最核心的事,就是在配置层面把这三类变量塞进不同的命名空间,顺便把执行顺序敲死。后面按阶段一个个说。
准备阶段:流量标记分层与规则命名空间划分
流量标记用独立字段,不要复用同一个Cookie键
斗篷分流和A/B测试各自都需要给请求打标记,这俩标记必须写到不同的键名里去。具体怎么操作呢:斗篷分流的标记,建议写进一个专门的服务端变量或者独立的Cookie键;A/B测试的实验分组,写到另一个独立键。假如两个标记都往同一个键里塞,后执行的逻辑就会覆盖先执行的,后续请求里分流结果直接就丢了。
验证方法其实挺简单——在测试环境构造一个同时命中斗篷放行条件和A/B测试分组的请求,然后看两个标记是不是同时存在于请求上下文里。只看到一个,那就是被覆盖了,没跑。
规则引擎按功能划分命名空间
如果斗篷分流和A/B测试共用同一个规则引擎,规则ID和优先级就得按区间来管。打个比方,斗篷分流规则占一个ID段,A/B测试规则占另一个ID段,优先级计算的时候不允许跨区间仲裁。这么干的好处是,你调A/B测试的分组比例时,不会莫名其妙把斗篷分流的命中顺序给改了。
但这里有个限制:如果规则引擎本身不支持命名空间,那就得在配置层手动约定ID前缀,部署前还得做一次冲突扫描,确认两个区间的规则没有交叉引用。这一步别偷懒,跳过的话后面排查起来很要命。
执行顺序先定下来再配规则
斗篷分流和A/B测试谁先执行,会直接影响跳转结果。通常就两种选法:先做斗篷放行判定,再做A/B分组;或者反过来,先A/B分组,再走斗篷判定。两种顺序都能跑,但必须在准备阶段就定死,写进配置文档里。
要是先做A/B分组,斗篷分流后面命中时会基于已经分好组的流量再筛一遍,可能出现某些分组流量被斗篷规则整体过滤掉的情况,实验样本量就不够了。先做斗篷放行的话,A/B测试只对放行后的流量做分组,样本更干净,可放行率的波动会直接影响实验进度。选哪个,看斗篷放行率稳不稳。
执行阶段:请求链路中的变量传递与隔离
请求上下文里给两套变量分配独立存储位置
请求进到服务端之后,斗篷分流和A/B测试的判定结果要写进请求上下文的不同属性里。斗篷分流的放行结果写一个专用的上下文对象,A/B测试的分组结果写另一个。后面跳转逻辑读这两个属性时,各从各的位置取值,不交叉引用。 操作上有个点要注意:如果中间件层做了上下文序列化或者透传,得确认两个变量序列化之后还是独立的。有些框架在序列化时会把所有自定义属性合并到一个扁平对象里,键名冲突就来了。验证方法是打印序列化前后的上下文对象,对比键名和值,一眼就能看出来。
跳转目标拼接时不要互相覆盖
A/B测试一般会给落地页URL追加实验分组参数,斗篷分流可能也会追加来源标记参数。两个逻辑都往URL上追加参数的话,参数名的前缀规则得提前约定好,不然同名参数就会互相覆盖。 比如说,斗篷分流的参数用固定前缀,A/B测试的参数用另一个前缀。拼接时按顺序追加,不做去重合并。这样即使两边都追加了参数,URL上也能同时保留两组信息,后续归因的时候从参数名就能区分来源。
决策日志分离写入
斗篷分流的决策日志和A/B测试的分组日志,建议写到不同的日志通道;或者在同一份日志里用不同字段区分开。混在一起写的话,复盘时你很难区分转化差异到底是分流策略调整带来的,还是实验分组变化带来的。 写入频率方面,流量量级大的话,A/B测试的分组日志可以按采样比例写,斗篷分流的决策日志按全量或者高采样写。两条日志通过请求ID关联,复盘时按需拼接就行。
复盘阶段:归因口径对齐与交叉验证
先确认归因口径是否一致
复盘时最容易踩的坑,是斗篷分流和A/B测试用了不一样的归因窗口或者转化定义。举个例子,斗篷分流的转化统计按点击后24小时算,A/B测试的转化统计按会话内算,这两边的转化率压根没有可比性。
所以复盘前第一件事,就是核对两套逻辑的归因口径:转化事件定义一致吗?归因窗口一致吗?去重规则一致吗?有一样对不上,先对齐口径再比数据。
交叉验证怎么做?固定斗篷分流策略不动,只调A/B测试的分组比例,然后观察斗篷分流的放行率和转化数据稳不稳。如果斗篷侧的数据也跟着波动,那变量之间就有污染。 反向验证也是一样的道理:固定A/B测试分组不变,只调斗篷分流的放行条件,看A/B测试各分组的转化差异是不是收敛了。差异反而扩大的话,说明分流策略的变化影响了实验分组的结果。
实战复盘:一个家居流量团队的踩坑过程
之前接触过一个做家居流量站的团队,日均百度竞价点击量在一千二三左右,服务器是两台4核8G的云主机,前面挂了一层CDN。他们同时在跑斗篷分流和落地页A/B测试,A/B测试分两组,各占五成流量。 他们踩的坑是什么呢——斗篷分流和A/B测试都把标记写进了同一个Cookie键。斗篷分流先执行,写入来源标记;A/B测试后执行,写入实验分组,顺手把来源标记给盖了。结果后续请求里斗篷分流读不到来源标记,放行判定回退到了默认策略,一部分本该放行的流量被拦掉了。A/B测试那边也没跑掉,实验分组标记偶尔被斗篷的后续逻辑重置,分组数据出现了漂移。
调整过程分了三步:第一步,把斗篷分流的标记和A/B测试的分组标记拆到两个独立的Cookie键,中间件层加了键名冲突检查。第二步,调整执行顺序,先做斗篷放行判定,再做A/B分组,确保实验分组只作用于放行后的流量。第三步,两套决策日志拆到不同日志文件,通过请求ID关联,复盘时分别统计。
调整后的状态:斗篷放行率稳在之前的水平,波动幅度从原来的两成多收窄到百分之五点几。A/B测试两组的转化差异从忽高忽低变成了稳定的可比较区间,虽然差异绝对值不大,但至少数据可信了。服务器资源占用没什么明显变化,CDN侧的缓存命中率也维持原样。
配置检查清单:上线前和复盘时各看一遍
上线前检查项
- 斗篷分流标记和A/B测试分组标记是否写入了不同的键名或字段?
- 规则引擎中两套规则的ID段或命名空间是否已划分,是否存在交叉引用?
- 执行顺序是否已确定并写入配置文档,中间件层的执行顺序是否与文档一致?
- 请求上下文序列化后,两套变量是否仍然保持独立?
- URL参数拼接是否有前缀约定,是否存在同名参数覆盖风险?
- 决策日志是否分离写入,请求ID是否可用于关联?
复盘时检查项
- 两套逻辑的转化事件定义、归因窗口和去重规则是否一致?
- 固定一侧策略、调整另一侧时,两侧数据是否出现联动波动?
- 决策日志中是否存在同一请求被两套逻辑重复标记的情况?
- 分流放行率和实验分组比例的变化趋势是否在预期范围内?
常见问题
斗篷分流和A/B测试能不能共用同一套规则引擎?
共用是可以的,但规则ID、优先级和日志字段上必须做隔离。共用引擎的好处是运维成本低,坏处是规则冲突排查起来更复杂。团队规模不大、规则数量不多的情况下,共用引擎加命名空间隔离是可行的;规则数量已经上百条了,那就建议拆到独立的规则模块去。 至少要做到三点:标记不互相覆盖、执行顺序明确、日志可分别归因。这三点做到了,大部分变量污染问题就能排除。流量量级大、实验频率高的话,还需要在中间件层加冲突检测和告警。
执行顺序选先斗篷还是先A/B?
斗篷放行率稳定、波动小,那就先斗篷后A/B,实验样本不受放行率波动干扰,更干净。斗篷放行率本身波动较大,先A/B后斗篷可以让实验分组覆盖全量流量,但得接受部分分组流量被斗篷过滤后样本量不足的风险。选择依据是放行率的稳定程度,跟哪个更“正确”没关系。