使用 Ruby Lambda 函数的层
使用 Lambda 层来打包要在多个函数中重复使用的代码和依赖项。层通常包含库依赖项、自定义运行时系统或配置文件。创建层涉及三个常见步骤:
-
打包层内容。此步骤需要创建 .zip 文件存档,其中包含要在函数中使用的依赖项。
-
在 Lambda 中创建层。
-
将层添加到函数。
打包层内容
要创建层,请将您的包捆绑到满足以下要求的 .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 创建层
-
创建一个
Gemfile
,指定要包含在层中的纯 Ruby Gem:例 Gemfile
source 'https://rubygems.org' gem 'tzinfo'
-
使用捆绑程序将 Gem 安装到
vendor/bundle
目录:bundle config set --local path vendor/bundle bundle install
-
将已安装的 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/
-
压缩层内容:
您的 .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 包括 nokogiri
使用带本机扩展的 Gem 来创建层
-
创建
Gemfile
。例 Gemfile
source 'https://rubygems.org' gem 'nokogiri' gem 'httparty'
-
使用 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/ -
构建映像并提取层:
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。
使用您自己的代码创建层
-
为您的层创建所需的目录结构:
mkdir -p ruby/lib
-
在
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
-
压缩层内容:
您的 .zip 文件的目录结构应如下所示:
ruby/ └── lib/ └── order_validator.rb
-
在您的函数中,需要并使用这些模块。您必须在函数代码中单独引入各个 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 控制台发布层。
在函数中使用层中的 Gem
在函数代码中,必须显式引入要使用的各个 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
将层添加到函数
示例应用程序
有关如何使用 Lambda 层的更多示例,请参阅 Amazon Lambda Developer Guide GitHub 存储库中的 layer-ruby