如何使用 Cloudflare Worker 实现延迟测试工具
在这篇教程中,我们将学习如何使用 Cloudflare Worker 创建一个简单的延迟测试工具。这个工具可以测量多个 URL 的响应延迟,并根据结果重定向用户,同时在页面上显示每个 URL 的延迟信息,使用不同的颜色来指示延迟的高低。
准备工作
- 注册 Cloudflare 账户:如果你还没有 Cloudflare 账户,访问 Cloudflare 官网 注册一个账户。
- 创建一个新的 Worker:在 Cloudflare 的控制面板中,选择 “Workers” 并创建一个新的 Worker。
实现步骤
1. 事件监听
首先,我们需要设置一个事件监听器,来处理所有传入的请求。当请求到达时,我们将调用 handleRequest
函数。
1 2 3
| addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); });
|
2. 构建 HTML 内容
在 handleRequest
函数中,我们将生成一个包含加载动画和结果显示区域的 HTML 页面。以下是 HTML 模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| async function handleRequest(request) { const htmlContent = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Latency Test</title> <style> body { background: linear-gradient(135deg, #e2e2e2, #ffffff); animation: backgroundAnimation 10s infinite alternate; height: 100vh; display: flex; justify-content: center; align-items: center; flex-direction: column; margin: 0; } .loader { border: 16px solid #f3f3f3; border-radius: 50%; border-top: 16px solid #3498db; width: 120px; height: 120px; animation: spin 2s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } #result { display: none; opacity: 0; transition: opacity 0.5s; text-align: center; font-size: 20px; color: #3498db; } @keyframes backgroundAnimation { 0% { background-color: #ffffff; } 100% { background-color: #f3f3f3; } } </style> </head> <body> <div class="loader" id="loader"></div> <div id="result"></div> <script> // JavaScript 代码 </script> </body> </html>`; return new Response(htmlContent, { headers: { 'Content-Type': 'text/html' }, }); }
|
加载动画示例:
3. 测量延迟
创建一个名为 measureLatency
的函数,该函数将发送一个 HEAD
请求来测量 URL 的延迟。
1 2 3 4 5 6 7 8 9 10
| async function measureLatency(url) { const start = Date.now(); try { await fetch(url, { method: 'HEAD' }); return Date.now() - start; } catch (error) { console.error('Error measuring latency:', error); return Infinity; } }
|
4. 根据延迟重定向
在 testLatency
函数中,我们将调用 measureLatency
测量两个 URL 的延迟,并根据结果决定重定向到哪个 URL。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| async function testLatency() { const cfPagesUrl = 'https://666.com'; const vercelUrl = 'https://888.com';
const cfPagesLatency = await measureLatency(cfPagesUrl); const vercelLatency = await measureLatency(vercelUrl);
const resultElement = document.getElementById('result'); const loaderElement = document.getElementById('loader');
loaderElement.style.display = 'none'; resultElement.style.display = 'block';
let targetUrl; if (cfPagesLatency < vercelLatency) { resultElement.innerText = 'Redirecting to CF Pages...'; targetUrl = cfPagesUrl; } else { resultElement.innerText = 'Redirecting to Vercel...'; targetUrl = vercelUrl; } }
|
5. 显示延迟信息
动态更新结果区域,显示各个 URL 的延迟,并使用不同的颜色来指示延迟等级:
1 2 3 4 5 6 7 8 9 10
| function getColorForLatency(latency) { if (latency < 100) return 'green'; else if (latency < 300) return 'orange'; else return 'red'; }
const cfPagesMessage = \`CF Pages 延迟: <span style="color:\${getColorForLatency(cfPagesLatency)};">\${cfPagesLatency} ms</span>\`; const vercelMessage = \`Vercel 延迟: <span style="color:\${getColorForLatency(vercelLatency)};">\${vercelLatency} ms</span>\`; resultElement.innerHTML += '<br>' + cfPagesMessage + '<br>' + vercelMessage;
|
结果动画示例:
6. 完整代码 (2024-11-15优化了一下代码)
将所有部分结合在一起,以下是完整的 Cloudflare Worker 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); });
async function handleRequest(request) { const htmlContent = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Latency Test</title> <style> body { background: linear-gradient(135deg, #e2e2e2, #ffffff); animation: backgroundAnimation 10s infinite alternate; height: 100vh; display: flex; justify-content: center; align-items: center; flex-direction: column; margin: 0; }
.loader { border: 16px solid #f3f3f3; border-radius: 50%; border-top: 16px solid #3498db; width: 120px; height: 120px; animation: spin 2s linear infinite; }
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
#result { display: none; opacity: 0; transition: opacity 0.5s; text-align: center; font-size: 20px; color: #3498db; }
@keyframes backgroundAnimation { 0% { background-color: #ffffff; } 100% { background-color: #f3f3f3; } } </style> </head> <body> <div class="loader" id="loader"></div> <div id="result"></div> <script> async function measureLatency(url, retries = 3) { let latency = Infinity; // 初始化为最大值 for (let i = 0; i < retries; i++) { const start = Date.now(); try { await fetch(url, { method: 'HEAD' }); latency = Date.now() - start; break; // 如果成功,跳出循环 } catch (error) { console.warn(\`Retry \${i + 1} failed for \${url}\`); } } return latency; }
function getColorForLatency(latency) { if (latency < 100) return 'green'; if (latency < 300) return 'orange'; return 'red'; }
async function testLatency() { const urls = [ { name: 'CF Pages', url: 'https://cf.666.com/' }, { name: 'Vercel', url: 'https://vc.888.com/' }, { name: 'GitHub', url: 'https://gh.666.com/' }, { name: 'Netlify', url: 'https://nl.888.com/' }, { name: '备用', url: 'https://blog.666.com/' } ];
const results = await Promise.all( urls.map(async ({ name, url }) => { const latency = await measureLatency(url); return { name, url, latency }; }) );
results.sort((a, b) => a.latency - b.latency);
const resultElement = document.getElementById('result'); const loaderElement = document.getElementById('loader');
loaderElement.style.display = 'none'; resultElement.style.display = 'block';
results.forEach(({ name, latency }) => { resultElement.innerHTML += \`\${name} 延迟: <span style="color:\${getColorForLatency(latency)};">\${latency} ms</span><br>\`; });
const bestOption = results[0]; resultElement.innerHTML += '<br>Redirecting to ' + bestOption.name + '...';
setTimeout(() => { resultElement.style.opacity = 1; setTimeout(() => { window.location.href = bestOption.url; }, 2000); }, 100); }
window.onload = testLatency; </script> </body> </html>`;
return new Response(htmlContent, { headers: { 'Content-Type': 'text/html' }, }); }
|
运行和测试
如需要增加或修改 URL,只需要修改 urls
数组。如下面代码中,我们添加了两个 URL:
1 2 3 4 5 6 7 8 9 10
| async function testLatency() { const urls = [ { name: 'CF Pages', url: 'https://cf.666.com/' }, { name: 'Vercel', url: 'https://vc.888.com/' }, { name: 'GitHub', url: 'https://gh.666.com/' }, { name: 'Netlify', url: 'https://nl.888.com/' }, { name: '备用', url: 'https://blog.666.com/' }, { name: '新URL1', url: 'https://newurl1.com/' }, { name: '新URL2', url: 'https://newurl2.com/' } ];
|
完成上述步骤后,保存并部署你的 Worker。打开分配给你的 Worker 的 URL,你应该能看到加载动画,随后页面将显示测量的延迟和重定向信息。
结语
通过本教程,你学会了如何使用 Cloudflare Worker 创建一个延迟测试工具。