问题描述
是否可以在一个 CNAME 下在两个目标之间动态路由?我找不到 Cloudflare 工作人员或页面规则可以完成此操作的任何特定文档。
对于上下文,我的团队正在尝试在两个已部署的 Heroku 应用程序之间进行 A/B 测试,如“a-test.herokuapp.com”所示,它是控件,而“b-test.herokuapp.com”是我们的B 测试。
我希望 Cloudflare 工作人员能够在幕后在这两个目标之间动态路由,同时保持我们的 URL 相同,例如app.domain.com。
有人知道这是否可行,如果可以,是否有任何相关文档?谢谢!
解决方法
您可以通过 Worker 做到这一点。您的代码如下所示:
addEventListener("fetch",event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
let url = new URL(request.url);
if (isInGroupA(request)) {
url.hostname = "a-test.herokuapp.com";
} else {
url.hostname = "b-test.herokuapp.com";
}
return fetch(url,request);
}
function isInGroupA(request) {
// write your logic that chooses between A and B here...
}
,
方法一:
因此,Cloudflare 有一个使用 Worker 的 A/B Testing example。此方法使用 cookie 来实现您的需要。这将是大多数情况下的首选方法。
function handleRequest(request) {
const NAME = "experiment-0"
// The Responses below are placeholders. You can set up a custom path for each test (e.g. /control/somepath ).
const TEST_RESPONSE = new Response("Test group") // e.g. await fetch("/test/sompath",request)
const CONTROL_RESPONSE = new Response("Control group") // e.g. await fetch("/control/sompath",request)
// Determine which group this requester is in.
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 {
// If there is no cookie,this is a new client. Choose a group and set the cookie.
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))
})
方法二:
另一种方法是使用 Cloudflare Loadbalancer。假设您有两个源服务器(A 和 B),并在两者上配置了一个域,您可以使用十进制百分比等效指标(0.1 到 1)将请求拆分到任一服务器。例如。您可能有 40% 的请求进入 A 环境,60% 的流量进入 B 环境。
方法 3:
您也可以考虑Cloudflare Tunnels,现在可以免费使用。同样,这取决于您拥有的配置/设置,但隧道允许零 ip 设置。不需要在两个源服务器 IP 之间进行负载平衡,您只需在使用 Tunnel ID 运行的 Tunnel 服务的一个或两个实例之间进行负载平衡。您基本上是通过负载平衡器设置建立隧道。