“Spring Boot部署在Lambda中出现\”statusCode\”: 502 网关超时”

huangapple go评论77阅读模式
英文:

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&#39;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 )
        {
      &quot;statusCode&quot;: 502,
      &quot;multiValueHeaders&quot;: {
        &quot;Content-Type&quot;: [
          &quot;application/json&quot;
        ]
      },
      &quot;body&quot;: &quot;{\&quot;message\&quot;:\&quot;Gateway timeout\&quot;}&quot;,
      &quot;isBase64Encoded&quot;: 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&lt;AwsProxyRequest, AwsProxyResponse&gt; 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 &quot;task buildZip&quot; here to get build-&gt;&quot;distributions&quot; jar in zip file)

    plugins {
        id &#39;java&#39;
        id &#39;org.springframework.boot&#39; version &#39;3.1.0&#39;
        id &#39;io.spring.dependency-management&#39; version &#39;1.1.0&#39;
    }
    
    group = &#39;com.example&#39;
    version = &#39;0.0.1-SNAPSHOT&#39;
    sourceCompatibility = &#39;17&#39;
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        implementation &#39;org.springframework.boot:spring-boot-starter-web&#39;
        implementation &#39;org.springframework.boot:spring-boot-starter-test&#39;
        implementation &#39;mysql:mysql-connector-java:8.0.32&#39;
        implementation &#39;org.springframework.boot:spring-boot-starter-jdbc&#39;
        implementation &#39;com.amazonaws:aws-lambda-java-core:1.2.2&#39;
        implementation &#39;com.amazonaws:aws-lambda-java-events:3.11.1&#39;
        implementation &#39;com.amazonaws.serverless:aws-serverless-java-container-spring:1.5.2&#39;
    }
    task buildZip(type: Zip) {
        into(&#39;lib&#39;) {
            from(jar)
            from(configurations.runtimeClasspath)
        }
    }
    tasks.named(&#39;test&#39;) {
        useJUnitPlatform()
    }
    jar {
        duplicatesStrategy = DuplicatesStrategy.EXCLUDE
        manifest {
            attributes &quot;Main-Class&quot;: &quot;com.example.awstest&quot;
        }
    
        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 (&quot;com.example.awstest&quot;)
    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 = &quot;*&quot;)
                @GetMapping(&quot;/searchAllData&quot;)
                public List&lt;TESTData&gt; searchAllData() {
        
                    List&lt;TESTData&gt; dataList = awstestServiceDAO.getAllData();
                    return dataList;
                 }
        
                @CrossOrigin(origins = &quot;*&quot;)
                @GetMapping(&quot;/searchDataByUser/{userno}&quot;)
                public List&lt;TESTData&gt; searchDataByUser(@PathVariable Integer userno) {
        
                    List&lt;TESTData&gt; dataList = awstestServiceDAO.findDataByMemberNo(userno);
                    return dataList;
                }
        
        }

Lambda Console:

Added handler as: `com.example.awstest.handler.AWSLambdaHandler::handleRequest`

Test Function: apigateway-awsproxy

    {
      &quot;body&quot;: &quot;eyJ0ZXN0IjoiYm9keSJ9&quot;,
      &quot;resource&quot;: &quot;/{proxy+}&quot;,
      &quot;path&quot;: &quot;/searchAllData&quot;,
      &quot;httpMethod&quot;: &quot;GET&quot;,
      &quot;isBase64Encoded&quot;: true,
      &quot;pathParameters&quot;: {
        &quot;proxy&quot;: &quot;/searchAllData&quot;
      },
      &quot;stageVariables&quot;: {
        &quot;baz&quot;: &quot;qux&quot;
      },
      &quot;headers&quot;: {
        &quot;Accept&quot;: &quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8&quot;,
        &quot;Accept-Encoding&quot;: &quot;gzip, deflate, sdch&quot;,
        &quot;Accept-Language&quot;: &quot;en-US,en;q=0.8&quot;,
        &quot;Cache-Control&quot;: &quot;max-age=0&quot;,
        &quot;CloudFront-Forwarded-Proto&quot;: &quot;https&quot;,
        &quot;CloudFront-Is-Desktop-Viewer&quot;: &quot;true&quot;,
        &quot;CloudFront-Is-Mobile-Viewer&quot;: &quot;false&quot;,
        &quot;CloudFront-Is-SmartTV-Viewer&quot;: &quot;false&quot;,
        &quot;CloudFront-Is-Tablet-Viewer&quot;: &quot;false&quot;,
        &quot;CloudFront-Viewer-Country&quot;: &quot;US&quot;,
        &quot;Host&quot;: &quot;1234567890.execute-api.us-east-1.amazonaws.com&quot;,
        &quot;Upgrade-Insecure-Requests&quot;: &quot;1&quot;,
        &quot;User-Agent&quot;: &quot;Custom User Agent String&quot;,
        &quot;Via&quot;: &quot;1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)&quot;,
        &quot;X-Amz-Cf-Id&quot;: &quot;cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==&quot;,
        &quot;X-Forwarded-For&quot;: &quot;127.0.0.1, 127.0.0.2&quot;,
        &quot;X-Forwarded-Port&quot;: &quot;443&quot;,
        &quot;X-Forwarded-Proto&quot;: &quot;https&quot;
      },
      &quot;multiValueHeaders&quot;: {
        &quot;Accept&quot;: [
          &quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8&quot;
        ],
        &quot;Accept-Encoding&quot;: [
          &quot;gzip, deflate, sdch&quot;
        ],
        &quot;Accept-Language&quot;: [
          &quot;en-US,en;q=0.8&quot;
        ],
        &quot;Cache-Control&quot;: [
          &quot;max-age=0&quot;
        ],
        &quot;CloudFront-Forwarded-Proto&quot;: [
          &quot;https&quot;
        ],
        &quot;CloudFront-Is-Desktop-Viewer&quot;: [
          &quot;true&quot;
        ],
        &quot;CloudFront-Is-Mobile-Viewer&quot;: [
          &quot;false&quot;
        ],
        &quot;CloudFront-Is-SmartTV-Viewer&quot;: [
          &quot;false&quot;
        ],
        &quot;CloudFront-Is-Tablet-Viewer&quot;: [
          &quot;false&quot;
        ],
        &quot;CloudFront-Viewer-Country&quot;: [
          &quot;US&quot;
        ],
        &quot;Host&quot;: [
          &quot;0123456789.execute-api.us-east-1.amazonaws.com&quot;
        ],
        &quot;Upgrade-Insecure-Requests&quot;: [
          &quot;1&quot;
        ],
        &quot;User-Agent&quot;: [
          &quot;Custom User Agent String&quot;
        ],
        &quot;Via&quot;: [
          &quot;1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)&quot;
        ],
        &quot;X-Amz-Cf-Id&quot;: [
          &quot;cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==&quot;
        ],
        &quot;X-Forwarded-For&quot;: [
          &quot;127.0.0.1, 127.0.0.2&quot;
        ],
        &quot;X-Forwarded-Port&quot;: [
          &quot;443&quot;
        ],
        &quot;X-Forwarded-Proto&quot;: [
          &quot;https&quot;
        ]
      },
      &quot;requestContext&quot;: {
        &quot;accountId&quot;: &quot;123456789012&quot;,
        &quot;resourceId&quot;: &quot;123456&quot;,
        &quot;stage&quot;: &quot;prod&quot;,
        &quot;requestId&quot;: &quot;c6af9ac6-7b61-11e6-9a41-93e8deadbeef&quot;,
        &quot;requestTime&quot;: &quot;09/Apr/2015:12:34:56 +0000&quot;,
        &quot;requestTimeEpoch&quot;: 1428582896000,
        &quot;identity&quot;: {
          &quot;cognitoIdentityPoolId&quot;: null,
          &quot;accountId&quot;: null,
          &quot;cognitoIdentityId&quot;: null,
          &quot;caller&quot;: null,
          &quot;accessKey&quot;: null,
          &quot;sourceIp&quot;: &quot;127.0.0.1&quot;,
          &quot;cognitoAuthenticationType&quot;: null,
          &quot;cognitoAuthenticationProvider&quot;: null,
          &quot;userArn&quot;: null,
          &quot;userAgent&quot;: &quot;Custom User Agent String&quot;,
          &quot;user&quot;: null
        },
        &quot;path&quot;: &quot;/prod/searchAllData&quot;,
        &quot;resourcePath&quot;: &quot;/{proxy+}&quot;,
        &quot;httpMethod&quot;: &quot;GET&quot;,
        &quot;apiId&quot;: &quot;1234567890&quot;,
        &quot;protocol&quot;: &quot;HTTP/1.1&quot;
      }
    }

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&#39;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>



huangapple
  • 本文由 发表于 2023年6月29日 07:10:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76577207.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定