使用 Ruby Lambda 函数的层 - Amazon Lambda
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

使用 Ruby Lambda 函数的层

使用 Lambda 层来打包要在多个函数中重复使用的代码和依赖项。层通常包含库依赖项、自定义运行时系统或配置文件。创建层涉及三个常见步骤:

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

  2. 在 Lambda 中创建层。

  3. 将层添加到函数。

打包层内容

要创建层,请将您的包捆绑到满足以下要求的 .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 运行时的层路径

  • 您的层中的包必须与 Linux 兼容。Lambda 函数在 Amazon Linux 上运行。

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

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

使用纯 Ruby Gem 创建层
  1. 创建一个 Gemfile,指定要包含在层中的纯 Ruby Gem:

    例 Gemfile
    source 'https://rubygems.org' gem 'tzinfo'
  2. 使用捆绑程序将 Gem 安装到 vendor/bundle 目录:

    bundle config set --local path vendor/bundle bundle install
  3. 将已安装的 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/
  4. 压缩层内容:

    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 Gem 包含必须针对目标平台进行编译的本机扩展(C 代码)。带本机扩展的主流 Gem 包括 nokogiripgmysql2sqlite3ffi。这些 Gem 必须在兼容 Lambda 运行时的 Linux 环境中构建。

使用带本机扩展的 Gem 来创建层
  1. 创建 Gemfile

    例 Gemfile
    source 'https://rubygems.org' gem 'nokogiri' gem 'httparty'
  2. 使用 Docker 在兼容 Lambda 的 Linux 环境中构建 Gem。在 Dockerfile 中指定一个Amazon基础映像

    例 适用于 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/
  3. 构建映像并提取层:

    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

使用您自己的代码创建层
  1. 为您的层创建所需的目录结构:

    mkdir -p ruby/lib
  2. ruby/lib 目录中创建您的 Ruby 模块。以下示例模块通过确认订单包含所需信息来验证订单。

    例 ruby/lib/order_validator.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
  3. 压缩层内容:

    Linux/macOS
    zip -r layer.zip ruby/
    PowerShell
    Compress-Archive -Path .\ruby -DestinationPath .\layer.zip

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

    ruby/              
    └── lib/
        └── order_validator.rb
  4. 在您的函数中,需要并使用这些模块。您必须在函数代码中单独引入各个 Gem。您不能使用 bundler/setup,也不能使用 Bundler.require。有关更多信息,请参阅 在函数中使用层中的 Gem。示例:

    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

    您可以使用以下测试事件调用函数:

    { "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 中创建层

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

Amazon CLI

运行 publish-layer-version Amazon CLI 命令以创建 Lambda 层:

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

兼容的运行时参数是可选的。指定后,Lambda 将使用此参数在 Lambda 控制台中筛选层。

Console
创建层(控制台)
  1. 打开 Lambda 控制台的 Layers page(层页面)。

  2. 选择 Create layer(创建层)。

  3. 选择上传 .zip 文件,然后上传您之前创建的 .zip 存档。

  4. (可选)对于兼容的运行时,请选择与您用于构建层的 Ruby 版本相对应的 Ruby 运行时。

  5. 选择创建

在函数中使用层中的 Gem

在函数代码中,必须显式引入要使用的各个 gem。不支持 bundler/setupBundler.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

将层添加到函数

Amazon CLI

要将层附加到函数,请运行 update-function-configuration Amazon CLI 命令。对于 --layers 参数,使用层 ARN。ARN 必须指定版本(例如 arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1)。有关更多信息,请参阅 层和层版本

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,则 Amazon CLI 选项是必需的。要将其设为默认设置,请运行 aws configure set cli-binary-format raw-in-base64-out。有关更多信息,请参阅版本 2 的 Amazon Command Line Interface 用户指南中的 Amazon CLI 支持的全局命令行选项

Console
向函数添加层
  1. 打开 Lamba 控制台的函数页面

  2. 选择函数。

  3. 向下滚动到部分,然后选择添加层

  4. 选择层下,选择自定义层,然后选择您的层。

    注意

    如果您在创建层时没有添加兼容的运行时,则您的层将不会在此处列出。您可以改为指定层 ARN。

  5. 选择添加

示例应用程序

有关如何使用 Lambda 层的更多示例,请参阅 Amazon Lambda Developer Guide GitHub 存储库中的 layer-ruby 示例应用程序。此应用程序中有一个包含 tzinfo 库的层。创建层后,即可部署并调用相应的函数来确认层是否按预期运行。