

# 定义采用 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/)。