

# 使用 Ruby 构建 Lambda 函数
<a name="lambda-ruby"></a>

您可以在 AWS Lambda 中运行 Ruby 代码。Lambda 可为 Ruby 提供[运行时](lambda-runtimes.md)，用于运行代码来处理事件。您的代码在包含 适用于 Ruby 的 AWS SDK 的环境中运行，其中包含来自您管理的 AWS Identity and Access Management (IAM) 角色的凭证。要了解有关 Ruby 运行时随附的 SDK 版本的更多信息，请参阅 [包含运行时的 SDK 版本](#ruby-sdk-included)。

Lambda 支持以下 Ruby 运行时：


| 名称 | 标识符 | 操作系统 | 弃用日期 | 阻止函数创建 | 阻止函数更新 | 
| --- | --- | --- | --- | --- | --- | 
|  Ruby 3.4  |  `ruby3.4`  |  Amazon Linux 2023  |   2028 年 3 月 31 日   |   2028 年 4 月 30 日   |   2028 年 5 月 31 日   | 
|  Ruby 3.3  |  `ruby3.3`  |  Amazon Linux 2023  |   2027 年 3 月 31 日   |   2027 年 4 月 30 日   |   2027 年 5 月 31 日   | 
|  Ruby 3.2  |  `ruby3.2`  |  Amazon Linux 2  |   2026 年 3 月 31 日   |   2026 年 8 月 31 日   |   Sep 30, 2026   | 

**创建 Ruby 函数**

1. 打开 [Lambda 控制台](https://console.aws.amazon.com/lambda)。

1. 选择 **Create function**（创建函数）。

1. 配置以下设置：
   + **函数名称**：输入函数名称。
   + **运行时**：选择 **Ruby 3.4**。

1. 选择**创建函数**。

控制台将使用名为 `lambda_function.rb` 的源文件创建一个 Lambda 函数。您可以在内置代码编辑器中编辑此文件并添加更多文件。在**部署**部分，选择**部署**以更新函数的代码。然后，要运行您的代码，请在**测试事件**部分中选择**创建测试事件**。

`lambda_function.rb` 文件会导出一个名为 `lambda_handler` 的函数，此函数将接受事件对象和上下文对象。这是 Lambda 在调用函数时调用的[处理函数](ruby-handler.md)。Ruby 函数运行时从 Lambda 获取调用事件并将其传递到处理程序。在函数配置中，处理程序值为 `lambda_function.lambda_handler`。

保存函数代码时，Lambda 控制台会创建一个 .zip 文件归档部署包。在控制台外部开发函数代码时（使用 IDE），您需要[创建部署程序包](ruby-package.md)将代码上载到 Lambda 函数。

除了调用事件之外，函数运行时还将上下文对象传递给处理程序。[上下文对象](ruby-context.md)包含有关调用、函数和执行环境的其他信息。环境变量中提供了更多信息。

您的 Lambda 函数附带了 CloudWatch Logs 日志组。函数运行时会将每次调用的详细信息发送到 CloudWatch Logs。该运行时会中继调用期间[函数输出的任何日志](ruby-logging.md)。如果您的函数返回错误，则 Lambda 将为错误设置格式，并将其返回给调用方。

**Topics**
+ [

## 包含运行时的 SDK 版本
](#ruby-sdk-included)
+ [

## 再启用一个 Ruby JIT（YJIT）
](#ruby-yjit)
+ [

# 定义采用 Ruby 的 Lambda 函数处理程序
](ruby-handler.md)
+ [

# 使用 .zip 文件归档部署 Ruby Lambda 函数
](ruby-package.md)
+ [

# 使用容器镜像部署 Ruby Lambda 函数
](ruby-image.md)
+ [

# 使用 Ruby Lambda 函数的层
](ruby-layers.md)
+ [

# 使用 Lambda 上下文对象检索 Ruby 函数信息
](ruby-context.md)
+ [

# Ruby Lambda 函数日志记录和监控
](ruby-logging.md)
+ [

# 在 AWS Lambda 中检测 Ruby 代码
](ruby-tracing.md)

## 包含运行时的 SDK 版本
<a name="ruby-sdk-included"></a>

Ruby 运行时中包含的 AWS SDK 版本取决于运行时版本和您的 AWS 区域。适用于 Ruby 的 AWS SDK 采用模块化设计，并按照 AWS 服务各自独立。要查找您正在使用的运行时中包含的特定服务 Gem 的版本号，请使用以下格式的代码创建 Lambda 函数。用您的代码使用的服务 Gem 的名称替换 `aws-sdk-s3` 和 `Aws::S3`。

```
require 'aws-sdk-s3'

def lambda_handler(event:, context:)
  puts "Service gem version: #{Aws::S3::GEM_VERSION}"
  puts "Core version: #{Aws::CORE_GEM_VERSION}"
end
```

## 再启用一个 Ruby JIT（YJIT）
<a name="ruby-yjit"></a>

Ruby 运行时系统支持 [YJIT](https://docs.ruby-lang.org/en/master/jit/yjit_md.html)，这是一款轻量级的极简 Ruby JIT 编译器。YJIT 提供的性能有显著提升，但消耗的内存也比 Ruby 解释器更多。建议将 YJIT 用于 Ruby on Rails 工作负载。

默认情况下，将不会启用 YJIT。要为 Ruby 函数启用 YJIT，请将 `RUBY_YJIT_ENABLE` 环境变量设置为 `1`。要确认已启用 YJIT，请打印 `RubyVM::YJIT.enabled?` 方法的结果。

**Example ：确认已启用 YJIT**  

```
puts(RubyVM::YJIT.enabled?())
# => true
```

# 定义采用 Ruby 的 Lambda 函数处理程序
<a name="ruby-handler"></a>

Lambda 函数*处理程序*是函数代码中处理事件的方法。当调用函数时，Lambda 运行处理程序方法。您的函数会一直运行，直到处理程序返回响应、退出或超时。

**Topics**
+ [

## Ruby 处理程序基础知识
](#ruby-handler-basics)
+ [

## Ruby Lambda 函数的代码最佳实践
](#ruby-best-practices)

## Ruby 处理程序基础知识
<a name="ruby-handler-basics"></a>

在以下示例中，文件 `function.rb` 将定义一个名为 `handler` 的处理程序方法。该处理程序函数将选取两个对象作为输入并返回一个 JSON 文档。

**Example function.rb**  

```
require 'json'

def handler(event:, context:)
    { event: JSON.generate(event), context: JSON.generate(context.inspect) }
end
```

在您的函数配置中，`handler` 设置指示 Lambda 在何处查找处理程序。对于上述示例，此设置的正确值为 **function.handler**。它包含两个由点分隔的名称：文件的名和处理程序方法的名称。

您还可以在类中定义处理程序方法。以下示例在名为 `process` 的模块中的名为 `Handler` 的类上定义了一个名为 `LambdaFunctions` 的处理程序。

**Example source.rb**  

```
module LambdaFunctions
  class Handler
    def self.process(event:,context:)
      "Hello!"
    end
  end
end
```

在本例中，处理程序设置为 **source.LambdaFunctions::Handler.process**。

该处理程序接受的两个对象是调用事件和上下文。事件是一个 Ruby 对象，包含由调用方提供的负载。如果该负载为 JSON 文档，则事件对象为 Ruby 哈希。否则，它是一个字符串。[上下文对象](ruby-context.md)具有一些方法和属性，它们提供了有关调用、函数和执行环境的信息。

函数处理程序在 Lambda 函数每次被调用时执行。处理程序外部的静态代码对该函数的每个实例执行一次。如果您的处理程序使用开发工具包客户端和数据库连接之类的资源，您可以在处理程序方法外部创建这些资源以对多个调用重复使用它们。

您的函数的每个实例都可以处理多个调用事件，但一次只能处理一个事件。在给定的任何时间，处理事件的实例数都是您的函数的*并发*。有关 Lambda 执行环境的更多信息，请参阅 [了解 Lambda 执行环境生命周期](lambda-runtime-environment.md)。

## Ruby Lambda 函数的代码最佳实践
<a name="ruby-best-practices"></a>

在构建 Lambda 函数时，请遵循以下列表中的指南，采用最佳编码实践：
+ **从核心逻辑中分离 Lambda 处理程序。**这样您可以创建更容易进行单元测试的函数。例如，在 Ruby 中，如下所示：

  ```
  def lambda_handler(event:, context:)
      foo = event['foo']
      bar = event['bar']
      
      result = my_lambda_function(foo:, bar:)
  
  end
  
  def my_lambda_function(foo:, bar:)
      // MyLambdaFunction logic here
      
  end
  ```
+ **控制函数部署包中的依赖项。**AWS Lambda 执行环境包含许多库。对于 Ruby 运行时，其中包括 AWS SDK。Lambda 会定期更新这些库，以支持最新的功能组合和安全更新。这些更新可能会使 Lambda 函数的行为发生细微变化。要完全控制您的函数所用的依赖项，请使用部署程序包来打包所有依赖项。
+ **将依赖关系的复杂性降至最低。**首选在[执行环境](lambda-runtime-environment.md)启动时可以快速加载的更简单的框架。
+ **将部署包大小精简为只包含运行时必要的部分。**这样会减少调用前下载和解压缩部署程序包所需的时间。对于用 Ruby 编写的函数，请勿将整个 AWS SDK 库作为部署包的一部分上传，而是有选择地依赖于获取您所需的 SDK 组件的 gem（例如 DynamoDB 或 Amazon S3 SDK gem）。

**利用执行环境重用来提高函数性能。**连接软件开发工具包 (SDK) 客户端和函数处理程序之外的数据库，并在 `/tmp` 目录中本地缓存静态资产。由函数的同一实例处理的后续调用可重用这些资源。这样就可以通过缩短函数运行时间来节省成本。

为了避免调用之间潜在的数据泄露，请不要使用执行环境来存储用户数据、事件或其他具有安全影响的信息。如果您的函数依赖于无法存储在处理程序的内存中的可变状态，请考虑为每个用户创建单独的函数或单独的函数版本。

**使用 keep-alive 指令来维护持久连接。**Lambda 会随着时间的推移清除空闲连接。在调用函数时尝试重用空闲连接会导致连接错误。要维护您的持久连接，请使用与运行时关联的 keep-alive 指令。有关示例，请参阅[在 Node.js 中通过 Keep-Alive 重用连接](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html)。

**使用[环境变量](configuration-envvars.md)将操作参数传递给函数。**例如，您在写入 Amazon S3 存储桶时，不应对要写入的存储桶名称进行硬编码，而应将存储桶名称配置为环境变量。

**避免在 Lambda 函数中使用递归调用**，在这种情况下，函数会调用自己或启动可能再次调用该函数的进程。这可能会导致意想不到的函数调用量和升级成本。如果您看到意外的调用量，请立即将函数保留并发设置为 `0` 来限制对函数的所有调用，同时更新代码。

Lambda 函数代码中**不要使用非正式的非公有 API**。对于 AWS Lambda 托管式运行时，Lambda 会定期为 Lambda 的内部 API 应用安全性和功能更新。这些内部 API 更新可能不能向后兼容，会导致意外后果，例如，假设您的函数依赖于这些非公有 API，则调用会失败。请参阅 [API 参考](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)以查看公开发布的 API 列表。

**编写幂等代码。**为您的函数编写幂等代码可确保以相同的方式处理重复事件。您的代码应该正确验证事件并优雅地处理重复事件。有关更多信息，请参阅[如何使我的 Lambda 函数具有幂等性？](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/)。

# 使用 .zip 文件归档部署 Ruby Lambda 函数
<a name="ruby-package"></a>

 AWS Lambda 函数的代码包含一个 .rb 文件，其中包含函数的处理程序代码，以及代码所依赖的任何其他依赖项（Gem）。要将此函数部署到 Lambda，您可以使用*部署包*。此包可以是 .zip 文件归档或容器映像。有关在 Ruby 中使用容器映像的更多信息，请参阅[使用容器映像部署 Ruby Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/ruby-image.html)。

 要创建 .zip 文件归档格式的部署包，可以使用命令行工具内置的 .zip 文件归档实用工具或任何其他 .zip 文件实用工具（例如 [7zip](https://www.7-zip.org/download.html)）。以下各部分中显示的示例假设您在 Linux 或 macOS 环境中使用命令行 `zip` 工具。要在 Windows 中使用相同命令，您可以安装 [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10)，以获取 Windows 集成版本的 Ubuntu 和 Bash。

 请注意，Lambda 使用 POSIX 文件权限，因此在创建 .zip 文件归档之前，您可能需要[为部署包文件夹设置权限](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-deployment-package-errors/)。

以下部分中的示例命令使用 [Bundler](https://bundler.io/) 实用程序为部署包添加依赖项。要安装 Bundler，请运行以下命令：

```
gem install bundler
```

**Topics**
+ [

## Ruby 中的依赖项
](#ruby-package-runtime-dependencies)
+ [

## 创建不含依赖项的 .zip 部署包
](#ruby-package-codeonly)
+ [

## 创建含依赖项的 .zip 部署包
](#ruby-package-dependencies)
+ [

## 为依赖项创建 Ruby 层
](#ruby-package-dependencies-layers)
+ [

## 使用原生库创建 .zip 部署包
](#ruby-package-native)
+ [

## 使用 .zip 文件创建和更新 Ruby Lambda 函数
](#ruby-package-create-functions)

## Ruby 中的依赖项
<a name="ruby-package-runtime-dependencies"></a>

对于使用 Ruby 运行时系统的 Lambda 函数，依赖项可以是任何 Ruby Gem。使用 .zip 存档部署函数时，可以使用函数代码或使用 Lambda 层将这些依赖项添加到 .zip 文件中。层是可以包含其他代码或其他内容的单独的 .zip 文件。要了解有关使用 Lambda 层的更多信息，请参阅 [使用层管理 Lambda 依赖项](chapter-layers.md)。

Ruby 运行时包括 适用于 Ruby 的 AWS SDK。如果您的函数使用开发工具包，则无需将其与代码捆绑。不过，如果您希望保持对依赖项的完全控制权或使用特定版本的开发工具包，则可将其添加到函数的部署包中。您可以将开发工具包包含在.zip 文件中，也可以使用 Lambda 层进行添加。.zip 文件或 Lambda 层中的依赖项优先于运行时系统中包含的版本。要查找运行时系统版本中包含哪个版本的 SDK for Ruby，请参阅 [包含运行时的 SDK 版本](lambda-ruby.md#ruby-sdk-included)。

 在 [AWS 责任共担模式](lambda-runtimes.md#runtimes-shared-responsibility)下，您负责管理函数部署包中的所有依赖项。这包括应用更新和安全补丁。要更新函数部署包中的依赖项，请先创建一个新的 .zip 文件，然后将其上传到 Lambda 中。有关更多信息，请参阅 [创建含依赖项的 .zip 部署包](#ruby-package-dependencies) 和 [使用 .zip 文件创建和更新 Ruby Lambda 函数](#ruby-package-create-functions)。

## 创建不含依赖项的 .zip 部署包
<a name="ruby-package-codeonly"></a>

如果您的函数代码没有依赖项，则 .zip 文件仅包含带有函数处理程序代码的 .rb 文件。使用首选 ZIP 实用工具创建一个 .zip 文件，并将 .rb 文件置于根目录中。如果 .rb 文件不在 .zip 文件的根目录下，Lambda 将无法运行代码。

要了解如何部署 .zip 文件以创建新的 Lambda 函数或更新现有函数，请参阅 [使用 .zip 文件创建和更新 Ruby Lambda 函数](#ruby-package-create-functions)。

## 创建含依赖项的 .zip 部署包
<a name="ruby-package-dependencies"></a>

如果函数代码依赖其他 Ruby Gem，您可以使用函数代码将这些依赖项添加到 .zip 文件中，也可以使用 [Lambda 层](chapter-layers.md)进行添加。本部分中的说明旨在向您展示如何将依赖项包含在 .zip 部署包中。有关如何将依赖项包含在层中的说明，请参阅 [为依赖项创建 Ruby 层](#ruby-package-dependencies-layers)。

假设函数代码保存在项目目录下名为 `lambda_function.rb` 的文件中。以下示例 CLI 命令将创建名为 `my_deployment_package.zip` 的 .zip 文件，其中包含函数代码及其依赖项。

**创建部署包**

1. 在项目目录中，创建 `Gemfile` 来指定其中的依赖项。

   ```
   bundle init
   ```

1. 使用首选文本编辑器对 `Gemfile` 进行编辑，从而指定函数的依赖项。例如，要使用 TZInfo Gem，请按照如下所示编辑 `Gemfile`。

   ```
   source "https://rubygems.org"
   gem "tzinfo"
   ```

1. 运行以下命令，将 `Gemfile` 中指定的 Gem 安装到项目目录中。此命令将 `vendor/bundle` 设置为 Gem 的默认安装路径。

   ```
   bundle config set --local path 'vendor/bundle' && bundle install
   ```

   您应该可以看到类似于如下所示的输出内容。

   ```
   Fetching gem metadata from https://rubygems.org/...........
   Resolving dependencies...
   Using bundler 2.4.13
   Fetching tzinfo 2.0.6
   Installing tzinfo 2.0.6
   ...
   ```
**注意**  
稍后想再次全局安装 Gem，请运行以下命令：  

   ```
   bundle config set --local system 'true'
   ```

1. 创建 .zip 文件存档，其中包含带有函数处理程序代码以及您在上一步中安装的依赖项的 `lambda_function.rb` 文件。

   ```
   zip -r my_deployment_package.zip lambda_function.rb vendor
   ```

   您应该可以看到类似于如下所示的输出内容。

   ```
   adding: lambda_function.rb (deflated 37%)
     adding: vendor/ (stored 0%)
     adding: vendor/bundle/ (stored 0%)
     adding: vendor/bundle/ruby/ (stored 0%)
     adding: vendor/bundle/ruby/3.2.0/ (stored 0%)
     adding: vendor/bundle/ruby/3.2.0/build_info/ (stored 0%)
     adding: vendor/bundle/ruby/3.2.0/cache/ (stored 0%)
     adding: vendor/bundle/ruby/3.2.0/cache/aws-eventstream-1.0.1.gem (deflated 36%)
   ...
   ```

## 为依赖项创建 Ruby 层
<a name="ruby-package-dependencies-layers"></a>

要了解如何将您的 Ruby 依赖项打包到 Lambda 层中，请参阅[使用 Ruby Lambda 函数的层](ruby-layers.md)。

## 使用原生库创建 .zip 部署包
<a name="ruby-package-native"></a>

许多常见的 Ruby Gem（例如 `nokogiri`、`nio4r` 和 `mysql`），都包含用 C 语言编写的本机扩展。将包含 C 代码的库添加到部署包时，必须正确构建程序包，确保其与 Lambda 执行环境兼容。

对于生产应用程序，建议您使用 AWS Serverless Application Model（AWS SAM）来构建和部署代码。在 AWS SAM 中，使用 `sam build --use-container` 选项在类似 Lambda 的 Docker 容器中构建函数。要了解有关使用 AWS SAM 来部署函数代码的更多信息，请参阅《AWS SAM 开发人员指南》**中的 [Building applications](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-using-build.html)。

要在不使用 AWS SAM 的情况下创建包含带本机扩展的 Gem 的.zip 部署包，您也可以使用容器将依赖项捆绑到与 Lambda Ruby 运行时系统环境相同的环境中。要完成这些步骤，就必须在生成计算机上安装 Docker。要了解有关安装 Docker 的更多信息，请参阅 [Install Docker Engine](https://docs.docker.com/engine/install/)。

**在 Docker 容器中创建.zip 部署包**

1. 在本地生成计算机上创建文件夹来保存容器。在该文件夹中，创建一个名为 `dockerfile` 的文件，再将以下代码粘贴到该文件中。

   ```
   FROM public.ecr.aws/sam/build-ruby3.2:latest-x86_64
   RUN gem update bundler 
   CMD "/bin/bash"
   ```

1. 在您创建 `dockerfile` 的文件夹中，运行以下命令来创建 Docker 容器。

   ```
   docker build -t awsruby32 .
   ```

1. 导航到项目目录，其中包含带有函数处理程序代码以及指定函数依赖项的 `Gemfile` 的 `.rb` 文件。在该目录中，运行以下命令启动 Lambda Ruby 容器。

------
#### [ Linux/MacOS ]

   ```
   docker run --rm -it -v $PWD:/var/task -w /var/task awsruby32
   ```

**注意**  
在 MacOS 中，您可能会看到一条警告，告知您所请求映像的平台与检测到的主机平台不匹配。请忽略该警告。

------
#### [ Windows PowerShell ]

   ```
   docker run --rm -it -v ${pwd}:var/task -w /var/task awsruby32
   ```

------

   容器启动时，您应该会看到 bash 提示符。

   ```
   bash-4.2#
   ```

1. 配置捆绑实用程序，将 `Gemfile` 中指定的 Gem 安装到本地 `vendor/bundle` 目录中并安装依赖项。

   ```
   bash-4.2# bundle config set --local path 'vendor/bundle' && bundle install
   ```

1. 创建包含函数代码及其依赖项的 .zip 部署包。在此示例中，包含函数处理程序代码的文件名为 `lambda_function.rb`。

   ```
   bash-4.2# zip -r my_deployment_package.zip lambda_function.rb vendor
   ```

1. 退出容器并返回到本地项目目录。

   ```
   bash-4.2# exit
   ```

   现在，您可以使用.zip 文件部署包来创建或更新 Lambda 函数。请参阅 [使用 .zip 文件创建和更新 Ruby Lambda 函数](#ruby-package-create-functions)。

## 使用 .zip 文件创建和更新 Ruby Lambda 函数
<a name="ruby-package-create-functions"></a>

 创建 .zip 部署包后，您可以用其创建新的 Lambda 函数或更新现有的 Lambda 函数。您可以使用 Lambda 控制台、AWS Command Line Interface 和 Lambda API 部署 .zip 程序包。您也可以使用 AWS Serverless Application Model（AWS SAM）和 CloudFormation 创建和更新 Lambda 函数。

Lambda 的 .zip 部署包的最大大小为 250MB（已解压缩）。请注意，此限制适用于您上传的所有文件（包括任何 Lambda 层）的组合大小。

Lambda 运行时需要权限才能读取部署包中的文件。在 Linux 权限八进制表示法中，Lambda 对于不可执行文件（rw-r--r--）需要 644 个权限，对于目录和可执行文件需要 755 个权限（rwxr-xr-x）。

在 Linux 和 MacOS 中，使用 `chmod` 命令更改部署包中文件和目录的文件权限。例如，要为不可执行文件提供正确的权限，请运行以下命令。

```
chmod 644 <filepath>
```

要在 Windows 中更改文件权限，请参阅 Microsoft Windows 文档中的 [Set, View, Change, or Remove Permissions on an Object](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc731667(v=ws.10))。

**注意**  
如果您不向 Lambda 授予访问部署包中目录所需的权限，Lambda 会将这些目录的权限设置为 755（rwxr-xr-x）。

### 使用控制台通过 .zip 文件创建和更新函数
<a name="ruby-package-create-console"></a>

 要创建新函数，必须先在控制台中创建该函数，然后上传您的 .zip 归档。要更新现有函数，请打开函数页面，然后按照相同的步骤添加更新的 .zip 文件。

 如果您的 .zip 文件小于 50MB，则可以通过直接从本地计算机上传该文件来创建或更新函数。对于大于 50MB 的 .zip 文件，必须首先将您的程序包上传到 Amazon S3 存储桶。有关如何使用 AWS 管理控制台 将文件上传到 Amazon S3 存储桶的说明，请参阅 [Amazon S3 入门](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html)。要使用 AWS CLI 上传文件，请参阅《AWS CLI 用户指南**》中的[移动对象](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)。

**注意**  
您无法更改现有函数的[部署包类型](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-PackageType)（.zip 或容器映像）。例如，您无法将容器映像函数转换为使用 .zip 文件归档。您必须创建新函数。

**创建新函数（控制台）**

1. 打开 Lambda 控制台的[“函数”页面](https://console.aws.amazon.com/lambda/home#/functions)，然后选择**创建函数**。

1. 选择**从头开始创作**。

1. 在**基本信息**中，执行以下操作：

   1. 对于**函数名称**，输入函数的名称。

   1. 对于**运行时系统**，选择要使用的运行时系统。

   1. （可选）对于**架构**，选择要用于函数的指令集架构。默认架构为 x86\$164。确保您的函数的 .zip 部署包与您选择的指令集架构兼容。

1. （可选）在 **Permissions**（权限）下，展开 **Change default execution role**（更改默认执行角色）。您可以创建新的**执行角色**，也可以使用现有角色。

1. 选择 **Create function (创建函数)**。Lambda 使用您选择的运行时系统创建基本“Hello world”函数。

**从本地计算机上传 .zip 归档（控制台）**

1. 在 Lambda 控制台的[“函数”页面](https://console.aws.amazon.com/lambda/home#/functions)中，选择要为其上传 .zip 文件的函数。

1. 选择**代码**选项卡。

1. 在**代码源**窗格中，选择**上传自**。

1. 选择 **.zip 文件**。

1. 要上传 .zip 文件，请执行以下操作：

   1. 选择**上传**，然后在文件选择器中选择您的 .zip 文件。

   1. 选择**打开**。

   1. 选择**保存**。

**从 Amazon S3 存储桶上传 .zip 归档（控制台）**

1. 在 Lambda 控制台的[“函数”页面](https://console.aws.amazon.com/lambda/home#/functions)中，选择要为其上传新 .zip 文件的函数。

1. 选择**代码**选项卡。

1. 在**代码源**窗格中，选择**上传自**。

1. 选择 **Amazon S3 位置**。

1. 粘贴 .zip 文件的 Amazon S3 链接 URL，然后选择**保存**。

### 使用控制台代码编辑器更新 .zip 文件函数
<a name="ruby-package-console-edit"></a>

 对于某些带有 .zip 部署包的函数，您可以使用 Lambda 控制台的内置代码编辑器直接更新函数代码。要使用此功能，函数必须满足以下条件：
+ 函数必须使用一种解释性语言运行时系统（Python、Node.js 或 Ruby）
+ 函数的部署包必须小于 50 MB（未压缩状态）。

带有容器映像部署包的函数的代码不能直接在控制台中编辑。

**要使用控制台代码编辑器更新函数代码。**

1. 打开 Lambda 控制台的[“函数”页面](https://console.aws.amazon.com/lambda/home#/functions)，然后选择函数。

1. 选择**代码**选项卡。

1. 在**代码源**窗格中，选择源代码文件并在集成的代码编辑器中对其进行编辑。

1. 在**部署**部分，选择**部署**以更新函数的代码：  
![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

### 使用 AWS CLI 通过 .zip 文件创建和更新函数
<a name="ruby-package-create-cli"></a>

 您可以使用 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 创建新函数或使用 .zip 文件更新现有函数。使用 [create-function](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-function.html) 和 [update-function-code](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-function.html) 命令部署 .zip 程序包。如果您的 .zip 文件小于 50MB，则可以从本地生成计算机上的文件位置上传 .zip 程序包。对于较大的文件，必须从 Amazon S3 存储桶上传 .zip 程序包。有关如何使用 AWS CLI 将文件上传到 Amazon S3 存储桶的说明，请参阅《AWS CLI 用户指南**》中的[移动对象](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)。

**注意**  
如果您使用 AWS CLI 从 Amazon S3 存储桶上传 .zip 文件，则该存储桶必须与您的函数位于同一个 AWS 区域 中。

 要通过 AWS CLI 使用 .zip 文件创建新函数，则必须指定以下内容：
+ 函数的名称 (`--function-name`)
+ 函数的运行时系统 (`--runtime`)
+ 函数的[执行角色](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html) (`--role`) 的 Amazon 资源名称（ARN）
+ 函数代码 (`--handler`) 中处理程序方法的名称

 还必须指定 .zip 文件的位置。如果 .zip 文件位于本地生成计算机上的文件夹中，请使用 `--zip-file` 选项指定文件路径，如以下示例命令所示。

```
aws lambda create-function --function-name myFunction \
--runtime ruby3.2 --handler lambda_function.lambda_handler \
--role arn:aws:iam::111122223333:role/service-role/my-lambda-role \
--zip-file fileb://myFunction.zip
```

 要指定 .zip 文件在 Amazon S3 存储桶中的位置，请使用 `--code` 选项，如以下示例命令所示。您只需对版本控制对象使用 `S3ObjectVersion` 参数。

```
aws lambda create-function --function-name myFunction \
--runtime ruby3.2 --handler lambda_function.lambda_handler \
--role arn:aws:iam::111122223333:role/service-role/my-lambda-role \
--code S3Bucket=amzn-s3-demo-bucket,S3Key=myFileName.zip,S3ObjectVersion=myObjectVersion
```

 要使用 CLI 更新现有函数，请使用 `--function-name` 参数指定函数的名称。您还必须指定要用于更新函数代码的 .zip 文件的位置。如果 .zip 文件位于本地生成计算机上的文件夹中，请使用 `--zip-file` 选项指定文件路径，如以下示例命令所示。

```
aws lambda update-function-code --function-name myFunction \
--zip-file fileb://myFunction.zip
```

 要指定 .zip 文件在 Amazon S3 存储桶中的位置，请使用 `--s3-bucket` 和 `--s3-key` 选项，如以下示例命令所示。您只需对版本控制对象使用 `--s3-object-version` 参数。

```
aws lambda update-function-code --function-name myFunction \
--s3-bucket amzn-s3-demo-bucket --s3-key myFileName.zip --s3-object-version myObject Version
```

### 使用 Lambda API 通过 .zip 文件创建和更新函数
<a name="ruby-package-create-api"></a>

 要使用 .zip 文件归档创建和更新函数，请使用以下 API 操作：
+ [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html)
+ [UpdateFunctionCode](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionCode.html)

### 使用 AWS SAM 通过 .zip 文件创建和更新函数
<a name="ruby-package-create-sam"></a>

 AWS Serverless Application Model（AWS SAM）是一个工具包，可帮助简化在 AWS 上构建和运行无服务器应用程序的过程。您可以在 YAML 或 JSON 模板中为应用程序定义资源，并使用 AWS SAM 命令行界面（AWS SAM CLI）构建、打包和部署应用程序。当您通过 AWS SAM 模板构建 Lambda 函数时，AWS SAM 会使用您的函数代码和您指定的任何依赖项自动创建 .zip 部署包或容器映像。要了解有关使用 AWS SAM 构建和部署 Lambda 函数的更多信息，请参阅《AWS Serverless Application Model 开发人员指南**》中的 [AWS SAM 入门](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html)。

您可以使用 AWS SAM 创建使用现有 .zip 文件归档的 Lambda 函数。要使用 AWS SAM 创建 Lambda 函数，您可以将 .zip 文件保存在 Amazon S3 存储桶或生成计算机上的本地文件夹中。有关如何使用 AWS CLI 将文件上传到 Amazon S3 存储桶的说明，请参阅《AWS CLI 用户指南**》中的[移动对象](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)。

 在 AWS SAM 模板中，`AWS::Serverless::Function` 资源将指定 Lambda 函数。在此资源中，设置以下属性以创建使用 .zip 文件归档的函数：
+ `PackageType` – 设置为 `Zip`
+ `CodeUri` – 设置为函数代码的 Amazon S3 URI、本地文件夹的路径或 [FunctionCode](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-functioncode.html) 对象
+ `Runtime` – 设置为您选择的运行时系统

 使用 AWS SAM，如果 .zip 文件大于 50MB，则不需要先将其上传到 Amazon S3 存储桶。AWS SAM 可以从本地生成计算机上的某个位置上传最大允许大小为 250MB（已解压缩）的 .zip 程序包。

 要了解有关在 AWS SAM 中使用 .zip 文件部署函数的更多信息，请参阅《AWS SAM 开发人员指南**》中的 [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)。

### 使用 CloudFormation 通过 .zip 文件创建和更新函数
<a name="ruby-package-create-cfn"></a>

 您可以使用 CloudFormation 创建使用 .zip 文件归档的 Lambda 函数。要从 .zip 文件创建 Lambda 函数，必须先将您的文件上传到 Amazon S3 存储桶。有关如何使用 AWS CLI 将文件上传到 Amazon S3 存储桶的说明，请参阅《AWS CLI 用户指南**》中的[移动对象](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)。

在 CloudFormation 模板中，`AWS::Lambda::Function` 资源将指定 Lambda 函数。在此资源中，设置以下属性以创建使用 .zip 文件归档的函数：
+ `PackageType` – 设置为 `Zip`
+ `Code` – 在 `S3Bucket` 和 `S3Key` 字段中输入 Amazon S3 存储桶名称和 .zip 文件名。
+ `Runtime` – 设置为您选择的运行时系统

 CloudFormation 生成的 .zip 文件不能超过 4MB。要了解有关在 CloudFormation 中使用 .zip 文件部署函数的更多信息，请参阅《CloudFormation 用户指南**》中的 [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)。

# 使用容器镜像部署 Ruby Lambda 函数
<a name="ruby-image"></a>

有三种方法可以为 Ruby Lambda 函数构建容器映像：
+ [使用 Ruby 的 AWS 基本映像](#ruby-image-instructions)

  [AWS 基本映像](images-create.md#runtimes-images-lp)会预加载一个语言运行时系统、一个用于管理 Lambda 和函数代码之间交互的运行时系统接口客户端，以及一个用于本地测试的运行时系统接口仿真器。
+ [使用 AWS 仅限操作系统的基础镜像](images-create.md#runtimes-images-provided)

  [AWS 仅限操作系统的运行时系统](https://gallery.ecr.aws/lambda/provided)包含 Amazon Linux 发行版和[运行时系统接口模拟器](https://github.com/aws/aws-lambda-runtime-interface-emulator/)。这些镜像通常用于为编译语言（例如 [Go](go-image.md#go-image-provided) 和 [Rust](lambda-rust.md)）以及 Lambda 未提供基础映像的语言或语言版本（例如 Node.js 19）创建容器镜像。您也可以使用仅限操作系统的基础映像来实施[自定义运行时系统](runtimes-custom.md)。要使映像与 Ruby 兼容，您必须在映像中包含 [Java 的运行时系统接口客户端](#ruby-image-clients)。
+ [使用非 AWS 基本映像](#ruby-image-clients)

  您还可以使用其他容器注册表的备用基本映像，例如 Alpine Linux 或 Debian。您还可以使用您的组织创建的自定义映像。要使映像与 Ruby 兼容，您必须在映像中包含 [Java 的运行时系统接口客户端](#ruby-image-clients)。

**提示**  
要缩短 Lambda 容器函数激活所需的时间，请参阅 Docker 文档中的[使用多阶段构建](https://docs.docker.com/build/building/multi-stage/)。要构建高效的容器映像，请遵循[编写 Dockerfiles 的最佳实践](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)。

此页面介绍了如何为 Lambda 构建、测试和部署容器映像。

**Topics**
+ [

## Ruby AWS 基本映像
](#ruby-image-base)
+ [

## 使用 Ruby 的 AWS 基本映像
](#ruby-image-instructions)
+ [

## 将备用基本映像与运行时系统接口客户端配合使用
](#ruby-image-clients)

## Ruby AWS 基本映像
<a name="ruby-image-base"></a>

AWS 为 Ruby 提供了以下基本映像：


| 标签 | 运行时 | 操作系统 | Dockerfile | 弃用 | 
| --- | --- | --- | --- | --- | 
| 3.4 | Ruby 3.4 | Amazon Linux 2023 | [GitHub 上的适用于 Ruby 3.4 的 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/ruby3.4/Dockerfile.ruby3.4) |   2028 年 3 月 31 日   | 
| 3.3 | Ruby 3.3 | Amazon Linux 2023 | [GitHub 上的适用于 Ruby 3.3 的 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/ruby3.3/Dockerfile.ruby3.3) |   2027 年 3 月 31 日   | 
| 3.2 | Ruby 3.2 | Amazon Linux 2 | [GitHub 上的适用于 Ruby 3.2 的 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/ruby3.2/Dockerfile.ruby3.2) |   2026 年 3 月 31 日   | 

Amazon ECR 存储库：[gallery.ecr.aws/lambda/ruby](https://gallery.ecr.aws/lambda/ruby)

## 使用 Ruby 的 AWS 基本映像
<a name="ruby-image-instructions"></a>

### 先决条件
<a name="ruby-image-prerequisites"></a>

要完成本节中的步骤，您必须满足以下条件：
+ [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker)（最低版本 25.0.0）
+ Docker [buildx 插件](https://github.com/docker/buildx/blob/master/README.md)。
+ Ruby

### 从基本映像创建映像
<a name="ruby-image-create"></a>

**要创建适用于 Ruby 的容器映像**

1. 为项目创建一个目录，然后切换到该目录。

   ```
   mkdir example
   cd example
   ```

1. 创建名为 `Gemfile` 的新文件。您可以在此处列出应用程序所需的 RubyGems 软件包。适用于 Ruby 的 AWS SDK 可从 RubyGems 获得。您应该选择特定的 AWS 服务 Gem 进行安装。例如，要使用[适用于 Lambda 的 Ruby Gem](https://rubygems.org/gems/aws-sdk-lambda/)，Gemfile 应如下所示：

   ```
   source 'https://rubygems.org'
   
   gem 'aws-sdk-lambda'
   ```

   或者，[aws-sdk](https://rubygems.org/gems/aws-sdk/) Gem 包含所有可用的 AWS 服务 Gem。此 Gem 非常大。我们建议您仅在依赖许多 AWS 服务时使用它。

1. 使用 [bundle 安装](https://bundler.io/v2.4/man/bundle-install.1.html)来安装 Gemfile 中指定的依赖项。

   ```
   bundle install
   ```

1. 创建名为 `lambda_function.rb` 的新文件。您可以将以下示例函数代码添加到文件中进行测试，也可以使用您自己的函数代码。  
**Example Ruby 函数**  

   ```
   module LambdaFunction
     class Handler
       def self.process(event:,context:)
         "Hello from Lambda!"
       end
     end
   end
   ```

1. 创建新 Dockerfile。以下示例 Dockerfile 使用 [AWS](images-create.md#runtimes-images-lp) 基本映像。此 Docerfile 使用以下配置：
   + 将 `FROM` 属性设置为基本映像的 URI。
   + 使用 COPY 命令将函数代码和运行时系统依赖项复制到 `{LAMBDA_TASK_ROOT}`，此为 [Lambda 定义的环境变量](configuration-envvars.md#configuration-envvars-runtime)。
   + 将 `CMD` 参数设置为 Lambda 函数处理程序。

   请注意，示例 Dockerfile 不包含 [USER 指令](https://docs.docker.com/reference/dockerfile/#user)。当您将容器映像部署到 Lambda 时，Lambda 会自动定义具有最低权限的默认 Linux 用户。这与标准 Docker 行为不同，标准 Docker 在未提供 `USER` 指令时默认为 `root` 用户。  
**Example Dockerfile**  

   ```
   FROM public.ecr.aws/lambda/ruby:3.4
   
   # Copy Gemfile and Gemfile.lock
   COPY Gemfile Gemfile.lock ${LAMBDA_TASK_ROOT}/
   
   # Install Bundler and the specified gems
   RUN gem install bundler:2.4.20 && \
       bundle config set --local path 'vendor/bundle' && \
       bundle install
   
   # Copy function code
   COPY lambda_function.rb ${LAMBDA_TASK_ROOT}/    
   
   # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
   CMD [ "lambda_function.LambdaFunction::Handler.process" ]
   ```

1. 使用 [docker build](https://docs.docker.com/engine/reference/commandline/build/) 命令构建 Docker 映像。以下示例将映像命名为 `docker-image` 并为其提供 `test` [标签](https://docs.docker.com/engine/reference/commandline/build/#tag)。要使您的映像与 Lambda 兼容，您必须使用 `--provenance=false` 选项。

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**注意**  
该命令指定了 `--platform linux/amd64` 选项，可确保无论生成计算机的架构如何，容器始终与 Lambda 执行环境兼容。如果打算使用 ARM64 指令集架构创建 Lambda 函数，请务必将命令更改为使用 `--platform linux/arm64` 选项。

### （可选）在本地测试映像
<a name="ruby-image-test"></a>

1. 使用 **docker run** 命令启动 Docker 映像。在此示例中，`docker-image` 是映像名称，`test` 是标签。

   ```
   docker run --platform linux/amd64 -p 9000:8080 docker-image:test
   ```

   此命令会将映像作为容器运行，并在 `localhost:9000/2015-03-31/functions/function/invocations` 创建本地端点。
**注意**  
如果为 ARM64 指令集架构创建 Docker 映像，请务必使用 `--platform linux/arm64` 选项，而不是 `--platform linux/amd64` 选项。

1. 在新的终端窗口中，将事件发布到本地端点。

------
#### [ Linux/macOS ]

   在 Linux 和 macOS 中，运行以下 `curl` 命令：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
   ```

   此命令使用空事件调用函数并返回响应。如果您使用自己的函数代码而不是示例函数代码，则可能需要使用 JSON 负载调用函数。示例：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   在 PowerShell 中，运行以下 `Invoke-WebRequest` 命令：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   此命令使用空事件调用函数并返回响应。如果您使用自己的函数代码而不是示例函数代码，则可能需要使用 JSON 负载调用函数。示例：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. 获取容器 ID。

   ```
   docker ps
   ```

1. 使用 [docker kill](https://docs.docker.com/engine/reference/commandline/kill/) 命令停止容器。在此命令中，将 `3766c4ab331c` 替换为上一步中的容器 ID。

   ```
   docker kill 3766c4ab331c
   ```

### 部署映像
<a name="ruby-image-deploy"></a>

**将映像上传到 Amazon ECR 并创建 Lambda 函数**

1. 运行 [get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html) 命令，以针对 Amazon ECR 注册表进行 Docker CLI 身份验证。
   + 将 `--region` 值设置为要在其中创建 Amazon ECR 存储库的 AWS 区域。
   + 将 `111122223333` 替换为您的 AWS 账户 ID。

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. 使用 [create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html) 命令在 Amazon ECR 中创建存储库。

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**注意**  
Amazon ECR 存储库必须与 Lambda 函数位于同一 AWS 区域 内。

   如果成功，您将会看到如下响应：

   ```
   {
       "repository": {
           "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world",
           "registryId": "111122223333",
           "repositoryName": "hello-world",
           "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world",
           "createdAt": "2023-03-09T10:39:01+00:00",
           "imageTagMutability": "MUTABLE",
           "imageScanningConfiguration": {
               "scanOnPush": true
           },
           "encryptionConfiguration": {
               "encryptionType": "AES256"
           }
       }
   }
   ```

1. 从上一步的输出中复制 `repositoryUri`。

1. 运行 [docker tag](https://docs.docker.com/engine/reference/commandline/tag/) 命令，将本地映像作为最新版本标记到 Amazon ECR 存储库中。在此命令中：
   + `docker-image:test` 是 Docker 映像的名称和[标签](https://docs.docker.com/engine/reference/commandline/build/#tag)。这是您在 `docker build` 命令中指定的映像名称和标签。
   + 将 `<ECRrepositoryUri>` 替换为复制的 `repositoryUri`。确保 URI 末尾包含 `:latest`。

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   示例：

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 运行 [docker push](https://docs.docker.com/engine/reference/commandline/push/) 命令，以将本地映像部署到 Amazon ECR 存储库。确保存储库 URI 末尾包含 `:latest`。

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 如果您还没有函数的执行角色，请[创建执行角色](lambda-intro-execution-role.md#permissions-executionrole-api)。在下一步中，您需要提供角色的 Amazon 资源名称（ARN）。

1. 创建 Lambda 函数。对于 `ImageUri`，指定之前的存储库 URI。确保 URI 末尾包含 `:latest`。

   ```
   aws lambda create-function \
     --function-name hello-world \
     --package-type Image \
     --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
     --role arn:aws:iam::111122223333:role/lambda-ex
   ```
**注意**  
只要映像与 Lambda 函数位于同一区域内，您就可以使用其他 AWS 账户中的映像创建函数。有关更多信息，请参阅 [Amazon ECR 跨账户权限](images-create.md#configuration-images-xaccount-permissions)。

1. 调用函数。

   ```
   aws lambda invoke --function-name hello-world response.json
   ```

   应出现如下响应：

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. 要查看函数的输出，请检查 `response.json` 文件。

要更新函数代码，您必须再次构建映像，将新映像上传到 Amazon ECR 存储库，然后使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令将映像部署到 Lambda 函数。

Lambda 会将映像标签解析为特定的映像摘要。这意味着，如果您将用于部署函数的映像标签指向 Amazon ECR 中的新映像，则 Lambda 不会自动更新该函数以使用新映像。

要将新映像部署到相同的 Lambda 函数，即使 Amazon ECR 中的映像标签保持不变，也必须使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令。在以下示例中，`--publish` 选项使用更新的容器映像创建函数的新版本。

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```

## 将备用基本映像与运行时系统接口客户端配合使用
<a name="ruby-image-clients"></a>

如果使用[仅限操作系统的基础映像](images-create.md#runtimes-images-provided)或者备用基础映像，则必须在映像中包括运行时系统接口客户端。运行时系统接口客户端可扩展 [运行时 API](runtimes-api.md)，用于管理 Lambda 和函数代码之间的交互。

使用 RubyGems.org 程序包管理器安装[适用于 Ruby 的 Lambda 运行时系统接口客户端](https://rubygems.org/gems/aws_lambda_ric)：

```
gem install aws_lambda_ric
```

您也可以从 GitHub 下载 [Ruby 运行时接口客户端](https://github.com/aws/aws-lambda-ruby-runtime-interface-client)。

以下示例演示了如何使用非 AWS 基本映像构建适用于 Ruby 的容器映像。示例 Dockerfile 使用官方 Ruby 基本映像。Docker 包含运行时系统接口客户端。

### 先决条件
<a name="ruby-alt-prerequisites"></a>

要完成本节中的步骤，您必须满足以下条件：
+ [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker)（最低版本 25.0.0）
+ Docker [buildx 插件](https://github.com/docker/buildx/blob/master/README.md)。
+ Ruby

### 从备用基本映像创建映像
<a name="ruby-alt-create"></a>

**要使用备用基本映像创建适用于 Ruby 的容器映像**

1. 为项目创建一个目录，然后切换到该目录。

   ```
   mkdir example
   cd example
   ```

1. 创建名为 `Gemfile` 的新文件。您可以在此处列出应用程序所需的 RubyGems 软件包。适用于 Ruby 的 AWS SDK 可从 RubyGems 获得。您应该选择特定的 AWS 服务 Gem 进行安装。例如，要使用[适用于 Lambda 的 Ruby Gem](https://rubygems.org/gems/aws-sdk-lambda/)，Gemfile 应如下所示：

   ```
   source 'https://rubygems.org'
   
   gem 'aws-sdk-lambda'
   ```

   或者，[aws-sdk](https://rubygems.org/gems/aws-sdk/) Gem 包含所有可用的 AWS 服务 Gem。此 Gem 非常大。我们建议您仅在依赖许多 AWS 服务时使用它。

1. 使用 [bundle 安装](https://bundler.io/v2.4/man/bundle-install.1.html)来安装 Gemfile 中指定的依赖项。

   ```
   bundle install
   ```

1. 创建名为 `lambda_function.rb` 的新文件。您可以将以下示例函数代码添加到文件中进行测试，也可以使用您自己的函数代码。  
**Example Ruby 函数**  

   ```
   module LambdaFunction
     class Handler
       def self.process(event:,context:)
         "Hello from Lambda!"
       end
     end
   end
   ```

1. 创建新 Dockerfile。以下 Dockerfile 使用 Ruby 基本映像而不是 [AWS 基本映像](images-create.md#runtimes-images-lp)。Dockerfile 包含[适用于 Ruby 的运行时系统接口客户端](https://github.com/aws/aws-lambda-ruby-runtime-interface-client)，该客户端可使映像与 Lambda 兼容。或者，您可以将运行时系统接口客户端添加到应用程序的 Gemfile 中。
   + 将 `FROM` 属性设置为 Ruby 基本映像。
   + 为函数代码创建目录和指向该目录的环境变量。在本示例中，目录为 `/var/task`，会镜像 Lambda 执行环境。不过，您可以为函数代码选择任何目录，因为 Dockerfile 不使用 AWS 基础映像。
   + 将 `ENTRYPOINT` 设置为您希望 Docker 容器在启动时运行的模块。在本例中，模块为运行时系统接口客户端。
   + 将 `CMD` 参数设置为 Lambda 函数处理程序。

   请注意，示例 Dockerfile 不包含 [USER 指令](https://docs.docker.com/reference/dockerfile/#user)。当您将容器映像部署到 Lambda 时，Lambda 会自动定义具有最低权限的默认 Linux 用户。这与标准 Docker 行为不同，标准 Docker 在未提供 `USER` 指令时默认为 `root` 用户。  
**Example Dockerfile**  

   ```
   FROM ruby:2.7
   
   # Install the runtime interface client for Ruby
   RUN gem install aws_lambda_ric
   
   # Add the runtime interface client to the PATH
   ENV PATH="/usr/local/bundle/bin:${PATH}"
   
   # Create a directory for the Lambda function
   ENV LAMBDA_TASK_ROOT=/var/task
   RUN mkdir -p ${LAMBDA_TASK_ROOT}
   WORKDIR ${LAMBDA_TASK_ROOT}
   
   # Copy Gemfile and Gemfile.lock
   COPY Gemfile Gemfile.lock ${LAMBDA_TASK_ROOT}/
   
   # Install Bundler and the specified gems
   RUN gem install bundler:2.4.20 && \
       bundle config set --local path 'vendor/bundle' && \
       bundle install
   
   # Copy function code
   COPY lambda_function.rb ${LAMBDA_TASK_ROOT}/    
   
   # Set runtime interface client as default command for the container runtime
   ENTRYPOINT [ "aws_lambda_ric" ]
   
   # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
   CMD [ "lambda_function.LambdaFunction::Handler.process" ]
   ```

1. 使用 [docker build](https://docs.docker.com/engine/reference/commandline/build/) 命令构建 Docker 映像。以下示例将映像命名为 `docker-image` 并为其提供 `test` [标签](https://docs.docker.com/engine/reference/commandline/build/#tag)。要使您的映像与 Lambda 兼容，您必须使用 `--provenance=false` 选项。

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**注意**  
该命令指定了 `--platform linux/amd64` 选项，可确保无论生成计算机的架构如何，容器始终与 Lambda 执行环境兼容。如果打算使用 ARM64 指令集架构创建 Lambda 函数，请务必将命令更改为使用 `--platform linux/arm64` 选项。

### （可选）在本地测试映像
<a name="ruby-alt-test"></a>

使用[运行时系统接口仿真器](https://github.com/aws/aws-lambda-runtime-interface-emulator/)在本地测试映像。您可以[将仿真器构建到映像中](https://github.com/aws/aws-lambda-runtime-interface-emulator/?tab=readme-ov-file#build-rie-into-your-base-image)，也可以使用以下程序将其安装在本地计算机上。

**在本地计算机上安装并运行运行时系统接口仿真器**

1. 从项目目录中，运行以下命令以从 GitHub 下载运行时系统接口仿真器（x86-64 架构）并将其安装在本地计算机上。

------
#### [ Linux/macOS ]

   ```
   mkdir -p ~/.aws-lambda-rie && \
       curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \
       chmod +x ~/.aws-lambda-rie/aws-lambda-rie
   ```

   要安装 arm64 仿真器，请将上一条命令中的 GitHub 存储库 URL 替换为以下内容：

   ```
   https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
   ```

------
#### [ PowerShell ]

   ```
   $dirPath = "$HOME\.aws-lambda-rie"
   if (-not (Test-Path $dirPath)) {
       New-Item -Path $dirPath -ItemType Directory
   }
         
   $downloadLink = "https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie"
   $destinationPath = "$HOME\.aws-lambda-rie\aws-lambda-rie"
   Invoke-WebRequest -Uri $downloadLink -OutFile $destinationPath
   ```

   要安装 arm64 模拟器，请将 `$downloadLink` 替换为以下内容：

   ```
   https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
   ```

------

1. 使用 **docker run** 命令启动 Docker 映像。请注意以下几点：
   + `docker-image` 是映像名称，`test` 是标签。
   + `aws_lambda_ric lambda_function.LambdaFunction::Handler.process` 是 `ENTRYPOINT`，后跟您 Dockerfile 中的 `CMD`。

------
#### [ Linux/macOS ]

   ```
   docker run --platform linux/amd64 -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
       --entrypoint /aws-lambda/aws-lambda-rie \
       docker-image:test \
           aws_lambda_ric lambda_function.LambdaFunction::Handler.process
   ```

------
#### [ PowerShell ]

   ```
   docker run --platform linux/amd64 -d -v "$HOME\.aws-lambda-rie:/aws-lambda" -p 9000:8080 `
   --entrypoint /aws-lambda/aws-lambda-rie `
   docker-image:test `
       aws_lambda_ric lambda_function.LambdaFunction::Handler.process
   ```

------

   此命令会将映像作为容器运行，并在 `localhost:9000/2015-03-31/functions/function/invocations` 创建本地端点。
**注意**  
如果为 ARM64 指令集架构创建 Docker 映像，请务必使用 `--platform linux/arm64` 选项，而不是 `--platform linux/amd64` 选项。

1. 将事件发布到本地端点。

------
#### [ Linux/macOS ]

   在 Linux 和 macOS 中，运行以下 `curl` 命令：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
   ```

   此命令使用空事件调用函数并返回响应。如果您使用自己的函数代码而不是示例函数代码，则可能需要使用 JSON 负载调用函数。示例：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   在 PowerShell 中，运行以下 `Invoke-WebRequest` 命令：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   此命令使用空事件调用函数并返回响应。如果您使用自己的函数代码而不是示例函数代码，则可能需要使用 JSON 负载调用函数。示例：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. 获取容器 ID。

   ```
   docker ps
   ```

1. 使用 [docker kill](https://docs.docker.com/engine/reference/commandline/kill/) 命令停止容器。在此命令中，将 `3766c4ab331c` 替换为上一步中的容器 ID。

   ```
   docker kill 3766c4ab331c
   ```

### 部署映像
<a name="ruby-alt-deploy"></a>

**将映像上传到 Amazon ECR 并创建 Lambda 函数**

1. 运行 [get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html) 命令，以针对 Amazon ECR 注册表进行 Docker CLI 身份验证。
   + 将 `--region` 值设置为要在其中创建 Amazon ECR 存储库的 AWS 区域。
   + 将 `111122223333` 替换为您的 AWS 账户 ID。

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. 使用 [create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html) 命令在 Amazon ECR 中创建存储库。

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**注意**  
Amazon ECR 存储库必须与 Lambda 函数位于同一 AWS 区域 内。

   如果成功，您将会看到如下响应：

   ```
   {
       "repository": {
           "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world",
           "registryId": "111122223333",
           "repositoryName": "hello-world",
           "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world",
           "createdAt": "2023-03-09T10:39:01+00:00",
           "imageTagMutability": "MUTABLE",
           "imageScanningConfiguration": {
               "scanOnPush": true
           },
           "encryptionConfiguration": {
               "encryptionType": "AES256"
           }
       }
   }
   ```

1. 从上一步的输出中复制 `repositoryUri`。

1. 运行 [docker tag](https://docs.docker.com/engine/reference/commandline/tag/) 命令，将本地映像作为最新版本标记到 Amazon ECR 存储库中。在此命令中：
   + `docker-image:test` 是 Docker 映像的名称和[标签](https://docs.docker.com/engine/reference/commandline/build/#tag)。这是您在 `docker build` 命令中指定的映像名称和标签。
   + 将 `<ECRrepositoryUri>` 替换为复制的 `repositoryUri`。确保 URI 末尾包含 `:latest`。

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   示例：

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 运行 [docker push](https://docs.docker.com/engine/reference/commandline/push/) 命令，以将本地映像部署到 Amazon ECR 存储库。确保存储库 URI 末尾包含 `:latest`。

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 如果您还没有函数的执行角色，请[创建执行角色](lambda-intro-execution-role.md#permissions-executionrole-api)。在下一步中，您需要提供角色的 Amazon 资源名称（ARN）。

1. 创建 Lambda 函数。对于 `ImageUri`，指定之前的存储库 URI。确保 URI 末尾包含 `:latest`。

   ```
   aws lambda create-function \
     --function-name hello-world \
     --package-type Image \
     --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
     --role arn:aws:iam::111122223333:role/lambda-ex
   ```
**注意**  
只要映像与 Lambda 函数位于同一区域内，您就可以使用其他 AWS 账户中的映像创建函数。有关更多信息，请参阅 [Amazon ECR 跨账户权限](images-create.md#configuration-images-xaccount-permissions)。

1. 调用函数。

   ```
   aws lambda invoke --function-name hello-world response.json
   ```

   应出现如下响应：

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. 要查看函数的输出，请检查 `response.json` 文件。

要更新函数代码，您必须再次构建映像，将新映像上传到 Amazon ECR 存储库，然后使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令将映像部署到 Lambda 函数。

Lambda 会将映像标签解析为特定的映像摘要。这意味着，如果您将用于部署函数的映像标签指向 Amazon ECR 中的新映像，则 Lambda 不会自动更新该函数以使用新映像。

要将新映像部署到相同的 Lambda 函数，即使 Amazon ECR 中的映像标签保持不变，也必须使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令。在以下示例中，`--publish` 选项使用更新的容器映像创建函数的新版本。

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```

# 使用 Ruby Lambda 函数的层
<a name="ruby-layers"></a>

使用 [Lambda 层](chapter-layers.md)来打包要在多个函数中重复使用的代码和依赖项。层通常包含库依赖项、[自定义运行时系统](runtimes-custom.md)或配置文件。创建层涉及三个常见步骤：

1. 打包层内容。此步骤需要创建 .zip 文件存档，其中包含要在函数中使用的依赖项。

1. 在 Lambda 中创建层。

1. 将层添加到函数。

**Topics**
+ [

## 打包层内容
](#ruby-layers-package)
+ [

## 在 Lambda 中创建层
](#publishing-layer)
+ [

## 在函数中使用层中的 Gem
](#ruby-layers-bundler-limitations)
+ [

## 将层添加到函数
](#ruby-layer-adding)
+ [

## 示例应用程序
](#ruby-layer-sample-app)

## 打包层内容
<a name="ruby-layers-package"></a>

要创建层，请将您的包捆绑到满足以下要求的 .zip 文件存档中：
+ 使用计划用于 Lambda 函数的相同 Ruby 版本来创建层。例如，如果为 Ruby 3.4 创建层，则函数应使用 Ruby 3.4 运行时。
+ 您层的 .zip 文件必须使用以下目录结构之一：
  + `ruby/gems/x.x.x`（其中 *x.x.x* 为 Ruby 版本，例如 `3.4.0`）
  + `ruby/lib`

  有关更多信息，请参阅 [每个 Lambda 运行时的层路径](packaging-layers.md#packaging-layers-paths)。
+ 您的层中的包必须与 Linux 兼容。Lambda 函数在 Amazon Linux 上运行。

您可以创建包含第三方 Ruby Gem 或自己的 Ruby 模块和类的层。许多主流的 Ruby Gem 包含必须针对 Lambda Linux 环境进行编译的本机扩展（C 代码）。

### 纯 Ruby Gem
<a name="ruby-layers-pure-ruby-gems"></a>

纯 Ruby Gem 仅包含 Ruby 代码，无需编译。这些 Gem 更易于打包和跨平台使用。

**使用纯 Ruby Gem 创建层**

1. 创建一个 `Gemfile`，指定要包含在层中的纯 Ruby Gem：  
**Example Gemfile**  

   ```
   source 'https://rubygems.org'
   
   gem 'tzinfo'
   ```

1. 使用捆绑程序将 Gem 安装到 `vendor/bundle` 目录：

   ```
   bundle config set --local path vendor/bundle
   bundle install
   ```

1. 将已安装的 Gem 复制到 Lambda 需要的目录结构 `ruby/gems/3.4.0`）：

   ```
   mkdir -p ruby/gems/3.4.0
   cp -r vendor/bundle/ruby/3.4.0*/* ruby/gems/3.4.0/
   ```

1. 压缩层内容：

------
#### [ Linux/macOS ]

   ```
   zip -r layer.zip ruby/
   ```

------
#### [ PowerShell ]

   ```
   Compress-Archive -Path .\ruby -DestinationPath .\layer.zip
   ```

------

   您的 .zip 文件的目录结构应如下所示：

   ```
   ruby/              
   └── gems/
       └── 3.4.0/
           ├── gems/
           │   ├── concurrent-ruby-1.3.5/
           │   └── tzinfo-2.0.6/
           ├── specifications/
           ├── cache/
           ├── build_info/
           └── (other bundler directories)
   ```
**注意**  
您必须在函数代码中单独引入各个 Gem。您不能使用 `bundler/setup`，也不能使用 `Bundler.require`。有关更多信息，请参阅 [在函数中使用层中的 Gem](#ruby-layers-bundler-limitations)。

### 带有本机扩展的 Gem
<a name="ruby-layers-native-extensions"></a>

许多主流的 Ruby Gem 包含必须针对目标平台进行编译的本机扩展（C 代码）。带本机扩展的主流 Gem 包括 [nokogiri](https://rubygems.org/gems/nokogiri/)、[pg](https://rubygems.org/gems/pg/)、[mysql2](https://rubygems.org/gems/mysql2/)、[sqlite3](https://rubygems.org/gems/sqlite3/) 和 [ffi](https://rubygems.org/gems/ffi/)。这些 Gem 必须在兼容 Lambda 运行时的 Linux 环境中构建。

**使用带本机扩展的 Gem 来创建层**

1. 创建 `Gemfile`。  
**Example Gemfile**  

   ```
   source 'https://rubygems.org'
   
   gem 'nokogiri'
   gem 'httparty'
   ```

1. 使用 Docker 在兼容 Lambda 的 Linux 环境中构建 Gem。在 Dockerfile 中指定一个[AWS基础映像](ruby-image.md#ruby-image-base)：  
**Example 适用于 Ruby 3.4 的 Dockerfile**  

   ```
   FROM public.ecr.aws/lambda/ruby:3.4
   
   # Copy Gemfile
   COPY Gemfile ./
   
   # Install system dependencies for native extensions
   RUN dnf update -y && \
       dnf install -y gcc gcc-c++ make
   
   # Configure bundler and install gems
   RUN bundle config set --local path vendor/bundle && \
       bundle install
   
   # Create the layer structure
   RUN mkdir -p ruby/gems/3.4.0 && \
       cp -r vendor/bundle/ruby/3.4.0*/* ruby/gems/3.4.0/
   
   # Create the layer zip file
   RUN zip -r layer.zip ruby/
   ```

1. 构建映像并提取层：

   ```
   docker build -t ruby-layer-builder .
   docker run --rm -v $(pwd):/output --entrypoint cp ruby-layer-builder layer.zip /output/
   ```

   这将在合适的 Linux 环境中构建 Gem，并将 `layer.zip` 文件复制到本地目录。您的 .zip 文件的目录结构应如下所示：

   ```
   ruby/
   └── gems/
       └── 3.4.0/
           ├── gems/
           │   ├── bigdecimal-3.2.2/
           │   ├── csv-3.3.5/
           │   ├── httparty-0.23.1/
           │   ├── mini_mime-1.1.5/
           │   ├── multi_xml-0.7.2/
           │   ├── nokogiri-1.18.8-x86_64-linux-gnu/
           │   └── racc-1.8.1/
           ├── build_info/
           ├── cache/
           ├── specifications/
           └── (other bundler directories)
   ```
**注意**  
您必须在函数代码中单独引入各个 Gem。您不能使用 `bundler/setup`，也不能使用 `Bundler.require`。有关更多信息，请参阅 [在函数中使用层中的 Gem](#ruby-layers-bundler-limitations)。

### 自定义 Ruby 模块
<a name="custom-ruby-modules"></a>

**使用您自己的代码创建层**

1. 为您的层创建所需的目录结构：

   ```
   mkdir -p ruby/lib
   ```

1. 在 `ruby/lib` 目录中创建您的 Ruby 模块。以下示例模块通过确认订单包含所需信息来验证订单。  
**Example ruby/lib/order\$1validator.rb**  

   ```
   require 'json'
   
   module OrderValidator
     class ValidationError < StandardError; end
   
     def self.validate_order(order_data)
       # Validates an order and returns formatted data
       required_fields = %w[product_id quantity]
       
       # Check required fields
       missing_fields = required_fields.reject { |field| order_data.key?(field) }
       unless missing_fields.empty?
         raise ValidationError, "Missing required fields: #{missing_fields.join(', ')}"
       end
       
       # Validate quantity
       quantity = order_data['quantity']
       unless quantity.is_a?(Integer) && quantity > 0
         raise ValidationError, 'Quantity must be a positive integer'
       end
       
       # Format and return the validated data
       {
         'product_id' => order_data['product_id'].to_s,
         'quantity' => quantity,
         'shipping_priority' => order_data.fetch('priority', 'standard')
       }
     end
   
     def self.format_response(status_code, body)
       # Formats the API response
       {
         statusCode: status_code,
         body: JSON.generate(body)
       }
     end
   end
   ```

1. 压缩层内容：

------
#### [ Linux/macOS ]

   ```
   zip -r layer.zip ruby/
   ```

------
#### [ PowerShell ]

   ```
   Compress-Archive -Path .\ruby -DestinationPath .\layer.zip
   ```

------

   您的 .zip 文件的目录结构应如下所示：

   ```
   ruby/              
   └── lib/
       └── order_validator.rb
   ```

1. 在您的函数中，需要并使用这些模块。您必须在函数代码中单独引入各个 Gem。您不能使用 `bundler/setup`，也不能使用 `Bundler.require`。有关更多信息，请参阅 [在函数中使用层中的 Gem](#ruby-layers-bundler-limitations)。示例：

   ```
   require 'json'
   require 'order_validator'
   
   def lambda_handler(event:, context:)
     begin
       # Parse the order data from the event body
       order_data = JSON.parse(event['body'] || '{}')
       
       # Validate and format the order
       validated_order = OrderValidator.validate_order(order_data)
       
       OrderValidator.format_response(200, {
         message: 'Order validated successfully',
         order: validated_order
       })
     rescue OrderValidator::ValidationError => e
       OrderValidator.format_response(400, {
         error: e.message
       })
     rescue => e
       OrderValidator.format_response(500, {
         error: 'Internal server error'
       })
     end
   end
   ```

   您可以使用以下[测试事件](testing-functions.md#invoke-with-event)调用函数：

   ```
   {
       "body": "{\"product_id\": \"ABC123\", \"quantity\": 2, \"priority\": \"express\"}"
   }
   ```

   预期的回应：

   ```
   {
     "statusCode": 200,
     "body": "{\"message\":\"Order validated successfully\",\"order\":{\"product_id\":\"ABC123\",\"quantity\":2,\"shipping_priority\":\"express\"}}"
   }
   ```

## 在 Lambda 中创建层
<a name="publishing-layer"></a>

您可以使用 AWS CLI 或 Lambda 控制台发布层。

------
#### [ AWS CLI ]

运行 [publish-layer-version](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/publish-layer-version.html) AWS CLI 命令以创建 Lambda 层：

```
aws lambda publish-layer-version --layer-name my-layer --zip-file fileb://layer.zip --compatible-runtimes ruby3.4
```

[兼容的运行时](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes)参数是可选的。指定后，Lambda 将使用此参数在 Lambda 控制台中筛选层。

------
#### [ Console ]

**创建层（控制台）**

1. 打开 Lambda 控制台的 [Layers page](https://console.aws.amazon.com/lambda/home#/layers)（层页面）。

1. 选择 **Create layer**（创建层）。

1. 选择**上传 .zip 文件**，然后上传您之前创建的 .zip 存档。

1. （可选）对于**兼容的运行时**，请选择与您用于构建层的 Ruby 版本相对应的 Ruby 运行时。

1. 选择**创建**。

------

## 在函数中使用层中的 Gem
<a name="ruby-layers-bundler-limitations"></a>

在函数代码中，必须显式引入要使用的各个 gem。不支持 `bundler/setup` 和 `Bundler.require` 等捆绑程序命令。下面介绍了如何在 Lambda 函数中正确使用层中的 Gem：

```
# Correct: Use explicit requires for each gem
require 'nokogiri'
require 'httparty'

def lambda_handler(event:, context:)
  # Use the gems directly
  doc = Nokogiri::HTML(event['html'])
  response = HTTParty.get(event['url'])
  # ... rest of your function
end

# Incorrect: These Bundler commands will not work
# require 'bundler/setup'
# Bundler.require
```

## 将层添加到函数
<a name="ruby-layer-adding"></a>

------
#### [ AWS CLI ]

要将层附加到函数，请运行 [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) AWS CLI 命令。对于 `--layers` 参数，使用层 ARN。ARN 必须指定版本（例如 `arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1`）。有关更多信息，请参阅 [层和层版本](chapter-layers.md#lambda-layer-versions)。

```
aws lambda update-function-configuration --function-name my-function --cli-binary-format raw-in-base64-out --layers "arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1"
```

如果使用 **cli-binary-format** 版本 2，则 AWS CLI 选项是必需的。要将其设为默认设置，请运行 `aws configure set cli-binary-format raw-in-base64-out`。有关更多信息，请参阅*版本 2 的 AWS Command Line Interface 用户指南*中的 [AWS CLI 支持的全局命令行选项](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。

------
#### [ Console ]

**向函数添加层**

1. 打开 Lamba 控制台的[函数页面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 选择函数。

1. 向下滚动到**层**部分，然后选择**添加层**。

1. 在**选择层**下，选择**自定义层**，然后选择您的层。
**注意**  
如果您在创建层时没有添加[兼容的运行时](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes)，则您的层将不会在此处列出。您可以改为指定层 ARN。

1. 选择**添加**。

------

## 示例应用程序
<a name="ruby-layer-sample-app"></a>

有关如何使用 Lambda 层的更多示例，请参阅 AWS Lambda Developer Guide GitHub 存储库中的 [layer-ruby](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/layer-ruby) 示例应用程序。此应用程序中有一个包含 [tzinfo](https://rubygems.org/gems/tzinfo) 库的层。创建层后，即可部署并调用相应的函数来确认层是否按预期运行。

# 使用 Lambda 上下文对象检索 Ruby 函数信息
<a name="ruby-context"></a>

当 Lambda 运行您的函数时，它会将上下文对象传递到[处理程序](ruby-handler.md)。此对象提供的方法和属性包含有关调用、函数和执行环境的信息。

**上下文方法**
+ `get_remaining_time_in_millis` – 返回执行超时前剩余的毫秒数。

**上下文属性**
+ `function_name` – Lambda 函数的名称。
+ `function_version` – 函数的[版本](configuration-versions.md)
+ `invoked_function_arn` – 用于调用函数的 Amazon Resource Name (ARN)。表明调用者是否指定了版本号或别名。
+ `memory_limit_in_mb` – 为函数分配的内存量。
+ `aws_request_id` – 调用请求的标识符。
+ `log_group_name` – 函数的日志组。
+ `log_stream_name` – 函数实例的日志流。
+ `deadline_ms` – 执行超时的日期（Unix 时间格式，以毫秒为单位）。
+ `identity` – （移动应用程序）授权请求的 Amazon Cognito 身份的相关信息。
+ `client_context` – （移动应用程序）客户端应用程序提供给 Lambda 的客户端上下文。

# Ruby Lambda 函数日志记录和监控
<a name="ruby-logging"></a>

AWS Lambda 将代表您自动监控 Lambda 函数并将日志记录发送至 Amazon CloudWatch。您的 Lambda 函数带有一个 CloudWatch Logs 日志组以及函数的每个实例的日志流。Lambda 运行时环境会将每个调用的详细信息发送到日志流，然后中继函数代码的日志和其他输出。有关更多信息，请参阅 [将 Lambda 函数日志发送到 CloudWatch Logs](monitoring-cloudwatchlogs.md)。

本页旨在介绍如何从 Lambda 函数的代码生成日志输出，并使用 AWS Command Line Interface、Lambda 控制台或 CloudWatch 控制台访问日志。

**Topics**
+ [

## 创建返回日志的函数
](#ruby-logging-output)
+ [

## 在 Lambda 控制台中查看日志
](#ruby-logging-console)
+ [

## 在 CloudWatch 控制台中查看日志
](#ruby-logging-cwconsole)
+ [

## 使用 AWS Command Line Interface（AWS CLI）查看日志
](#ruby-logging-cli)
+ [

## 删除日志
](#ruby-logging-delete)
+ [

## 使用 Ruby 日志记录库
](#ruby-logging-lib)

## 创建返回日志的函数
<a name="ruby-logging-output"></a>

要从函数代码输出日志，您可以使用 `puts` 语句或使用写入到 `stdout` 或 `stderr` 的任何日志记录库。以下示例记录环境变量和事件对象的值。

**Example lambda\$1function.rb**  

```
# lambda_function.rb

def handler(event:, context:)
    puts "## ENVIRONMENT VARIABLES"
    puts ENV.to_a
    puts "## EVENT"
    puts event.to_a
end
```

**Example 日志格式**  

```
START RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95 Version: $LATEST
## ENVIRONMENT VARIABLES
environ({'AWS_LAMBDA_LOG_GROUP_NAME': '/aws/lambda/my-function', 'AWS_LAMBDA_LOG_STREAM_NAME': '2020/01/31/[$LATEST]3893xmpl7fac4485b47bb75b671a283c', 'AWS_LAMBDA_FUNCTION_NAME': 'my-function', ...})
## EVENT
{'key': 'value'}
END RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95
REPORT RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95  Duration: 15.74 ms  Billed Duration: 147 ms Memory Size: 128 MB Max Memory Used: 56 MB  Init Duration: 130.49 ms
XRAY TraceId: 1-5e34a614-10bdxmplf1fb44f07bc535a1   SegmentId: 07f5xmpl2d1f6f85 Sampled: true
```

Ruby 运行时记录每次调用的 `START`、`END` 和 `REPORT` 行。报告行提供了以下详细信息：

**REPORT 行数据字段**
+ **RequestId** – 调用的唯一请求 ID。
+ **Duration**（持续时间）– 函数的处理程序方法处理事件所花费的时间。
+ **Billed Duration**（计费持续时间）– 针对调用计费的时间量。
+ **Memory Size**（内存大小）– 分配给函数的内存量。
+ **Max Memory Used**（最大内存使用量）– 函数使用的内存量。如果调用共享执行环境，Lambda 会报告所有调用使用的最大内存。此行为可能会导致报告值高于预期。
+ **Init Duration**（初始持续时间）– 对于提供的第一个请求，为运行时在处理程序方法外部加载函数和运行代码所花费的时间。
+ **XRAY TraceId** – 对于追踪的请求，为 [AWS X-Ray 追踪 ID](services-xray.md)。
+ **SegmentId** – 对于追踪的请求，为 X-Ray 分段 ID。
+ **Sampled**（采样）– 对于追踪的请求，为采样结果。

如需更详细的日志，请使用 [使用 Ruby 日志记录库](#ruby-logging-lib)。

## 在 Lambda 控制台中查看日志
<a name="ruby-logging-console"></a>

调用 Lambda 函数后，您可以使用 Lambda 控制台查看日志输出。

如果可以在嵌入式**代码**编辑器中测试代码，则可以在**执行结果**中找到日志。使用控制台测试功能调用函数时，可以在**详细信息**部分找到**日志输出**。

## 在 CloudWatch 控制台中查看日志
<a name="ruby-logging-cwconsole"></a>

您可以使用 Amazon CloudWatch 控制台查看所有 Lambda 函数调用的日志。

**使用 CloudWatch 控制台查看日志**

1. 打开 CloudWatch 控制台的 [Log groups](https://console.aws.amazon.com/cloudwatch/home?#logs:)（日志组页面）。

1. 选择您的函数 (**/aws/lambda/*your-function-name***) 的日志组。

1. 创建日志流。

每个日志流对应一个[函数实例](lambda-runtime-environment.md)。日志流会在您更新 Lambda 函数以及创建更多实例来处理并发调用时显示。要查找特定调用的日志，建议您使用 AWS X-Ray 检测函数。X-Ray 会在追踪中记录有关请求和日志流的详细信息。

## 使用 AWS Command Line Interface（AWS CLI）查看日志
<a name="ruby-logging-cli"></a>

AWS CLI 是一种开源工具，让您能够在命令行 Shell 中使用命令与 AWS 服务进行交互。要完成本节中的步骤，您必须拥有 [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

您可以通过 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)，使用 `--log-type` 命令选项检索调用的日志。响应包含一个 `LogResult` 字段，其中包含多达 4KB 来自调用的 base64 编码日志。

**Example 检索日志 ID**  
以下示例说明如何从 `LogResult` 字段中检索名为 `my-function` 的函数的*日志 ID*。  

```
aws lambda invoke --function-name my-function out --log-type Tail
```
您应看到以下输出：  

```
{
    "StatusCode": 200,
    "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...",
    "ExecutedVersion": "$LATEST"
}
```

**Example 解码日志**  
在同一命令提示符下，使用 `base64` 实用程序解码日志。以下示例说明如何为 `my-function` 检索 base64 编码的日志。  

```
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
```
如果使用 **cli-binary-format** 版本 2，则 AWS CLI 选项是必需的。要将其设为默认设置，请运行 `aws configure set cli-binary-format raw-in-base64-out`。有关更多信息，请参阅*版本 2 的 AWS Command Line Interface 用户指南*中的 [AWS CLI 支持的全局命令行选项](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。  
您应看到以下输出：  

```
START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST
"AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib",
END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8
REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8  Duration: 79.67 ms      Billed Duration: 80 ms         Memory Size: 128 MB     Max Memory Used: 73 MB
```
`base64` 实用程序在 Linux、macOS 和 [Ubuntu on Windows](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 上可用。macOS 用户可能需要使用 `base64 -D`。

**Example get-logs.sh 脚本**  
在同一命令提示符下，使用以下脚本下载最后五个日志事件。此脚本使用 `sed` 从输出文件中删除引号，并休眠 15 秒以等待日志可用。输出包括来自 Lambda 的响应，以及来自 `get-log-events` 命令的输出。  
复制以下代码示例的内容并将其作为 `get-logs.sh` 保存在 Lambda 项目目录中。  
如果使用 **cli-binary-format** 版本 2，则 AWS CLI 选项是必需的。要将其设为默认设置，请运行 `aws configure set cli-binary-format raw-in-base64-out`。有关更多信息，请参阅*版本 2 的 AWS Command Line Interface 用户指南*中的 [AWS CLI 支持的全局命令行选项](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。  

```
#!/bin/bash
aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"key": "value"}' out
sed -i'' -e 's/"//g' out
sleep 15
aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name stream1 --limit 5
```

**Example macOS 和 Linux（仅限）**  
在同一命令提示符下，macOS 和 Linux 用户可能需要运行以下命令以确保脚本可执行。  

```
chmod -R 755 get-logs.sh
```

**Example 检索最后五个日志事件**  
在同一命令提示符下，运行以下脚本以获取最后五个日志事件。  

```
./get-logs.sh
```
您应看到以下输出：  

```
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
{
    "events": [
        {
            "timestamp": 1559763003171,
            "message": "START RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf Version: $LATEST\n",
            "ingestionTime": 1559763003309
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tENVIRONMENT VARIABLES\r{\r  \"AWS_LAMBDA_FUNCTION_VERSION\": \"$LATEST\",\r ...",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tEVENT\r{\r  \"key\": \"value\"\r}\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "END RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "REPORT RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\tDuration: 26.73 ms\tBilled Duration: 27 ms \tMemory Size: 128 MB\tMax Memory Used: 75 MB\t\n",
            "ingestionTime": 1559763018353
        }
    ],
    "nextForwardToken": "f/34783877304859518393868359594929986069206639495374241795",
    "nextBackwardToken": "b/34783877303811383369537420289090800615709599058929582080"
}
```

## 删除日志
<a name="ruby-logging-delete"></a>

删除函数时，日志组不会自动删除。要避免无限期存储日志，请删除日志组，或[配置一个保留期](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#SettingLogRetention)，在该保留期之后，日志将自动删除。

## 使用 Ruby 日志记录库
<a name="ruby-logging-lib"></a>

Ruby [日志记录库](https://ruby-doc.org/stdlib-2.7.0/libdoc/logger/rdoc/index.html)可返回易于读取的简化日志。使用日志记录实用程序输出与函数相关的详细信息、消息和错误代码。

```
# lambda_function.rb

require 'logger'

def handler(event:, context:) 
  logger = Logger.new($stdout)
  logger.info('## ENVIRONMENT VARIABLES')
  logger.info(ENV.to_a)
  logger.info('## EVENT')
  logger.info(event)
  event.to_a
end
```

`logger` 的输出包括日志级别、时间戳和请求 ID。

```
START RequestId: 1c8df7d3-xmpl-46da-9778-518e6eca8125 Version: $LATEST
[INFO]  2020-01-31T22:12:58.534Z    1c8df7d3-xmpl-46da-9778-518e6eca8125    ## ENVIRONMENT VARIABLES

[INFO]  2020-01-31T22:12:58.534Z    1c8df7d3-xmpl-46da-9778-518e6eca8125    environ({'AWS_LAMBDA_LOG_GROUP_NAME': '/aws/lambda/my-function', 'AWS_LAMBDA_LOG_STREAM_NAME': '2020/01/31/[$LATEST]1bbe51xmplb34a2788dbaa7433b0aa4d', 'AWS_LAMBDA_FUNCTION_NAME': 'my-function', ...})

[INFO]  2020-01-31T22:12:58.535Z    1c8df7d3-xmpl-46da-9778-518e6eca8125    ## EVENT

[INFO]  2020-01-31T22:12:58.535Z    1c8df7d3-xmpl-46da-9778-518e6eca8125    {'key': 'value'}

END RequestId: 1c8df7d3-xmpl-46da-9778-518e6eca8125
REPORT RequestId: 1c8df7d3-xmpl-46da-9778-518e6eca8125  Duration: 2.75 ms   Billed Duration: 117 ms Memory Size: 128 MB Max Memory Used: 56 MB  Init Duration: 113.51 ms
XRAY TraceId: 1-5e34a66a-474xmpl7c2534a87870b4370   SegmentId: 073cxmpl3e442861 Sampled: true
```

# 在 AWS Lambda 中检测 Ruby 代码
<a name="ruby-tracing"></a>

Lambda 与 AWS X-Ray 集成使您能够跟踪、调试和优化 Lambda 应用程序。在请求遍历应用程序中的资源（从前端 API 到后端的存储和数据库）时，您可以使用 X-Ray 跟踪请求。只需将 X-Ray 开发工具包库添加到构建配置中，就可以记录您的函数对AWS服务进行的任何调用的错误和延迟。

在配置活跃跟踪后，您可以通过应用程序观察特定请求。[X-Ray 服务图](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html#xray-concepts-servicegraph)将显示有关应用程序及其所有组件的信息。以下示例显示了具有两个函数的应用程序。主函数处理事件，有时会返回错误。位于顶部的第二个函数将处理第一个函数的日志组中显示的错误，并使用 AWS SDK 调用 X-Ray、Amazon Simple Storage Service (Amazon S3) 和 Amazon CloudWatch Logs。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/sample-errorprocessor-servicemap.png)


要使用控制台切换 Lambda 函数的活动跟踪，请按照以下步骤操作：

**打开活跃跟踪**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数。

1. 选择 **Configuration**（配置），然后选择 **Monitoring and operations tools**（监控和操作工具）。

1. 在**其他监控工具**下，选择**编辑**。

1. 在 **CloudWatch 应用程序信号和 AWS X-Ray** 下，为 **Lambda 服务跟踪**选择**启用**。

1. 选择**保存**。

**定价**  
作为 AWS 免费套餐的组成部分，您可以每月免费使用 X-Ray 跟踪，但不能超过一定限制。超出该阈值后，X-Ray 会对跟踪存储和检索进行收费。有关更多信息，请参阅 [AWS X-Ray 定价](https://aws.amazon.com/xray/pricing/)。

您的函数需要权限才能将跟踪数据上载到 X-Ray。在 Lambda 控制台中激活跟踪后，Lambda 会将所需权限添加到函数的[执行角色](lambda-intro-execution-role.md)。如果没有，请将 [AWSXRayDaemonWriteAccess](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess) 策略添加到执行角色。

X-Ray 无法跟踪对应用程序的所有请求。X-Ray 将应用采样算法确保跟踪有效，同时仍会提供所有请求的一个代表性样本。采样率是每秒 1 个请求和 5% 的其他请求。您无法为函数配置此 X-Ray 采样率。

在 X-Ray 中，*跟踪*记录有关由一个或多个*服务*处理的请求的信息。Lambda 会每个跟踪记录 2 个分段，这些分段将在服务图上创建两个节点。下图突出显示了这两个节点：

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/xray-servicemap-function.png)


位于左侧的第一个节点表示接收调用请求的 Lambda 服务。第二个节点表示特定的 Lambda 函数。以下示例显示了一个包含这 2 个分段的跟踪。两者都命名为 **my-function**，但其中一个函数具有 `AWS::Lambda` 源，另一个则具有 `AWS::Lambda::Function` 源。如果 `AWS::Lambda` 分段显示错误，则表示 Lambda 服务存在问题。如果 `AWS::Lambda::Function` 分段显示错误，则说明函数存在问题。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/V2_sandbox_images/my-function-2-v1.png)


此示例将展开 `AWS::Lambda::Function` 分段，以显示其三个子分段。

**注意**  
AWS 目前正在实施对 Lambda 服务的更改。由于这些更改，您可能会看到 AWS 账户 中不同 Lambda 函数发出的系统日志消息和跟踪分段的结构和内容之间存在细微差异。  
此处显示的示例跟踪说明了旧样式函数分段。以下段落介绍了新旧样式分段之间的差异。  
这些更改将在未来几周内实施，除中国和 GovCloud 区域外，所有 AWS 区域 的函数都将过渡到使用新格式的日志消息和跟踪分段。

旧样式函数分段包含以下子分段：
+ **初始化** – 表示加载函数和运行[初始化代码](foundation-progmodel.md)所花费的时间。此子分段仅对由您的函数的每个实例处理的第一个事件显示。
+ **调用** – 表示执行处理程序代码花费的时间。
+ **开销** – 表示 Lambda 运行时为准备处理下一个事件而花费的时间。

新样式函数分段不包含 `Invocation` 子分段。而是将客户子分段直接附加到函数分段。有关新旧样式函数分段结构的更多信息，请参阅 [了解 X-Ray 跟踪](services-xray.md#services-xray-traces)。

您可以使用处理程序代码来记录元数据并跟踪下游调用。要记录有关您的处理程序对其他资源和服务进行调用的详细信息，请使用 X-Ray SDK for Ruby。要获取开发工具包，请将 `aws-xray-sdk` 包添加到应用程序的依赖项中。

**Example [blank-ruby/function/Gemfile](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-ruby/function/Gemfile)**  

```
# Gemfile
source 'https://rubygems.org'

gem 'aws-xray-sdk', '0.11.4'
gem 'aws-sdk-lambda', '1.39.0'
gem 'test-unit', '3.3.5'
```

要检测 AWS 开发工具包客户端，需要在初始化代码中创建客户端后运行 `aws-xray-sdk/lambda` 模块。

**Example [blank-ruby/function/lambda\$1function.rb](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-ruby/function/lambda_function.rb) – 跟踪AWS开发工具包客户端**  

```
# lambda_function.rb
require 'logger'
require 'json'
require 'aws-sdk-lambda'
$client = Aws::Lambda::Client.new()
$client.get_account_settings()

require 'aws-xray-sdk/lambda'

def lambda_handler(event:, context:)
  logger = Logger.new($stdout)
  ...
```

在 X-Ray 中，*跟踪*记录有关由一个或多个*服务*处理的请求的信息。Lambda 会每个跟踪记录 2 个分段，这些分段将在服务图上创建两个节点。下图突出显示了这两个节点：

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/xray-servicemap-function.png)


位于左侧的第一个节点表示接收调用请求的 Lambda 服务。第二个节点表示特定的 Lambda 函数。以下示例显示了一个包含这 2 个分段的跟踪。两者都命名为 **my-function**，但其中一个函数具有 `AWS::Lambda` 源，另一个则具有 `AWS::Lambda::Function` 源。如果 `AWS::Lambda` 分段显示错误，则表示 Lambda 服务存在问题。如果 `AWS::Lambda::Function` 分段显示错误，则说明函数存在问题。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/V2_sandbox_images/my-function-2-v1.png)


此示例将展开 `AWS::Lambda::Function` 分段，以显示其三个子分段。

**注意**  
AWS 目前正在实施对 Lambda 服务的更改。由于这些更改，您可能会看到 AWS 账户 中不同 Lambda 函数发出的系统日志消息和跟踪分段的结构和内容之间存在细微差异。  
此处显示的示例跟踪说明了旧样式函数分段。以下段落介绍了新旧样式分段之间的差异。  
这些更改将在未来几周内实施，除中国和 GovCloud 区域外，所有 AWS 区域 的函数都将过渡到使用新格式的日志消息和跟踪分段。

旧样式函数分段包含以下子分段：
+ **初始化** – 表示加载函数和运行[初始化代码](foundation-progmodel.md)所花费的时间。此子分段仅对由您的函数的每个实例处理的第一个事件显示。
+ **调用** – 表示执行处理程序代码花费的时间。
+ **开销** – 表示 Lambda 运行时为准备处理下一个事件而花费的时间。

新样式函数分段不包含 `Invocation` 子分段。而是将客户子分段直接附加到函数分段。有关新旧样式函数分段结构的更多信息，请参阅 [了解 X-Ray 跟踪](services-xray.md#services-xray-traces)。

您还可以分析 HTTP 客户端、记录 SQL 查询以及使用注释和元数据创建自定义子段。有关更多信息，请参阅 AWS X-Ray 开发人员指南中的 [X-Ray SDK for Ruby](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-ruby.html)。

**Topics**
+ [

## 使用 Lambda API 启用活动跟踪
](#ruby-tracing-api)
+ [

## 使用 CloudFormation 启用主动跟踪
](#ruby-tracing-cloudformation)
+ [

## 在层中存储运行时依赖项
](#ruby-tracing-layers)

## 使用 Lambda API 启用活动跟踪
<a name="ruby-tracing-api"></a>

要使用 AWS CLI 或 AWS 开发工具包管理跟踪配置，请使用以下 API 操作：
+ [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)
+ [GetFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html)
+ [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html)

以下示例 AWS CLI 命令对名为 **my-function** 的函数启用活跃跟踪。

```
aws lambda update-function-configuration --function-name my-function \
--tracing-config Mode=Active
```

跟踪模式是发布函数版本时版本特定配置的一部分。您无法更改已发布版本上的跟踪模式。

## 使用 CloudFormation 启用主动跟踪
<a name="ruby-tracing-cloudformation"></a>

要对 CloudFormation 模板中的 `AWS::Lambda::Function` 资源激活跟踪，请使用 `TracingConfig` 属性。

**Example [function-inline.yml](https://github.com/awsdocs/aws-lambda-developer-guide/blob/master/templates/function-inline.yml) – 跟踪配置**  

```
Resources:
  function:
    Type: [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)
    Properties:
      TracingConfig:
        Mode: Active
      ...
```

对于 AWS Serverless Application Model (AWS SAM) `AWS::Serverless::Function` 资源，请使用 `Tracing` 属性。

**Example [template.yml](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-nodejs/template.yml) – 跟踪配置**  

```
Resources:
  function:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      Tracing: Active
      ...
```

## 在层中存储运行时依赖项
<a name="ruby-tracing-layers"></a>

如果您使用 X-Ray 开发工具包来分析AWS开发工具包客户端和您的函数代码，则您的部署程序包可能会变得相当大。为了避免每次更新函数代码时上载运行时依赖项，请将 X-Ray SDK 打包到 [Lambda 层](chapter-layers.md)中。

以下示例显示存储 X-Ray SDK for Ruby 的 `AWS::Serverless::LayerVersion` 资源。

**Example [template.yml](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-ruby/template.yml) – 依赖项层**  

```
Resources:
  function:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      CodeUri: function/.
      Tracing: Active
      Layers:
        - !Ref libs
      ...
  libs:
    Type: [AWS::Serverless::LayerVersion](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-layerversion.html)
    Properties:
      LayerName: blank-ruby-lib
      Description: Dependencies for the blank-ruby sample app.
      ContentUri: lib/.
      CompatibleRuntimes:
        - ruby2.5
```

使用此配置，仅在更改运行时依赖项时您才会更新库层。由于函数部署软件包仅包含您的代码，因此可以帮助缩短上传时间。

为依赖项创建层需要更改构建才能在部署之前生成层存档。有关工作示例，请参阅 [blank-ruby](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-ruby) 示例应用程序。