Serverless 解惑——AWS Lambda 迁移阿里云函数计算指南

岳劲
2023-12-01

概念比较

在 AWS Lambda 中,函数是管理 AWS Lambda 的基本资源单位,用户可以在函数级别上授权、配置 CloudWatch 日志。在阿里云函数计算中,除了有函数外还有服务资源。其中,服务是管理函数计算的基本资源单位,可以在服务级别上授权、配置日志和创建函数等;函数是调度与运行的基本单位,也是一段代码的处理逻辑。
在阿里云函数计算中,一个服务下可以创建多个函数,每个函数可以设置不同的内存规格、环境变量等属性,这种服务或者函数层次化的抽象,在系统抽象和实现灵活度上能够取得很好的平衡。例如,实现一个微服务,调用阿里云语音合成服务,将文字转成语音,再把这段语音和一系列图片组合为视频。其中文字转语音函数是调用其他服务,可以设置很小的内存规格。而视频合成函数是计算密集型,需要更大的内存。因此,可以通过组合多个不同规格的函数实现微服务,优化成本。

免费开通服务

  1. 免费开通函数计算,按量付费,函数计算有很大的免费额度。

接下来,将通过一张表格的形式来呈现 AWS Lambda 与阿里云函数计算的概念比较:

概念

AWS Lambda

函数计算

服务

服务是管理函数计算的基本资源单位,可以在服务级别上授权、配置日志和创建函数等

函数

具有处理事件的代码,以及在 Lambda 与函数代码之间传递请求和响应的运行时

是调度与运行的基本单位,具有处理事件的代码,以及在阿里云函数计算服务与函数代码之间传递请求和响应的运行时

运行时(Runtime)

位于 Lambda 服务和函数代码之间,并在二者之间传递调用事件、上下文信息和响应。支持的运行时清单

位于阿里云函数计算服务和函数代码之间,并在二者之间传递调用事件、上下文信息和响应。支持的运行时清单

并发

在调用函数时,Lambda 会预配置其实例以处理事件。当函数代码完成运行时,它会处理另一个请求。如果当仍在处理请求时再次调用函数,则预配置另一个实例,从而增加该函数的并发性。并发限制

在函数计算 1.0 中,一个函数实例最多只能同时处理一个请求,如果当仍在处理请求时再次调用函数,则预配置另一个实例,从而增加该函数的并发性。在函数计算 2.0 中,函数计算支持了单实例并发处理多请求功能。并发限制

触发器

触发器是调用 Lambda 函数的资源或配置。这包括可配置为调用函数的 AWS 服务、用户开发的应用程序以及事件源映射。事件源映射是 Lambda 中的一种资源,它从流或队列中读取项目并调用函数。触发器列表

触发器是触发函数执行的方式,触发器提供了一种集中的和统一的方式来管理不同的事件源。在事件源中,当事件发生时,如果满足触发器定义的规则,事件源则调用触发器所对应的函数。触发器列表

开发工具 & SDK

下述表格为 AWS Lambda 与阿里云函数计算的开发工具 & SDK:

类型

AWS Lambda

函数计算

命令行

AWS Command Line Interface (AWS CLI)

Fcli: 阿里云函数计算的命令行工具,帮助用户便捷的管理函数计算中的资源

命令行

SAM CLI

Funcraft: 用于支持 Serverless 应用部署的工具,能帮助用户便捷地管理函数计算、API 网关、日志服务等资源。Funcraft 通过一个资源配置文件(template.yml),协助用户进行开发、构建、部署操作

IDE

AWS Toolkit Extension

Aliyun Serverless VSCode Extension: 结合了 函数计算 Funcraft 工具 以及函数计算 SDK ,是基于 VSCode 的开发调试部署工具;以及其他平台上的Cloud Toolkit

IDE

C9

FC WebIDE

SDK

Node.js:SDK for Javascript

Node.js:fc-nodejs-sdk

SDK

Python:SDK for Python

Python:fc-python-sdk

SDK

PHP:SDK for PHP

PHP:fc-php-sdk

SDK

Java:SDK for Java

Java:fc-java-sdk

SDK

Go:SDK for Go

Go:fc-go-sdk

SDK

C#:SDK for .NET

C#:fc-csharp-sdk

简单示例

迁移 Hello World 函数

接下来将介绍如何将 AWS Lambda 的一个简单示例迁移至阿里云函数计算服务。

exports.handler = async (event, context) => {
    console.log(`Event: ${JSON.stringify(event)}`);
    console.log(`Context: ${JSON.stringify(context)}`);
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
    };
    return response;
};

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tL2pMYEh-1583392382905)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2YP3kPw9-1583392382905)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== “点击并拖拽以移动”)]

上述为 AWS Lambda Nodejs10.x 运行时的函数代码,在该函数中做了以下三件事:

  1. 打印 Event 事件信息

  2. 打印 Context 上下文信息

  3. 返回 Response 对象,内容为

    {
       "statusCode": 200,
       "body": "\"Hello World!\"",
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j5w3uSIK-1583392382907)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s2mYbVgE-1583392382907)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== “点击并拖拽以移动”)]

    我们将其迁移至阿里云函数计算服务,根据快速入门/HelloWorld 示例中的内容创建好 nodejs10 运行时的函数代码,修改代码内容如下:

module.exports.handler = function(event, context, callback) {
  console.log(`Event: ${JSON.stringify(JSON.parse(event))}`);
  console.log(`Context: ${JSON.stringify(context)}`);
  const response = {
    statusCode: 200,
    body: JSON.stringify('Hello World!'),
  };
  callback(null, response);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nx3kc1Jj-1583392382909)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GHRRq1oo-1583392382909)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== “点击并拖拽以移动”)]

上述为阿里云函数计算 nodejs10 运行时的函数代码。注意,该函数代码和 AWS Lambda Nodejs10.x 运行时函数代码有以下两点不同:

  1. event 参数的输出方式
    在 AWS Lambda Nodejs10.x 中,输出 event 的代码为console.log(`Event: ${JSON.stringify(event)}`);;而在阿里云函数计算 nodejs10 中,输出 event 的代码为console.log(`Event: ${JSON.stringify(JSON.parse(event))}`);。在 AWS Lambda 中,事件 Event 传入的类型是 JSON 对象;而在阿里云函数计算中,事件 Event 传入的类型是 Buffer。
  2. 函数返回结果的方式
    在 AWS Lambda Nodejs10.x 中,函数返回结果的代码为return response;;而在阿里云函数计算 nodejs10 中,函数返回结果的代码为callback(null, response);

上述两点的不同是由于阿里云函数计算 Nodejs 普通函数入口和 AWS Lambda Nodejs 函数入口有所不同,阿里云函数计算 Nodejs 普通函数入口有以下三个参数:

  1. event 参数

  2. 参数是调用函数时传入的数据,其类型是 Buffer,是函数的输入参数。函数不对它的内容进行任何解释,在函数中可以根据实际情况对 event 进行转换。

  3. context 参数

  4. 参数中包含一些函数的运行时信息(例如 request id / 临时 AK 等),其类型是 object。包含以下信息:

    • requestId: 本次调用请求的唯一 id。
    • function: 当前调用的函数的一些基本信息如函数名 / 函数入口 / 函数内存 / 超时时间
    • credentials: 函数计算服务通过扮演用户提供的服务角色获得的一组临时密钥,其有效时间是 6 小时。可以在代码中使用它去访问相应的服务( 例如 OSS )
    • service: 当前调用的函数所在的 service 的信息,包括 service 的名字,接入的 SLS 的 logProject 和 logStore 信息,service的版本信息qualifier和version_id,qualifier表示调用函数时指定的service版本或别名,version_id表示实际调用的service版本。
    • region: 当前调用的函数所在区域,如 cn-shanghai。
    • accountId: 当前调用函数用户的阿里云 account id。
  5. callback 参数

    • callback 参数用于返回调用函数的结果,其签名是 function(err, data),与 Node.js 中惯用的 callback 一样,它的第一个参数是 error ,第二个参数 data 。如果调用时 err 不为空,则函数将返回 HandledInvocationError ,否则将返回 data 的内容。如果 data 是 Buffer 类型则它的数据将直接被返回,如果 data 是 object ,则会将其转换成 JSON 字符串返回,其他类型将被转换成 string 返回。

更多内容可以参考Node.js 函数入口

复杂示例

迁移 S3 触发 Lambda 的函数

接下来将介绍如何将 AWS Lambda 带有 S3 触发器并访问 S3 的简单示例函数迁移至阿里云函数计算服务。

console.log('Loading function');

const aws = require('aws-sdk');

const s3 = new aws.S3({ apiVersion: '2006-03-01' });

exports.handler = async (event, context) => {
    // Get the object from the event and show its content type
    const bucket = event.Records[0].s3.bucket.name;
    const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
    const params = {
        Bucket: bucket,
        Key: key,
    };
    try {
        const result = await s3.getObject(params).promise();
        console.log(result);
        return result;
    } catch (err) {
        console.log(err);
        const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
        console.log(message);
        throw new Error(err);
    }
};

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DDdI1DJB-1583392382911)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CKMvoldW-1583392382911)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== “点击并拖拽以移动”)]

上述为 AWS Lambda Nodejs10.x 运行时的函数代码,该函数配置了 S3 触发器以及相应的 Execution Role,该函数的主要逻辑如下:

  1. 当为 S3 触发器配置的事件源发生了相关事件时,事件源将调用该函数。
  2. 从 Event 事件信息中获取到事件相关的 Bucket 以及 Key。
  3. 访问 S3 获取到相关对象。

我们将其迁移至阿里云函数计算服务,根据快速入门/HelloWorld 示例中的内容创建好 nodejs10 运行时的函数代码,修改代码内容如下:

const oss = require('ali-oss');

module.exports.handler = async (event, context) => {
    // Get the object from the event and show its content type
    const event = JSON.parse(event);
    const bucket = event.events[0].oss.bucket.name;
    const key = event.events[0].oss.object.key;
    let client = new OSS({
      bucket: bucket,
      accessKeyId: context.credentials.accessKeyId,
      accessKeySecret: context.credentials.accessKeySecret,
      stsToken: context.credentials.securityToken,
    });
    try {
        const result = await client.get(key);
        console.log(result);
        callback(null, result);
    } catch (err) {
        console.log(err);
        const message = `Error getting object ${key} from bucket ${bucket}.`;
        console.log(message);
        callback(err);
    }
};

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ny0xP6Dw-1583392382912)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VOpNjODy-1583392382912)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== “点击并拖拽以移动”)]

上述为阿里云函数计算 nodejs10 运行时的函数代码,代码逻辑和 AWS Lambda 大致相同。其中,OSS 为阿里云对象存储服务。除此之外,还需要为该函数配置 OSS 触发器以及相应的 ServiceRole 和 InvocationRole。相关概念如下:

  1. 服务角色 Service Role
    为服务配置服务角色,即允许该服务下的函数扮演这个角色。假设该角色拥有 OSS 的相关权限,则函数通过扮演该角色可以使用 OSS 上的资源。阿里云函数计算的服务角色和 AWS Lambda 中的 Execution Role 是相同的作用。
  2. 触发角色 Invocation Role
    触发角色,事件源需要扮演一个角色来触发函数的执行,要求这个角色有触发函数执行的权限。关于事件源角色的详细信息请参考文章权限简介

除了上述的服务角色和触发角色外,还需要注意的一点是,在函数中是通过如下的代码片段生成了 OSS client:

let client = new OSS({
  bucket: bucket,
  accessKeyId: context.credentials.accessKeyId,
  accessKeySecret: context.credentials.accessKeySecret,
  stsToken: context.credentials.securityToken,
});

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k7oNs9nf-1583392382913)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XBgnV3lu-1583392382913)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== “点击并拖拽以移动”)]

context 参数中包含了credentials信息,函数计算服务通过扮演用户为服务配置的服务角色获得的一组临时密钥。用户可以在代码中使用它去访问相应的服务( 例如 OSS ),这就避免了把自己的 AK 信息写死在函数代码里。

迁移 AWS Step Functions 调用 AWS Lambda

接下来将介绍如何将 AWS Step Functions 调用 AWS Lambda 的简单示例迁移至阿里云函数工作流和函数计算服务。

{
  "StartAt": "Hello",
  "States": {
    "Hello": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-southeast-1::function:helloworld",
      "End": true
    }
  }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3BntK28-1583392382914)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Adagpqmn-1583392382915)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== “点击并拖拽以移动”)]

上述为 AWS Step Functions 的流程代码,该流程调用了 AWS Lambda 的函数,假设调用的函数代码为简单示例中的 Hello World 函数。

我们将其迁移至阿里云函数工作流服务,根据快速入门/创建流程中的内容创建好 函数工作流的流程,修改流程代码内容如下:

version: v1beta1
type: flow
steps:
  - type: task
    name: helloworld
    resourceArn: acs:fc:cn-hangzhou::services/helloworld/functions/sayHello

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dyVBqKVe-1583392382915)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mkQfG0pX-1583392382915)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== “点击并拖拽以移动”)]

上述为阿里云函数工作流服务的流程代码,代码逻辑和 AWS Step Functions 大致相同。可以看到,当将 AWS Lambda 成功迁移至阿里云函数计算服务后,如果有迁移 AWS Step Functions 调用 AWS Lambda 的需求,只需要将 AWS Step Functions 的流程逻辑迁移至阿里云函数工作流服务即可。

查看更多:https://yqh.aliyun.com/detail/6741?utm_content=g_1000106528

上云就看云栖号:更多云资讯,上云案例,最佳实践,产品入门,访问:https://yqh.aliyun.com/

 类似资料: