登录
  • 人们都希望被别人需要 却往往事与愿违
  • 用人不在于如何减少人的短处, 而在于如何发挥人的长处@彼得.德鲁克 (管理学之父)

将 Cloudflare Workers 迁移到 Azure Function

Azure Benny小土豆 523次浏览 4334字 0个评论
文章目录[显示]

WebP Cloud Services使用 Cloudflare Workers进行回源来保证原站服务器IP不泄漏。本着降本增效的理念,我们这次准备将部分回源请求迁移到 Azure Function。

Azure Function 同样也是由 Azure 提供的serverless服务,运行时可以使用 Python、NodeJS、Java和亲儿子 .NET、PowerShell,和 Cloudflare Workers一样,每个月前100万请求免费,具体信息可以参考价格表

我们的回源代码是使用 JavaScript写的,虽然这个语言挺扭曲的,但是为了方便迁移,就不变啦!

创建 Azure 账号

你需要有一个活跃订阅的Azure账号……

创建 Function

搜索栏搜索 Function App,点击 Create 按钮,会发现 Azure 提供了五种选项。选择第一个 Consumption

将 Cloudflare Workers 迁移到 Azure Function

基本信息

进入配置页面,可以新建一个资源组,需要选择的是 Runtime,这里选择 nodejs,然后 Region选择离用户最接近的地方。这里和 Cloudflare Workers不一样,Cloudflare Workers是在全球部署的,会在离用户最近的节点执行;Azure 这里是在固定的节点执行,所以对于大陆用户来说,日韩港新是比较不错的位置。

将 Cloudflare Workers 迁移到 Azure Function

存储

默认就行,要是看默认的名字不喜欢,可以自己改掉

网络

这里要选择Enable public access,要不然访问不了。

将 Cloudflare Workers 迁移到 Azure Function

其他选项

Monitoring 想开就开,为了省钱可以关掉。当然后续也可以重新开启;

Deployment是配置CD的地方,可以以后再配置

部署

部署完成之后 Azure 会提供一个URL,打开之后应该是这样的

将 Cloudflare Workers 迁移到 Azure Function

准备开发环境

不像 Cloudflare Workers 那么直接,开发 Azure Functions 最好用 VS Code。因为用 Azure Functions 扩展会很方便。

然后按F1弹出窗口 Azure Functions – Create New Project,语言就选择 JavaScript,愿意做类型体操也可以选择 TypeScript,或者任何你熟悉的语言都可以。

将 Cloudflare Workers 迁移到 Azure Function

Trigger为如何触发Functions,这个场景下选择HTTP Trigger就可以了

将 Cloudflare Workers 迁移到 Azure Function

熟悉开发环境

目录与文件

  • src/functions/fetchImage.js 这个就是你的代码
  • host.json:配置

部署

F1 – Deploy to Function App,选择订阅-刚刚创建的function

部署成功之后,浏览器访问:

https://blog-fun-post.azurewebsites.net/api/fetchimage

就可以看到 Hello World信息了。其中:

  • api是路由前缀,可以自定义的
  • fetchimage是代码里写好的路由,当然也可以自定义,默认代码里定义的name

Azure 上可以看到已经部署好的代码

将 Cloudflare Workers 迁移到 Azure Function

点进去终于有了和 Cloudflare Workers一样的在线编辑页面(不过可能是只读的,和选择的语言有关)

将 Cloudflare Workers 迁移到 Azure Function

本地调试

每次改代码都部署一次确实不是好办法。这个时候就要用本地调试啦,由于我们是用 HTTP trigger的,调试起来非常简单方便。哦对了,调试 JavaScript 应用得有nodejs

打开 fetchImage.js 按下F5,这里选择 Connect Storage Account(其实选择 emulator绕过去也行,没关系)

将 Cloudflare Workers 迁移到 Azure Function

如果是第一次运行,可能需要安装一些依赖,安装完成之后就会看到控制台输出了类似如下信息

Azure Functions Core Tools
Core Tools Version: 4.0.6280 Commit hash: N/A +421f0144b42047aa289ce691dc6db4fc8b6143e6 (64-bit)
Function Runtime Version: 4.834.3.22875
[2024-09-26T12:27:04.937Z] Debugger listening on ws://127.0.0.1:9229/882fb0c8-1957-4070-a6be-9cfd3250d77b
[2024-09-26T12:27:04.938Z] For help, see: https://nodejs.org/en/docs/inspector
[2024-09-26T12:27:05.003Z] Worker process started and initialized.
[2024-09-26T12:27:05.058Z] Debugger attached.
Functions:
fetchImage: [GET,POST] http://localhost:7071/api/fetchImage
For detailed output, run func with --verbose flag.

浏览器访问http://localhost:7071/api/fetchImage 就可以了,改了代码也会自动热加载,当然也可以打断点。

Functions

一个最简单的 Functions 代码是这样的

const { app } = require('@azure/functions');

app.http('fetch', {
	methods: ['GET', 'POST'],
	authLevel: 'anonymous',
	handler: async (request, context) => {
		context.log(`Http function processed request for url "${request.url}"`);
		return { body: `Hello hello hello` };
	},
});
  • app.http 的第一个参数是名字,要唯一,并且默认是路由
  • methods表示接受的请求方法
  • handler是处理请求的地方,第一个参数是request,可以用来获取请求体之类的信息,第二个是context,执行上下文,包括日志功能、绑定数据、环境信息等。
  • return 用于返回响应,按照文档 context.res 也应该可以,但是在我这里不行,可能需要额外配置一下。返回一个object,编辑器会自动补全,比如body, status,headers 等

定义路由

路由前缀

默认,functions的代码都是 在 /api 这个路由下的,在 host.json 里可以进行配置

"extensions": {
    "http": {
      "routePrefix": ""
    }
  }

这样就没有 api 这个前缀了,当然你也可以随便改!

路由名称

默认路由名称是app.http 的第一个参数,如

app.http('fetch', {
	methods: ['GET', 'POST'],
	authLevel: 'anonymous',
	handler: handler,
});

那么路由就是 fetch ,如果要自定义可以额外传入一个 route。需要注意不可以是空字符串,也不可以是/开头的

app.http('fetch', {
	methods: ['GET', 'POST'],
	authLevel: 'anonymous',
	handler: handler,
	route: "something"
});

根访问

如果你希望应用在 https://example.com 直接访问,不需要/api 也不需要路由名称,那么就要综合以上两种方法,配置前缀,然后 route: "/"不能留空😂,如果留空就会出现azure默认的页面

又一个人生小技巧🫠

迁移代码

我们的Cloudflare Workers代码是这么写的,非常简单

async function handleProxy(post_body) {
	const headers = {
		"Accept": post_body.accept,
		"User-Agent": post_body.user_agent
	};

	const response = await fetch(post_body.origin_url, {
		method: post_body.request_name,
		headers: headers
	});

	if (response.ok) {
		const res = new Response(response.body, {
			status: response.status,
			statusText: response.statusText,
			headers: response.headers
		});
		return res;
	} else {
		return new Response(response.statusText || "Unknown Error", {
			status: response.status,
			statusText: response.statusText
		});
	}
}

export default {
	async fetch(request, env, ctx) {
		try {
			const post_body = await request.json();
			return handleProxy(post_body);
		} catch (error) {
			return new Response("Invalid JSON data", { status: 400 });
		}
	},
};

基本上要改的地方如下:

  1. 入口参数位置调换
  2. 改改函数名字之类的

也就是改一下那个default

async function handler(request, context) {
	try {
		const body = await request.json();
		return handleProxy(body);
	} catch (error) {
		console.error('JSON parsing error:', error);
		return new Response('Invalid JSON data', { status: 400 });
	}
}

好了你的函数写好了,可以部署了。就是这么简单,除了配置环境那里麻烦点,别的都很容易,毕竟大家都是nodejs 20,自带了fetchResponse

甚至可以通过运行时信息不同,使用不同的入口函数,进而做到用一套代码。

总结

  1. Function提供的语言比Cloudflare Workers多
  2. 大家都是JavaScript,迁移很简单。为了类型安全也可以使用 TypeScript
  3. Function是区域性部署;Workers是全球部署且就近执行
  4. Function 想要做到就近执行,可能得需要配合 FrontDoor + 多地部署,想想就头疼
  5. Function提供的计划挺多的
  6. Function也应该可以拿来做一些奇奇怪怪的事情
  7. Azure的线路很好,对大陆访问非常友好,而Cloudflare则是降速CDN了
  8. Azure的功能好多(价格也很美丽),还待以后慢慢学习尝试

 


文章版权归原作者所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明原作者和本文原始地址:
https://dmesg.app/workers-function.html
喜欢 (1)
分享:-)
关于作者:
If you have any further questions, feel free to contact me in English or Chinese.
发表我的评论
取消评论

                     

去你妹的实名制!

  • 昵称 (必填)
  • 邮箱 (必填,不要邮件提醒可以随便写)
  • 网址 (选填)