英文:
Spring boot deployed in Lambda throws "statusCode": 502 Gateway timeout"
问题
我将为您提供已翻译的部分:
错误:(由于超时错误,我在Lambda测试中将超时时间增加到了15分钟,以下是结果,似乎仍然无法正常工作)
执行函数:成功(日志)
{
"statusCode": 502,
"multiValueHeaders": {
"Content-Type": [
"application/json"
]
},
"body": "{\"message\":\"网关超时\"}",
"isBase64Encoded": false
}
Spring Boot Request Stream Handler for Lambda:(异步,因为我觉得Lambda在初始启动时需要更多时间)
public class StreamLambdaHandler implements RequestStreamHandler {
private SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
public StreamLambdaHandler() throws ContainerInitializationException {
handler = new SpringBootProxyHandlerBuilder()
.defaultProxy()
.asyncInit()
.springBootApplication(SlowApplication.class)
.buildAndInitialize();
}
@Override
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
throws IOException {
handler.proxyStream(inputStream, outputStream, context);
}
}
build.gradle:(我在这里添加了“task buildZip”以将构建的“distributions” jar文件打包成zip文件)
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'mysql:mysql-connector-java:8.0.32'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
implementation 'com.amazonaws:aws-lambda-java-events:3.11.1'
implementation 'com.amazonaws.serverless:aws-serverless-java-container-spring:1.5.2'
}
task buildZip(type: Zip) {
into('lib') {
from(jar)
from(configurations.runtimeClasspath)
}
}
tasks.named('test') {
useJUnitPlatform()
}
jar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes "Main-Class": "com.example.awstest"
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Spring Boot应用程序类:
package com.example.awstest.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@ComponentScan ("com.example.awstest")
public class AWSTestApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(AWSTestApplication.class, args);
}
}
Spring Boot控制器:
package com.example.awstest.controller;
@RestController
public class AWSTestController {
@Autowired
private AWSTestServiceDAO awstestServiceDAO;
@CrossOrigin(origins = "*")
@GetMapping("/searchAllData")
public List<TESTData> searchAllData() {
List<TESTData> dataList = awstestServiceDAO.getAllData();
return dataList;
}
@CrossOrigin(origins = "*")
@GetMapping("/searchDataByUser/{userno}")
public List<TESTData> searchDataByUser(@PathVariable Integer userno) {
List<TESTData> dataList = awstestServiceDAO.findDataByMemberNo(userno);
return dataList;
}
}
Lambda控制台:
将处理程序添加为:com.example.awstest.handler.AWSLambdaHandler::handleRequest
测试函数:apigateway-awsproxy
{
"body": "eyJ0ZXN0IjoiYm9keSJ9",
"resource": "/{proxy+}",
"path": "/searchAllData",
"httpMethod": "GET",
"isBase64Encoded": true,
"pathParameters": {
"proxy": "/searchAllData"
},
"stageVariables": {
"baz": "qux"
},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, sdch",
"Accept-Language": "en-US,en;q=0.8",
"Cache-Control": "max-age=0",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Host": "1234567890.execute-api.us-east-1.amazonaws.com",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Custom User Agent String",
"Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
"X-Forwarded-For": "127.0.0.1, 127.0.0.2",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"multiValueHeaders": {
"Accept": [
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
],
"Accept-Encoding": [
"gzip, deflate, sdch"
],
"Accept-Language": [
"en-US,en;q=0.8"
],
"Cache-Control": [
"max-age=0"
],
"CloudFront-Forwarded-Proto": [
"https"
],
"CloudFront-Is-Desktop-Viewer": [
"true"
],
"CloudFront-Is-Mobile-Viewer": [
"false"
],
"CloudFront-Is-SmartTV-Viewer": [
"false"
],
"CloudFront-Is-Tablet-Viewer": [
"false"
],
"CloudFront-Viewer-Country": [
"US"
],
"Host": [
"0123456789.execute-api.us-east-1.amazonaws.com"
],
"Upgrade-Insecure-Requests":
<details>
<summary>英文:</summary>
I uploaded Spring boot jar file (it has lambda request stream handler) into AWS Lambda as zip file. Since the zip is big, I uploaded in S3 and given that link while creating this Lambda function in AWS Console. As I read everywhere that that's all the spring boot service deployment in lambda with the simple method. My spring boot service has 2 GET end points in it. Please find entire Spring boot service code and Lambda screenshots below.
Error: (It gave timeout error, so increased to 15 mins in Lambda test and the result is below, which seems to be not working still)
Executing function: succeeded (logs )
{
"statusCode": 502,
"multiValueHeaders": {
"Content-Type": [
"application/json"
]
},
"body": "{\"message\":\"Gateway timeout\"}",
"isBase64Encoded": false
}
Spring boot Request Stream Handler for Lambda: (Asynchronous, as i felt Lambda takes much time to start initially)
public class StreamLambdaHandler implements RequestStreamHandler {
private SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
public StreamLambdaHandler() throws ContainerInitializationException {
handler = new SpringBootProxyHandlerBuilder()
.defaultProxy()
.asyncInit()
.springBootApplication(SlowApplication.class)
.buildAndInitialize();
}
@Override
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
throws IOException {
handler.proxyStream(inputStream, outputStream, context);
}
}
build.gradle ( I added "task buildZip" here to get build->"distributions" jar in zip file)
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'mysql:mysql-connector-java:8.0.32'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
implementation 'com.amazonaws:aws-lambda-java-events:3.11.1'
implementation 'com.amazonaws.serverless:aws-serverless-java-container-spring:1.5.2'
}
task buildZip(type: Zip) {
into('lib') {
from(jar)
from(configurations.runtimeClasspath)
}
}
tasks.named('test') {
useJUnitPlatform()
}
jar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes "Main-Class": "com.example.awstest"
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Spring Boot Application Class:
package com.example.awstest.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@ComponentScan ("com.example.awstest")
public class AWSTestApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(AWSTestApplication.class, args);
}
}
Spring Boot Controller:
package com.example.awstest.controller;
@RestController
public class AWSTestController {
@Autowired
private AWSTestServiceDAO awstestServiceDAO;
@CrossOrigin(origins = "*")
@GetMapping("/searchAllData")
public List<TESTData> searchAllData() {
List<TESTData> dataList = awstestServiceDAO.getAllData();
return dataList;
}
@CrossOrigin(origins = "*")
@GetMapping("/searchDataByUser/{userno}")
public List<TESTData> searchDataByUser(@PathVariable Integer userno) {
List<TESTData> dataList = awstestServiceDAO.findDataByMemberNo(userno);
return dataList;
}
}
Lambda Console:
Added handler as: `com.example.awstest.handler.AWSLambdaHandler::handleRequest`
Test Function: apigateway-awsproxy
{
"body": "eyJ0ZXN0IjoiYm9keSJ9",
"resource": "/{proxy+}",
"path": "/searchAllData",
"httpMethod": "GET",
"isBase64Encoded": true,
"pathParameters": {
"proxy": "/searchAllData"
},
"stageVariables": {
"baz": "qux"
},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, sdch",
"Accept-Language": "en-US,en;q=0.8",
"Cache-Control": "max-age=0",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Host": "1234567890.execute-api.us-east-1.amazonaws.com",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Custom User Agent String",
"Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
"X-Forwarded-For": "127.0.0.1, 127.0.0.2",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"multiValueHeaders": {
"Accept": [
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
],
"Accept-Encoding": [
"gzip, deflate, sdch"
],
"Accept-Language": [
"en-US,en;q=0.8"
],
"Cache-Control": [
"max-age=0"
],
"CloudFront-Forwarded-Proto": [
"https"
],
"CloudFront-Is-Desktop-Viewer": [
"true"
],
"CloudFront-Is-Mobile-Viewer": [
"false"
],
"CloudFront-Is-SmartTV-Viewer": [
"false"
],
"CloudFront-Is-Tablet-Viewer": [
"false"
],
"CloudFront-Viewer-Country": [
"US"
],
"Host": [
"0123456789.execute-api.us-east-1.amazonaws.com"
],
"Upgrade-Insecure-Requests": [
"1"
],
"User-Agent": [
"Custom User Agent String"
],
"Via": [
"1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)"
],
"X-Amz-Cf-Id": [
"cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA=="
],
"X-Forwarded-For": [
"127.0.0.1, 127.0.0.2"
],
"X-Forwarded-Port": [
"443"
],
"X-Forwarded-Proto": [
"https"
]
},
"requestContext": {
"accountId": "123456789012",
"resourceId": "123456",
"stage": "prod",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
"requestTime": "09/Apr/2015:12:34:56 +0000",
"requestTimeEpoch": 1428582896000,
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"accessKey": null,
"sourceIp": "127.0.0.1",
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": "Custom User Agent String",
"user": null
},
"path": "/prod/searchAllData",
"resourcePath": "/{proxy+}",
"httpMethod": "GET",
"apiId": "1234567890",
"protocol": "HTTP/1.1"
}
}
Error:
s.exceptions.ContainerInitializationException: Could not initialize framework within the 20000ms timeout
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:207)
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:254)
at com.example.awstest.handler.AWSLambdaHandler.handleRequest(AWSLambdaHandler.java:36)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379)
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185)
04:36:48.470 [main] ERROR com.amazonaws.serverless.proxy.AwsProxyExceptionHandler -- Called exception handler for:
com.amazonaws.serverless.exceptions.ContainerInitializationException: Could not initialize framework within the 20000ms timeout
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:207)
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:254)
at com.example.awstest.handler.AWSLambdaHandler.handleRequest(AWSLambdaHandler.java:36)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379)
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185)
com.amazonaws.serverless.exceptions.ContainerInitializationException: Could not initialize framework within the 20000ms timeout
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:207)
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:254)
at com.example.awstest.handler.AWSLambdaHandler.handleRequest(AWSLambdaHandler.java:36)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379)
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185)
END RequestId: 21464e19-8dee-47e0-9acd-5ae04d24431a
REPORT RequestId: 21464e19-8dee-47e0-9acd-5ae04d24431a Duration: 20003.03 ms Billed Duration: 20004 ms Memory Size: 512 MB Max Memory Used: 137 MB
</details>
# 答案1
**得分**: 3
你的Gradle文件中使用了一个非常老旧且不兼容Spring Boot 3.x的AWS Serverless Java Container版本。
请移除`com.amazonaws.serverless:aws-serverless-java-container-spring:1.5.2`,并替换为`com.amazonaws.serverless:aws-serverless-java-container-springboot3:2.0.0-M1`。你还可以在https://github.com/awslabs/aws-serverless-java-container/tree/main/samples/springboot3/pet-store 中找到一个完全可用的示例,用于进行比较。
如果将来遇到类似的超时挑战,你还可以启用[AWS X-Ray][1]或[OpenTelemetry][2]以收集跟踪数据,查看时间消耗在哪里。
[1]: https://aws.amazon.com/xray/
[2]: https://aws-otel.github.io/docs/getting-started/lambda
<details>
<summary>英文:</summary>
Looking at your Gradle file you are using a very old outdated AWS Serverless Java Container version that is not compatible with Spring Boot 3.x.
Remove `com.amazonaws.serverless:aws-serverless-java-container-spring:1.5.2` and replace it with `com.amazonaws.serverless:aws-serverless-java-container-springboot3:2.0.0-M1`. You'll also find a fully working sample in https://github.com/awslabs/aws-serverless-java-container/tree/main/samples/springboot3/pet-store for comparison.
If you come across similar timeout challenges in the future, you can also enable [AWS X-Ray][1] or [OpenTelemetry][2] to gather tracing data and see where time is lost.
[1]: https://aws.amazon.com/xray/
[2]: https://aws-otel.github.io/docs/getting-started/lambda
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论