Cloudflare 应用开发使用小记

能给大众白嫖使用的 serverless 服务,像 Cloudflare 和 Vercel 就是好的服务商。

最近因为各种原因,突然想把在服务器上运行的 rss-timeline 记录(详情可以看这里 -- 我的动态时间线聚合)的程序换成在云服务上面部署,最终选择了 Cloudflare,并且实现了一版。下面是实现过程中一些记录。

worker

cloudflare 通过 worker 的方式提供服务,worker 有两种触发的方式

  • http trigger. 通过发送 http 请求进行触发,也是最常用的一种,实现 fetch 方法处理请求即可
    • 在 ChatGPT API 刚出的时候,很多人都因为 API 地址不能直连,所以搞一个 worker 请求转发就可以了。比如这个
  • cron trigger. 通过定时任务的方式来触发任务。通过配置 cron job 来声明执行的周期。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
export default {
	// The scheduled handler is invoked at the interval set in our wrangler.toml's
	// [[triggers]] configuration.
	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}`)
	},

	// The event handler is invoked whenever an HTTP request is made to your
	// worker. The request will trigger the event handler regardless of the
	// request method or URL path.
	fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
	 	return new Response(`Hello from the scheduled worker at ${request.url}`);
	 }

};

可以通过在配置文件 wrangle.toml 或者 dashboard 中的设置中声明环境变量。环境变量通过传递进来的 env 参数使用。

免费版主要是限制

  • 每次调用的 CPU 执行时间 10ms
    • 官网中介绍用量很少,基本都不会超
    • 但实际跑下来发现好像超了也没事?
  • 每天的请求执行次数 100, 000

本地调试

本地可以通过 wrangle 来进行开发调试和部署

cron worker 可以通过 --test-scheduled 参数,实现 http 调用 http://localhost:8787/__scheduled?cron=*+*+*+*+* 触发 trigger.

有些时候本地访问一些网站可能因为某些奇怪因素访问不了,可以通过 --remote 参数,实现本地运行远程调试,这样就可以突破网络限制访问某些网站。另外也可以通过这个方法直接操作数据库,这样就可以直接在网站就看到数据库的更新情况。

non-standard Node.js runtime

cloudflare worker 本质上其实是 edge function,其实际的运行时并不是正宗的 node 环境,所以一些对于 node api 的使用,是可能会满足不了的。部分到 API cloudflare 的运行时实现了,在自己的代码中可以直接用。但往往通过 npm install 使用的依赖就容易会出现这种兼容性问题。

对于这些有兼容性问题的 npm 库,建议在本地运行时看看实际跑到的代码是否真的用到这些 node api,如果没有,只是在文件当中导入的话,可以注释掉。动态语言 js 的一个爽点就是,就算代码有问题,但只要没有跑到有问题的地方,也还是能跑,就算这样注释掉一个依赖导入,但只要调用的代码没有使用它们,照样能跑。

如果调用的 node api 在 Cloudflare 中有实现的,通过换个方式导入也可以。

1
2
3
4
5
// Do this:
import { Buffer } from 'node:buffer';

// Do not do this:
import { Buffer } from 'buffer';

D1

cloudflare 提供的关系型数据库

创建数据库后可以在 worker 里面添加绑定,直接访问到数据库

1
2
3
4
[[d1_databases]]
binding = "DB" # available in your Worker on env.DB
database_name = "database"
database_id = "database_id"

实际使用起来就是会在入口处传递 env,然后这个数据库的实例也随着 env 传进来,然后就可以手写 sql 进行数据处理了。

数据库操作可以通过

  • 官网网页可以创建表,已经修改行数据
    • 官网也提供一个 console 进行 sql 语句的执行
  • 也可以在命令后通过 wrangle 执行 sql 语句,从而更新数据库
    • 这种方式还可以实现一些表结构的更新,比如增加一列

免费的用量限制

  • 最多创建 10 个数据库
  • 单个数据库 500MB
  • 每月读 5,000,000 行,写 100,000 行