PHP灰度发布与AB测试系统实现
灰度发布和AB测试是产品迭代中的重要工具。它们可以在小范围内验证新功能的效果,降低发布风险。今天说说PHP中的灰度发布和AB测试实现。
灰度发布的核心是根据条件将流量分配到不同版本的服务上。条件可以是用户ID、IP、设备类型等。
```php
class GrayRelease
{
private array $rules = [];
private array $versions = [];
public function addVersion(string $name, callable $handler, int $weight = 0): void
{
$this->versions[$name] = ['handler' => $handler, 'weight' => $weight];
}
public function addRule(string $name, callable $matcher, string $version): void
{
$this->rules[] = [
'name' => $name,
'matcher' => $matcher,
'version' => $version,
];
}
public function getVersion(array $context): string
{
// 先检查规则
foreach ($this->rules as $rule) {
if (($rule['matcher'])($context)) {
echo "规则匹配: {$rule['name']} -> {$rule['version']}\n";
return $rule['version'];
}
}
// 加权随机
$totalWeight = array_sum(array_column($this->versions, 'weight'));
if ($totalWeight === 0) {
return array_key_first($this->versions);
}
$random = rand(1, $totalWeight);
$current = 0;
foreach ($this->versions as $name => $config) {
$current += $config['weight'];
if ($random <= $current) {
return $name;
}
}
return array_key_first($this->versions);
}
public function execute(array $context): mixed
{
$version = $this->getVersion($context);
$handler = $this->versions[$version]['handler'] ?? null;
if ($handler === null) {
throw new RuntimeException("版本处理器不存在: {$version}");
}
return $handler($context);
}
public function getStats(): array
{
return [
'versions' => array_map(fn($v) => $v['weight'], $this->versions),
'rules' => array_column($this->rules, 'name'),
];
}
}
$gray = new GrayRelease();
$gray->addVersion('v1', function ($ctx) {
return "旧版首页 (v1)";
}, 80);
$gray->addVersion('v2', function ($ctx) {
return "新版首页 (v2)";
}, 20);
// 内部用户优先体验新版本
$gray->addRule('内部用户', fn($ctx) => ($ctx['user_type'] ?? '') === 'internal', 'v2');
$gray->addRule('白名单用户', fn($ctx) => in_array($ctx['user_id'] ?? 0, [1001, 1002, 1003]), 'v2');
$gray->addRule('Android用户', fn($ctx) => ($ctx['platform'] ?? '') === 'android', 'v2');
$users = [
['user_id' => 1001, 'user_type' => 'normal', 'platform' => 'web'],
['user_id' => 5001, 'user_type' => 'internal', 'platform' => 'ios'],
['user_id' => 9001, 'user_type' => 'normal', 'platform' => 'android'],
['user_id' => 7001, 'user_type' => 'normal', 'platform' => 'web'],
];
foreach ($users as $user) {
echo "\n用户 {$user['user_id']} ({$user['user_type']}, {$user['platform']}):\n";
echo " " . $gray->execute($user) . "\n";
}
?>
```
AB测试系统可以更精细地控制实验:
```php
class ABTestExperiment
{
private string $name;
private array $variants;
private array $allocations = [];
private int $totalUsers = 0;
public function __construct(string $name, array $variants = ['control' => 50, 'treatment' => 50])
{
$this->name = $name;
$this->variants = $variants;
}
public function assign(int $userId): string
{
$key = "abtest:{$this->name}:{$userId}";
$hash = crc32($key);
$totalWeight = array_sum($this->variants);
$bucket = abs($hash) % $totalWeight;
$current = 0;
foreach ($this->variants as $variant => $weight) {
$current += $weight;
if ($bucket < $current) {
$this->allocations[$variant] = ($this->allocations[$variant] ?? 0) + 1;
$this->totalUsers++;
return $variant;
}
}
return array_key_first($this->variants);
}
public function track(int $userId, string $event, array $data = []): void
{
$variant = $this->assign($userId);
$log = json_encode([
'time' => date('Y-m-d H:i:s'),
'experiment' => $this->name,
'user_id' => $userId,
'variant' => $variant,
'event' => $event,
'data' => $data,
]);
file_put_contents("/tmp/abtest_{$this->name}.log", $log . "\n", FILE_APPEND);
}
public function getResults(): array
{
$results = [];
foreach ($this->variants as $variant => $weight) {
$results[$variant] = [
'weight' => $weight,
'users' => $this->allocations[$variant] ?? 0,
'percentage' => $this->totalUsers > 0
? round(($this->allocations[$variant] ?? 0) / $this->totalUsers * 100, 2) . '%'
: '0%',
];
}
return $results;
}
}
// 首页改版AB测试
$homepageTest = new ABTestExperiment('homepage_redesign', [
'old' => 50,
'new' => 50,
]);
$users = range(1, 10000);
foreach ($users as $userId) {
$variant = $homepageTest->assign($userId);
if ($variant === 'new') {
// 记录新版的点击率
if (rand(0, 9) < 3) {
$homepageTest->track($userId, 'click');
}
}
}
echo "AB测试结果:\n";
print_r($homepageTest->getResults());
?>
```
功能开关用于动态启用或禁用功能:
```php
class FeatureFlag
{
private Redis $redis;
private string $prefix = 'feature:';
public function __construct(Redis $redis)
{
$this->redis = $redis;
}
public function enable(string $feature): void
{
$this->redis->set("{$this->prefix}{$feature}", '1');
$this->redis->publish('feature_changes', json_encode([
'feature' => $feature,
'action' => 'enable',
'time' => time(),
]));
}
public function disable(string $feature): void
{
$this->redis->set("{$this->prefix}{$feature}", '0');
$this->redis->publish('feature_changes', json_encode([
'feature' => $feature,
'action' => 'disable',
'time' => time(),
]));
}
public function isEnabled(string $feature): bool
{
return (bool)$this->redis->get("{$this->prefix}{$feature}");
}
public function isEnabledFor(string $feature, int $userId, int $percentage = 50): bool
{
if (!$this->isEnabled($feature)) return false;
$hash = crc32("{$feature}:{$userId}");
return abs($hash) % 100 < $percentage;
}
}
?>
```
灰度发布和AB测试是产品迭代的安全网。它们让新功能可以逐步上线,出现问题可以快速回滚。灰度发布控制流量分配,AB测试验证功能效果,功能开关实现动态控制。三个工具配合使用,可以构建完整的发布管理体系。
PHP灰度发布与AB测试系统实现
张小明
前端开发工程师
数据缺失机制识别与插补实战:从MNAR判断到KNN/MICE选型
1. 这不是理论课,是数据清洗现场的急救包“Data Imputation in Machine Learning: A Practical, No-Nonsense Guide”——光看标题里那个“No-Nonsense”(不废话)就该明白:这不是在讲高斯过程回归插补的渐近收敛性,也不…
荔枝派Zero(全志V3S)从零到桌面:手把手教你用Buildroot构建完整Linux系统(含5寸屏驱动)
荔枝派Zero全志V3S开发实战:Buildroot构建完整Linux系统指南荔枝派Zero作为一款基于全志V3S处理器的开源硬件平台,凭借其紧凑的尺寸和丰富的接口,成为嵌入式开发者的理想选择。本文将详细介绍如何使用Buildroot工具链,从零开始构建…
STM32低功耗实战:用CubeMX配置停止模式,让你的电池供电设备续航翻倍
STM32低功耗实战:用CubeMX配置停止模式,让你的电池供电设备续航翻倍在物联网和便携设备开发领域,电池续航能力往往是决定产品成败的关键因素。想象一下,一个用于环境监测的传感器节点,如果因为功耗过高而需要频繁更换电…
STM32新手避坑指南:MQ-2烟雾传感器数字/模拟输出到底怎么选?附完整代码
STM32新手避坑指南:MQ-2烟雾传感器数字/模拟输出到底怎么选?附完整代码第一次接触STM32和MQ-2传感器的新手开发者,往往会在数字输出和模拟输出之间犹豫不决。这两种输出方式不仅仅是硬件连接上的差异,更关系到整个项目的设计思路和…
如何快速掌握MacVim:macOS平台最强大的文本编辑器完全指南
如何快速掌握MacVim:macOS平台最强大的文本编辑器完全指南 【免费下载链接】macvim Vim - the text editor - for macOS 项目地址: https://gitcode.com/gh_mirrors/ma/macvim MacVim作为macOS平台上最专业的文本编辑器,完美融合了Vim的高效编辑能…
CANN/asc-devkit:asc_eq矢量相等比较函数
asc_eq 【免费下载链接】asc-devkit 本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。 项目地址: https://gitcode.com/can…