針對 Ruby Lambda 函數使用層
使用 Lambda 層封裝要在多個函式之間重複使用的程式碼與相依項。層通常具備程式庫相依性、自訂執行期或組態檔案。建立層包含三個一般步驟:
-
封裝層內容。這表示建立 .zip 封存檔,其中包含您要在函數中使用的相依項。
-
在 Lambda 中建立層。
-
將層新增至函數中。
封裝層內容
若要建立層,請將套件封裝成符合以下要求的 .zip 壓縮檔:
-
使用計劃用於 Lambda 函式的相同 Ruby 版本來建立層。例如,若針對 Ruby 3.4 建立層,需為函式使用 Ruby 3.4 執行時期。
-
層的 .zip 檔案必須使用下列任一目錄結構:
-
ruby/gems/(其中x.x.xx.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 中指定 AWS 基礎映像:
範例 適用於 Ruby 3.4 的 Dockerfile
FROMpublic.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 中建立層
您可以使用 AWS 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 層的更多範例,請參閱 AWS Lambda Developer Guide GitHub repository 中的 layer-ruby