用 Cloudflare Workers 搭 IPTV 频道目录:架构选型与踩坑
IPTV 频道目录有三个核心痛点:源地址动辄上万条、几天就失效一批、用户分布在全球各地。传统方案是在多个机房部署反向代理和 CDN,运维成本直接劝退。
Cloudflare Workers 的思路不同——代码跑在 300+ 边缘节点上,请求落在最近节点,不需要回源到中心机房。配合 D1(边缘 SQLite)和 KV 缓存,整套服务对个人项目几乎零成本(免费额度足够覆盖日常运行),延迟在毫秒级。下面从数据流、去重方案、性能优化、踩坑记录四个方面把这套架构拆开讲清楚。
为什么选 Workers + D1
边缘执行解决全球延迟
IPTV 查询请求分散在全球各地,传统方案要部署多机房才能降低延迟,运维成本高。Workers 一次部署到 300+ 节点,用户请求自动落到最近的边缘,延迟直接压到毫秒级,不需要额外配置。
D1 是什么,为什么够用
D1 是 Cloudflare 提供的边缘 SQLite,跑在边缘节点上,不用自己管连接池、备份、扩缩容。对频道目录场景,几个能力刚好够用:
- 零运维——不用管连接池、不用备份
- 事务支持——批量写入频道数据时保证一致性
- SQL 灵活——GROUP BY、窗口函数都能用,做频道分类统计很方便
- 免费额度足够——小规模项目跑下来几乎不花钱
对比自己写文件模拟数据库的方案,D1 在并发读写上是质的飞跃。
KV 缓存:把热点数据留在边缘
频道列表一天更新一次,但查询可能每秒几百次。把热点国家的频道列表放进 KV(Cloudflare 的键值缓存),D1 的查询量可以减少 90% 以上。策略很简单:
- 第一次查询:走 D1,结果写入 KV(1 小时过期)
- 后续查询:KV 命中直接返回
- 每日定时任务:刷新 KV 缓存,保证数据新鲜
核心架构怎么搭
数据流
复制
M3U8 源文件 → Python 解析器 → D1 存储 → KV 缓存 → Workers API → 前端
每天用 cron 定时刷新数据。
频道哈希去重
每个频道的播放 URL 经常带动态参数(时间戳、session ID),直接比对字符串会产生大量重复。解决办法:对 play_url 做 SHA-256 哈希,取前 8 位当 channel_hash 存进数据库。
python
复制
import hashlib
hash_str = hashlib.sha256(play_url.encode()).hexdigest()[:8]
这样即使 URL 后面的参数变了,只要基础地址相同就能匹配上。
M3U 订阅生成
用户勾选几个频道,系统实时生成标准 M3U 内容。EXTINF 行包含频道名、分组标签、节目指南元数据,导出的文件能直接拖进 VLC、TiviMate 这些播放器。
频道验证:最耗时的部分
验证一个频道是否真的能播,需要三步:
- 连通性检查:HTTP HEAD 请求,看 URL 能不能访问
- 流媒体属性:用 ffprobe 提取视频编码、分辨率、码率
- 稳定性测试:连续请求 3 次,成功率低于 80% 标记为不稳定
验证结果写回 D1,配合 KV 缓存做到秒级响应。但单次验证不够——要跟踪历史,用 7 天滑动窗口算可用率,否则一次抖动就会误判频道失效。
性能优化实战
批量写入
D1 单条 INSERT 很慢。实测下来,8000 条频道数据,批量写入约 2-3 秒,单条写入要 30+ 秒。差距来自网络往返开销,批量相当于把 8000 次往返合并成一次。
查询索引
频道搜索页用了三个组合索引:
channel_hash:哈希匹配用(group_title, country):分类筛选用is_active:排除失效频道用
搜索时先用哈希快速定位,再按分组和地区过滤,避免全表扫描。
缓存分层
- 静态页面:CDN 缓存 24 小时
- API 响应:KV 缓存 1 小时
- 数据变更:每日 cron 刷新 KV + 人工触发清除按钮
成本:基本靠 Cloudflare 免费额度
Cloudflare 的免费层(Free plan)对个人项目非常友好:
- Workers:每天 10 万次请求免费
- D1:每天 500 万次读 + 10 万次写免费
- KV:每天 10 万次读 + 1000 次写免费,1 GB 存储
- 带宽:完全免费,没有流量上限
实测一个 8000 频道、日均 10 万访问量的频道目录项目:
| 项目 | 用量 | 是否在免费额度内 |
|---|---|---|
| Workers 请求 | 500 万次/月 | ✅(10 万次/天 × 30 天 ≈ 300 万次) |
| D1 写入 | 10 万次/天 | ✅(免费额度刚好够用) |
| KV 操作 | 几万次/天 | ✅ |
| 带宽 | 200GB/月 | ✅(免费无上限) |
| 月费用 | — | 0 美元 |
整个频道目录跑在 Cloudflare 免费层上,月成本是零。要超出免费额度,需要单日请求超过 10 万次——对个人项目来说基本不可能。
超出免费额度的情况极其罕见——个人项目基本用不完。真要量级上去,升级套餐的费用也远低于 VPS。
踩过的几个坑
CORS 跨域
Workers 默认不带 CORS 头,前端调 API 直接被浏览器拦。每个 API 响应都要手动加:
javascript
复制
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST
Access-Control-Max-Age: 86400
D1 事务超时
批量验证频道时,如果一个事务里塞太多操作,会触发超时。解决办法是分批,每批 500 条,用 ctx.waitUntil() 异步执行,不阻塞请求响应。
M3U8 重定向追踪
很多 IPTV 流会跳转好几次才到真正的服务器。curl 默认只跟 5 次重定向就不跟了。改用 aiohttp(默认 10 次)或专门的 HTTP 客户端,才能拿到最终播放地址。
时区问题
D1 存的时间戳是 UTC,但用户分布全球。前端展示时用 Intl.DateTimeFormat 转成用户本地时区,后端统一存 UTC,不存本地时间。
本地验证工具
上面这套架构解决的是"在线搜索和播放"的问题,但还有一个前置问题没解决:拿到一批源地址,怎么快速知道哪些能用?
个人用户通常不会自己跑 Workers 服务,需要一个本地批量测试工具。开发过程中写了一个 IPTV-tools,核心逻辑跟文章里讲的 ffprobe 验证、黑名单过滤、M3U 导出一脉相承,只是封装成了带界面的桌面程序。
两者配合使用效果最好:Workers 定时任务自动维护数据,IPTV-tools 做本地精调和筛选,导出高质量 M3U 再上传到搜索服务。一个负责大规模自动化,一个负责人工细修。
总结
这套架构的核心思路是把"边缘执行 + 边缘存储 + 边缘缓存"三件事捏到一起:Workers 处理逻辑、D1 存数据、KV 做缓存、Cron Triggers 定时刷新。单个技术都不复杂,组合起来就能撑住一个全球低延迟的频道目录服务。
类似的架构不止适用于 IPTV,任何需要在全球范围内快速查询的实时数据目录项目(商品价格、新闻聚合、汇率数据等)都可以参考这个思路。
技术栈:Cloudflare Workers, D1 (SQLite), KV Cache, Cron Triggers, Python (ffprobe validation) 工具参考:IPTV-tools — 本地批量验证桌面工具,与搜索架构配合使用

浙公网安备 33010602011771号