You need to enable JavaScript to run this app.
导航

A/B测试

最近更新时间2024.04.09 14:14:16

首次发布时间2023.02.15 19:04:52

A/B测试是互联网产品中常见的场景,主要是根据特定规则,将客户分为两部分,一组用作测试组,另外用作对照组。利用边缘函数,您可以简单的构建起A/B测试的环境,同时,也可以利用边缘函数的高并发和分布式优势做简单的数据统计处理工作。

简单的A/B测试

以下示例通过Cookie来决定A/B测试的对照组和测试组,如果Cookie中不包含信息,随机50%概率返回测试。

function handleRequest(request) {
  const NAME = "experiment-0"

  const TEST_RESPONSE = new Response("Test group")
  const CONTROL_RESPONSE = new Response("Control group")

  const cookie = request.headers.get("cookie")
  if (cookie && cookie.includes(`${NAME}=control`)) {
    return CONTROL_RESPONSE
  }
  else if (cookie && cookie.includes(`${NAME}=test`)) {
    return TEST_RESPONSE
  }
  else {
    const group = Math.random() < 0.5 ? "test" : "control" // 50/50 split
    const response = group === "control" ? CONTROL_RESPONSE : TEST_RESPONSE
    response.headers.append("Set-Cookie", `${NAME}=${group}; path=/`)

    return response
  }
}

addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request))
})

另外,您也可以利用边缘函数对测试组的页面做信息验证或错误统计。通常,测试部署的软件可能存在工程BUG等异常,您可以利用边缘函数做一些简单的数据分析。
以下示例统计了测试组的2xx,3xx,4xx,5xx分布信息,并且定时发送回中心做进一步分析。

let ttTestRequests = 0;
let tt2xx = 0;
let tt3xx = 0;
let tt4xx = 0;
let tt5xx = 0;
let ttOtherStatusCode = 0;

const uploadURL = 'http://www.example.com/analytic';
async function uploadStatus(e) {
  const obj = new Object();

  obj['totalRequests'] = ttTestRequests;
  obj['2xx'] = tt2xx;
  obj['3xx'] = tt3xx;
  obj['4xx'] = tt4xx;
  obj['5xx'] = tt5xx;
  obj['others'] = ttOtherStatusCode;

  await fetch(uploadURL, {method: 'POST', body: JSON.stringify(obj)});
}

// 隔 5s 之后向中心上传状态码分布信息
addEventListener('@timer(5)', uploadStatus);

//  对 testURL 根据概率进行A/B测试
function recordStatusCode(status_code) {
  ++ttTestRequests;
  if (status_code >= 200 && status_code < 300) {
    ++tt2xx;
  } else if (status_code >= 300 && status_code < 400) {
    ++tt3xx;
  } else if (status_code >= 400 && status_code < 499) {
    ++tt4xx;
  } else if (status_code >= 500 && status_code < 599) {
    ++tt5xx;
  } else {
    ++ttOtherStatusCode;
  }
}

const probability = 0.2;

const testURL = 'http://www.example.com/test';

async function handle(event) {
  // 根据概率进行测试
  if (Math.random() < probability) {

    // 对该 url 进行请求
    const r = await fetch(testURL);

    // 将请求状态码进行收集
    recordStatusCode(r.status);

    return r;
  } else {
    return fetch(event.request);
  }
}

addEventListener("fetch", event => {
  event.respondWith(handle(event))
})