动态时间线聚合 - Cloudflare 重制版

上个周末把在服务器运行的 rss 聚合程序迁移到了 Cloudflare 处运行。真的 Cloudflare 太香了!!

why

  1. 之前部署到服务器这个流程太麻烦
    1. 本地修改代码 -> 打包发布 -> scp 上传服务器 -> 服务器关掉正在运行的程序 -> 重新运行程序
  2. 查看和管理数据麻烦:
    1. 因为使用本地 sqlite 数据库文件来保存抓取的文件,所以导致查看服务器上的数据就比较麻烦,得 ssh 连上去然后跑一个 sqlite client 的 shell 程序执行 sql 语句来查询,显示也不好看
    2. 基于文件存储,本地一份,服务器一份,数据常常不同步,还得专门搞一个功能来只抓数据
  3. 网络环境不是很好。
    1. 需要访问 vercel 部署的网页和访问 telegram api,都对网络环境有点要求,本地开发调试还得走个代理,又需要个额外配置
    2. 即使是部署在境外服务器上,网络访问也常常出现链接的问题,log 里面一大堆网络 error

方案

使用 Cloudflare 提供的

  • cron 定时任务调用 worker
    • worker 根据定时任务的 cron 种类来区分重发任务和抓取任务
    • 抓取任务:访问各个 RSS 源解析数据象,并把新的数据发送到 Telegram 频道并保存到数据库当中
    • 重发任务:捞取数据库当中没有发送成功的数据,重新发送到 Telegram 频道当中
  • 使用 D1 数据库存储数据

实现

Cloudflare 提供的 worker 需要用 JS / TS 实现。因为之前其实就已经写过 typescript 版本,所以其实直接迁移调试就可以了。

大概的创建的流程可以看 Cloudflare 应用,主要是有几个点需要注意

  • Cloudflare worker 启动都是通过其入口函数来启动的。传递的环境变量和数据库实例都是通过入口函数的 env 变量来传递的。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
export default {
	async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext): Promise<void> {
		// A Cron Trigger can make requests to other endpoints on the Internet,
		// publish to a Queue, query a D1 Database, and much more.
		//
		// We'll keep it simple and make an API call to a Cloudflare API:
		 let resp = await fetch('https://api.cloudflare.com/client/v4/ips');
		 let wasSuccessful = resp.ok ? 'success' : 'fail';

		// You could store this result in KV, write to a D1 Database, or publish to a Queue.
		// In this template, we'll just log the result:
		console.log(`trigger fired at ${event.cron}: ${wasSuccessful}`)
	}
};
  • 因为 Cloudflare 的 JS 运行时并不是标准的 node,所以一些依赖 node api 的 npm 库可能会跑不了。之前的一些依赖库可能就需要替换,或者手工对 npm 库源代码进行修改。

体验

  • 本地开发可以使用 remote 运行调试,直接用上 Cloudflare 的网络环境和数据库来进行测试。
  • 使用 Cloudflare worker 后可以用官方提供的 wrangle 一键部署,流程大大简化。
  • 使用 Cloudflare 的 dashboard 可以随时查看运行情况(但是拉历史日志好像比较麻烦?)。
  • 可以用在 dashboard 上面修改一些简单的配置,比如定时间隔和环境变量。
  • 可以用 D1 数据库的 console 查询数据库情况,并且做些简单的增删改查。