Springboot lambda on localstack with terraform, docker: 错误加载类 StreamLambdaHandler: Metaspace "," err



我使用spring boot创建了一个rest api lambda。当我从中创建一个jar文件并使用terraform将其部署到localstack时,我可以调用api,它按预期工作。

但是,当我从代码中创建docker映像并采用terraform来使用该image_uri时,当我调用api时,我得到以下错误:

Lambda runtime initialization error for function arn:aws:lambda:eu-west-2:000000000000:function:restapi: b'{"errorMessage":"Error loading class com.example.lambda.StreamLambdaHandler: Metaspace","errorType":"java.lang.OutOfMemoryError"}'

这是地形:

variable "STAGE" {
type    = string
default = "local"
}
variable "AWS_REGION" {
type    = string
default = "eu-west-2"
}
variable "IMG_URI" {
type    = string
default = "localhost:4510/com.example-restapi-lambda:1.0.0"
}
variable "FUNCTION_NAME" {
type    = string
default = "restapi"
}

variable "FUNCTION_HANDLER" {
type    = string
default = "com.example.lambda.StreamLambdaHandler"
}

provider "aws" {
access_key                  = "test_access_key"
secret_key                  = "test_secret_key"
region                      = var.AWS_REGION
s3_force_path_style         = true
skip_credentials_validation = true
skip_metadata_api_check     = true
skip_requesting_account_id  = true
endpoints {
apigateway       = var.STAGE == "local" ? "http://localhost:4566" : null
cloudformation   = var.STAGE == "local" ? "http://localhost:4566" : null
cloudwatch       = var.STAGE == "local" ? "http://localhost:4566" : null
cloudwatchevents = var.STAGE == "local" ? "http://localhost:4566" : null
iam              = var.STAGE == "local" ? "http://localhost:4566" : null
lambda           = var.STAGE == "local" ? "http://localhost:4566" : null
s3               = var.STAGE == "local" ? "http://localhost:4566" : null
}
}
resource "aws_iam_role" "lambda-execution-role" {
name = "lambda-execution-role-${var.FUNCTION_NAME}"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_lambda_function" "restApiLambdaFunction" {
image_uri     = var.IMG_URI
function_name = var.FUNCTION_NAME
role          = aws_iam_role.lambda-execution-role.arn
handler       = var.FUNCTION_HANDLER
# handler = "org.springframework.cloud.function.adapter.aws.FunctionInvoker"
runtime = "java11"
timeout = 60
environment {
variables = {
MAIN_CLASS    = "com.example.lambda.AWSLambdaApp"
# JAVA_OPTS = "-Xmx5g"
}
}
}
resource "aws_api_gateway_rest_api" "rest-api" {
name = "RestApi-${var.FUNCTION_NAME}"
}
resource "aws_api_gateway_resource" "proxy" {
rest_api_id = aws_api_gateway_rest_api.rest-api.id
parent_id   = aws_api_gateway_rest_api.rest-api.root_resource_id
path_part   = "{proxy+}"
}
resource "aws_api_gateway_method" "proxy" {
rest_api_id   = aws_api_gateway_rest_api.rest-api.id
resource_id   = aws_api_gateway_resource.proxy.id
http_method   = "ANY"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "proxy" {
rest_api_id = aws_api_gateway_rest_api.rest-api.id
resource_id = aws_api_gateway_method.proxy.resource_id
http_method = aws_api_gateway_method.proxy.http_method
integration_http_method = "POST"
type                    = "AWS_PROXY"
uri                     = aws_lambda_function.restApiLambdaFunction.invoke_arn
}
resource "aws_api_gateway_deployment" "rest-api-deployment" {
depends_on  = [aws_api_gateway_integration.proxy]
rest_api_id = aws_api_gateway_rest_api.rest-api.id
stage_name  = var.STAGE
}
resource "aws_cloudwatch_event_rule" "warmup" {
name                = "warmup-event-rule-${var.FUNCTION_NAME}"
schedule_expression = "rate(10 minutes)"
}
resource "aws_cloudwatch_event_target" "warmup" {
target_id = "warmup"
rule      = aws_cloudwatch_event_rule.warmup.name
arn       = aws_lambda_function.restApiLambdaFunction.arn
input     = "{"httpMethod": "SCHEDULE", "path": "warmup"}"
}
resource "aws_lambda_permission" "warmup-permission" {
statement_id  = "AllowExecutionFromCloudWatch"
action        = "lambda:InvokeFunction"
function_name = aws_lambda_function.restApiLambdaFunction.function_name
principal     = "events.amazonaws.com"
source_arn    = aws_cloudwatch_event_rule.warmup.arn
}

我所看到的最接近的解决方案是将JAVA_OPTS传递给docker映像,增加可用内存,但不确定如何通过terraform做到这一点。虽然我不确定这是否能解决问题。如有任何指导,将不胜感激。

根据我的评论,在aws_lambda_function资源中有一个memory_size选项[1]。如果没有定义,它将默认为128MB。它可能需要增加,以避免OOM错误。


[1] https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function memory_size

最新更新