跳到主要内容
版本:3.0.0

阿里云 FC

阿里云 Serverless 是国内最早提供 Serverless 计算服务的团队之一, 依托于阿里云强大的云基础设施服务能力,不断实现技术突破。目前,淘宝、支付宝、钉钉、高德等已经将 Serverless 应用于生产业务,云上的 Serverless 产品在南瓜电影、网易云音乐、爱奇艺体育、莉莉丝等数万家企业成功落地。

阿里云 Serverless 包含许多产品,如函数计算 FC,轻量应用引擎 SAE 等,本文主要使用了其 函数计算 部分。

下面是常见的函数触发器的使用和测试方法。

触发器代码

发布不包含触发器的函数,这是最简单的类型,可以直接通过 event 手动触发参数,也可以在平台绑定其他触发器。

通过直接在代码中的 @ServerlessTrigger 装饰器绑定事件触发器。

import { Provide, Inject, ServerlessTrigger, ServerlessTriggerType } from '@midwayjs/decorator';
import { Context, FC } from '@midwayjs/faas';

@Provide()
export class HelloAliyunService {
@Inject()
ctx: Context;

@ServerlessTrigger(ServerlessTriggerType.EVENT)
async handleEvent(event: any) {
return event;
}
}

本地开发

HTTP 触发器和 API Gateway 类型可以通过本地 npm run dev 和传统应用类似的开发方式进行本地开发,其他类型的触发器本地无法使用 dev 开发,只能通过运行 npm run test 进行测试执行。

本地测试

通过 createFunctionApp 创建函数 app,通过 getServerlessInstance 获取类实例,然后通过实例的方法直接调用,传入参数进行测试。

describe('test/hello_aliyun.test.ts', () => {
let app: Application;
let instance: HelloAliyunService;

beforeAll(async () => {
// create app
app = await createFunctionApp<Framework>(join(__dirname, '../'), {
initContext: createInitializeContext(),
});
instance = await app.getServerlessInstance<HelloAliyunService>(HelloAliyunService);
});

afterAll(async () => {
await close(app);
});

it('should get result from event trigger', async () => {
expect(await instance.handleEvent('hello world')).toEqual('hello world');
});
});

发布到阿里云

在项目根目录的 f.ymlprovider 段落处确保为 aliyun

service:
name: midway-faas-examples

provider:
name: aliyun

部署函数,直接使用发布命令即可打包并部署函数,Deploy 命令会自动打包,并调用阿里云官方部署工具发布。

$ npm run deploy
信息

如果输错了信息,可以重新执行 npx midway-bin deploy --resetConfig 修改。

阿里云部署首次需要配置 accountIdaccountKeyaccountSecret

相关配置获取,可参照下方图片:

点击此处跳转阿里云安全设置页

点击跳转阿里云个人 AccessKey 页面

这里以 http 触发器作为示例。

发布后,阿里云会输出一个临时可用的域名,打开浏览器访问即可。

发布完成后,平台状态如下。

发布效果,每个配置的函数都将发布成一个平台上的函数,并且自动配置 http 触发器。

常见问题

1、自定义域名

你需要提前申请一个域名,在国内的话,需要备案,否则无法绑定。

第一步,先将默认自动生成的域名的功能关闭

service:
name: midway-faas-examples

provider:
name: aliyun

custom:
customDomain: false

第二步,添加域名解析到你函数对应网关。

在函数页面绑定自定义域名,添加路由

绑定完成后,即可用域名访问。

2、http 头的一些限制

Request Headers 不支持以 x-fc-开头的自定义及以下字段的自定义:

  • accept-encoding
  • connection
  • keep-alive
  • proxy-authorization
  • te
  • trailer
  • transfer-encoding

Response Headers 不支持以 x-fc- 开头的自定义及以下字段的自定义:

  • connection
  • content-length
  • content-encoding
  • date
  • keep-alive
  • proxy-authenticate
  • server
  • trailer
  • transfer-encoding
  • upgrade

Request 限制项。如果超过以下限制,会返回 400 状态码和 InvalidArgument 错误码。

  • Headers 大小:Headers 中的所有 Key 和 Value 的总大小不得超过 4 KB。
  • Path 大小:包括所有的 Query Params,Path 的总大小不得超过 4 KB。
  • Body 大小:HTTP Body 的总大小不得超过 6 MB。

Response 限制项。如果超过以下限制,会返回 502 状态码和 BadResponse 错误码。

  • Headers 大小:Headers 中的所有 Key 和 Value 的总大小不得超过 4 KB。

3、发布包大小问题

为了提升启动速度,阿里云 FC 容器限制压缩包大小为 50M,请尽可能精简你的后端代码依赖。

一般来说,midway 默认脚手架(eggjs)构建完在 9M 左右,其他框架会更小,请尝试先删除 package-lock.json 后再尝试。

4、容器时区问题

大部分 Docker 镜像都是基于 Alpine,Ubuntu,Debian,CentOS 等基础镜像制作而成。 基本上都采用 UTC 时间,默认时区为零时区。

阿里云容器环境的时区默认是 GMT +0000,直接使用 new Date() 等前端获取的时候,国内的用户可能未作时区处理,会相差 8 个小时。

国内用户使用,默认可能习惯 GMT +0800 。可以通过环境变量调整(配置在平台或者 f.yml)。

process.env.TZ = 'Asia/Shanghai';
provider:
name: aliyun
runtime: nodejs12
environment:
TZ: 'Asia/Shanghai'
信息

注意,定时任务由网关触发,不会受到这里配置的函数时区影响。

5、修改 AccessKey

有时候,我们在第一次发布时会填错一个 AccessKey,或者其他区域选项,我们提供了一个 可以修改的参数,用于在发布时清理上次错误的选项。

midway-bin deploy --resetConfig

这里提示 Please create alias for key pair. If not, please enter to skip 时输入 default,否则不会使用当前的 AccessKey。如果只希望调整特定字段,可以进入 ~/.s/access.yaml 文件中,直接修改保存。

6、CLI 发布红色提示

在 HTTP 触发器发布后,会出现下面的红色提示。这是一个提示,原因为,未配置域名的情况下,阿里云将默认添加 Content-Disposition: attachment 头到响应中,浏览器打开地址会变为附件下载。可以通过绑定自定义域名或者本地 curl 的方式来测试结果。

7、发布时指定 accessKey 等

export REGION=cn-beijing
export ACCOUNT_ID=xxx
export ACCESS_KEY_ID=xxx
export ACCESS_KEY_SECRET=xxx

当前阿里云发布使用的是 funcraft 工具,可以使用 funcraft 的环境变量,可以加载启动的命令行前,也可以使用 yml 的变量填充方式。

8、发布超时问题

有时候包比较大, midway-bin deploy 上传可能会碰到超时的问题,这个超时时间是 funcraft 工具内部控制的。

解决方案: ~/.fcli/config.yaml 里面配置 timeout,单位是 s(秒)。

一般来说,midway 默认脚手架(eggjs)构建完在 9M 左右,其他框架会更小,请尝试先删除 package-lock.json 后再尝试。

如无效果,确实是包过大,可以修改 fun 工具的部署时间,位置为 ~/.fcli/config.yaml ,在其中增加 timeout 字段。

示例如下:

endpoint: ***************
api_version: '2016-08-15'
access_key_id: ***************
access_key_secret: ***************
security_token: ''
debug: false
timeout: 50 ## 部署超时时间,单位为 s
retries: 3