Cloudflare边缘计算初体验

因为最近在使用Cloudflare提供的DNS解析服务,于是顺带体验了它提供的Workers服务:

我不是很理解它所描述的“在边缘运行”具体是什么意思,于是尝试从文档中找答案:

什么是边缘计算?

边缘计算是一种致力于使计算尽可能靠近数据源、以减少延迟和带宽使用的网络理念。简而言之,边缘计算意味着在云端运行更少的进程,将这些进程移动到本地,例如用户的计算机、IoT 设备或边缘服务器。将计算放到网络边缘可以最大程度地减少客户端和服务器之间必须进行的长距离通信量。

详见:https://www.cloudflare.com/zh-cn/learning/serverless/glossary/what-is-edge-computing/

它类似于Web标准的Web Worker,可以在浏览器中运行js脚本,拦截Http请求,并返回自定义的Response,只不过在Cloudflare中,这些worker是运行在它的服务器上。

那么一个典型的Http请求就会是这样的:

访客 A <-> 边缘计算网络Worker C <-> 服务器 B

只不过Worker C不是一个,而是遍布于全球的250个服务器中离访客A最近的那一个,你可以在这些Worker中做很多事情,比如:

  1. 对服务器B的内容进行“边缘缓存”
  2. 根据Region选择对应的服务,甚至可以屏蔽特定区域
  3. 反向代理
  4. …

当然我相信边缘计算能做的事情肯定还有更多,只是目前我能想到的就是这些

实例

如果你熟知各种git page服务就应该知道,很多时候绑定域名是要收费的,比如Gitee:

那么通过边缘计算提供的云函数功能,就可以用反向代理绕过去此限制(是的,不用额外购买一台服务器配置nginx了!)

1. 安装Worker CLI

$ npm install -g @cloudflare/wrangler

或

$ yarn global add @cloudflare/wrangler

然后运行wrangler --version会输出以下结果:

$ wrangler --version
wrangler 1.19.8

2. 登录到Worker CLI

你可以运行 wrangler login 以使用账号和密码登录,也可以使用Global Key登陆

$ wrangler config --api-key

点击这里,获取Global Key

3. 生成你的项目

$ wrangler generate my-worker

或者根据模板来生成项目,如生成带有Typescript支持的模板项目:

$ wrangler generate cf-ts-worker https://github.com/cloudflare/worker-typescript-template

4. 编写代码

除了在生成的项目中有自带的模板函数以外,还可以访问这里看更多的例子

比如这里我们使用 Fetch HTML 这个模板,在 cf-ts-worker/src/index.ts中写入:

const url = "https://evink.gitee.io"
/**
 * gatherResponse awaits and returns a response body as a string.
 * Use await gatherResponse(..) in an async function to get the response body
 * @param {Response} response
 */
async function gatherResponse(response: any) {
  const { headers } = response
  const contentType = headers.get("content-type") || ""
  if (contentType.includes("application/json")) {
    return JSON.stringify(await response.json())
  }
  else if (contentType.includes("application/text")) {
    return response.text()
  }
  else if (contentType.includes("text/html")) {
    return response.text()
  }
  else {
    return response.text()
  }
}

async function handleRequest() {
  const init = {
    headers: {
      "content-type": "text/html;charset=UTF-8",
    },
  }
  const response = await fetch(url, init)
  const results = await gatherResponse(response)
  return new Response(results, init)
}

addEventListener("fetch", event => {
  return event.respondWith(handleRequest())
})

那么Worker就知道,一旦有人访问到它,就将访客重定向至 https://evink.gitee.io 也就帮我们完成了反向代理的工作。

5. 本地预览

打开 cf-ts-worker/wrangler.toml 填写你的 account_id,通过命令wrangler whoami可以知道你的account_id

$ wrangler whoami
👋  You are logged in with an API Token, associated with the email '<Your Email>'.

+----------------------------------+----------------------------------+
| Account Name                     | Account ID                       |
+----------------------------------+----------------------------------+
| Your Account                     | $yourAccountId                   |
+----------------------------------+----------------------------------+

关于 type的类型,可选的有 javascript,webpack,rust,如果你想要自定义的话,可以选择webpack,但注意若不提供自定义的webpack文件,可能会出错。建议始终填写为javascript

填写完毕后运行

$ wrangler dev

注意此命令每次都会运行wrangler.toml中的 [build]指令,所以不需要手动运行 npm install 或者 npm run build 或者 手动编译ts文件。且此预览命令也是在最近的边缘服务器上运行,所以并不会对电脑造成压力。

访问 http://127.0.0.1:8787,可以看到已成功反代:

6. 部署边缘服务

在 wrangler.toml 中添加路由规则,如:

name = "cf-ts-worker"
account_id = "$yourAccountId"
type = "javascript"
workers_dev = true

[env.production]
# The ID of the domain to deploying to
zone_id = "$yourZoneId"

# The route pattern your Workers application will be served at
route = "*www.evink.cn/*"

你可以在 概述 中找到 zone_id:

配置完毕后,运行:

$ wrangler publish

7. 最后一步

别忘了使用Cloudflare DNS解析服务,并添加一条DNS解析记录,将 www.evink.cn 指向任意服务器地址(A记录或者CNAME均可)

Q:非要使用CF的DNS解析服务吗? A:是的,如果不使用CF的DNS解析,那么你部署的边缘服务器将无法通过CF的服务器拦截Http请求

那么所有访问至 www.evink.cn 的请求都会被重定向至 evink.gitee.io