异步任务最佳实践

异步任务可以实时感知业务状态、控制执行函数,让您对一些异常情况进行更好的处理,例如报警通知、自动化重试等。本文介绍如何结合使用Serverless Devs和函数计算控制台实现异步调用任务。

背景信息

FaaS早期主要支持无状态、短时和轻量级的计算能力,例如API后端、图片处理和数据流式处理等。在各类场景中,对于FaaS函数的调用方式可分为异步调用和同步调用。同步调用和异步调用存在的差异是同步调用会立即执行函数,而异步调用则会立刻返回调用方202 HttpCode,并将异步调用消息入队,由后端服务排队处理。

使用场景

随着业务的发展,一些在线直播场景的用户在慢慢迁移至FaaS内,这类业务场景通常具有执行时间长、对延时敏感和可用性要求高等特征,开发人员需实时感知业务状态和控制函数的执行。由于异步调用对延时不敏感,同步调用长链接的稳定性比较差,并且占用客户端资源,所以既无法使用异步调用也无法使用同步调用。但由于异步调用在大量突增流量的离线业务下,具有削峰填谷的特点,可以平滑缓冲对业务下游系统的冲击,所以函数计算对异步调用进行相关拓展,引入异步任务。异步任务主要适用于以下业务场景:

  • 对执行具有可观测性

    • 在执行过程中您可以实时查看执行的状态,例如是否已出队、是否已触发函数执行和执行结果是否已正常发送Destination目标。

    • 业务具有明显的任务属性,如下所示:

      • 可以查看某个执行的触发事件和实时的执行日志。

      • 可以根据执行的名称、执行的时间或执行的状态等过滤查询历史记录。

  • 对执行具有可操作性

    业务具有明显的任务属性,如下所示:

    • 当执行时间较长时,在某些情况下可以手动停止执行函数。

    • 可以重新执行历史失败或成功的执行。

关于异步任务的详细信息,请参见异步任务

准备工作

  • 快速入门

  • 配置Serverless Devs

  • 创建SMQ队列。详细信息,请参见创建队列

  • 创建RAM角色,并授予以下权限策略,您也可以直接使用AliyunFCDefaultRolePolicy策略。关于权限策略的详细信息,请参见创建RAM角色

    {
        "Version": "1",
        "Statement": [
            {
                "Action": [
                    "fc:InvokeFunction",
                    "mns:SendMessage",
                    "mns:PublishMessage",
                    "log:*"
                ],
                "Resource": "*",
                "Effect": "Allow"
            }
        ]
    }

操作步骤

您可以通过异步任务实现以下效果:

  • 函数开始异步执行后,您可以通过函数计算控制台、SDK或API查看操作执行。

  • 当函数执行失败或手动停止后,函数计算系统会将异步消息推送至轻量消息队列(原 MNS)的队列中实现死信队列的功能,方便您感知异步函数执行失败的消息并进行后续处理。

  1. 执行以下命令,克隆项目工程。

    git clone https://github.com/awesome-fc/Stateful-Async-Invocation.git
  2. 执行以下命令,进入项目目录。

    cd Stateful-Async-Invocation
  3. 修改s.yaml文件。

    完整的s.yaml示例代码如下。实际使用过程中,需修改{accountid}的值为您的阿里云账号ID,修改{myqueue}的值为您配置的异步调用目标轻量消息队列(原 MNS)的队列名称。

    edition: 3.0.0
    name: stateful-async-inovcation-demo
    access: default
    resources:
      fc-job:
        component: fc3
        props:
          region: cn-hangzhou
          description: this is test
          handler: index.handler
          memorySize: 128
          runtime: python3
          instanceConcurrency: 1
          timeout: 60
          internetAccess: true
          role: acs:ram::{accountid}:role/aliyunfcdefaultrole
          functionName: my-fc-job
          code: ./code
          asyncInvokeConfig:
            maxAsyncEventAgeInSeconds: 172800
            maxAsyncRetryAttempts: 1
            asyncTask: true
            qualifier: LATEST
            destinationConfig:
              onSuccess:
                destination: acs:mns:cn-hangzhou:{accountid}:/queues/{myqueue}/messages
              onFailure:
                destination: acs:mns:cn-hangzhou:{accountid}:/queues/{myqueue}/messages
  4. 在目标目录中执行以下命令部署函数。

    sudo s deploy

    部署成功后,您可以登录函数计算控制台,查看是否成功创建函数并为该函数开启异步任务功能。

结果验证

  1. 您可以通过Serverless Devs工具异步调用上一步部署的函数,示例代码如下。

    sudo s invoke --invocation-type Async -e '{"failure":true}'

    您也可以通过函数计算控制台查看、操作异步调用。更多信息,请参见任务管理

    说明

    如果您需要查看详细信息例如函数日志,您需要为函数配置日志服务。详细信息,请参见配置日志

  2. 当函数调用结束后,如已配置了Destination目标,则可前往目标查看推送记录。

    本文示例中,配置的Destination目标为轻量消息队列(原 MNS)的队列,您可以在轻量消息队列(原MNS)控制台接收Destination推送的信息,如下所示。

    {
        "timestamp": 1728465119433,
        "requestContext": {
            "requestId": "1-670648a1-15197d0b-d07710222f9d",
            "functionArn": "acs:fc:cn-hangzhou:1034354682****:functions/my-fc-job",
            "condition": "InvocationError",
            "approximateInvokeCount": 2
        },
        "requestPayload": "{\"failure\":true}",
        "responseContext": {
            "statusCode": 200,
            "functionError": "InvocationError"
        },
        "responsePayload": "{\"errorMessage\":\"Function timed out after 60 seconds (maxMemoryUsage: 8MB)\"}"
    }
    说明

    当异步调用失败或手动终止后,您可以在轻量消息队列(原 MNS)中接收到异步调用的详细错误信息。