簡體   English   中英

如何讓lambda支持spring開機

[英]How to make lambda support spring boot

目標:我有一個 spring 啟動應用程序,我想讓它與 lambda 一起工作。
意思是:我想創建一個 jar,它可以上傳到 lambda function,當我用 API 網關調用它時,它會返回與我在計算機上用java -jar運行它時相同的結果。

我有一個@RestController ,我創建了一個名為: StreamLambdaHandler.java的 class,它應該處理 lambda 部分。

package mypackage;

import com.amazonaws.serverless.exceptions.ContainerInitializationException;
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class StreamLambdaHandler implements RequestStreamHandler {
    private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
    static {
        try {
            handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(MyClass.class); // MyClass is the class where I do SpringApplication.run for my app
        } catch (ContainerInitializationException e) {
            e.printStackTrace();
            throw new RuntimeException("Could initialize Spring framework", e);
        }
    }

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        handler.proxyStream(inputStream, outputStream, context);
        outputStream.close();
    }
}                                                                                                                                                            

我使用它的handleRequest function 作為 lambda function 的入口點:
在此處輸入圖像描述


我試着用 SAM 來做。 我的 saml.yaml:

AWSTemplateFormatVersion: '2010-09-09'                                                       
Transform: AWS::Serverless-2016-10-31
Description: AWS Serverless Spring Boot API - Spring Boot API PrycePick
Resources:
  SpringbootSampleFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler:  pryce_pick.search.StreamLambdaHandler::handleRequest
      Runtime: java11
      CodeUri: out/artifacts/myfunction/my.zip
      MemorySize: 512
      Policies: AWSLambdaBasicExecutionRole
      Timeout: 30
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /{proxy+}
            Method: any

Outputs:
  SpringbootSampleApi:
    Description: URL for application
    Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/'
    Export:
      Name: SpringbootApp

我運行了命令:
aws cloudformation package --template-file sam.yaml --output-template-file output-sam.yaml --s3-bucket mybucket

aws cloudformation deploy --template-file output-sam.yaml --stack-name bookApi --capabilities CAPABILITY_IAM

到目前為止,我所做的一切都是在多本手冊的指導下進行的。
創建了 jar 和所有依賴項,並在 amazon ui 中測試了 lambda function。

我得到了這個結果enter image description here似乎說一切正常。
但是,當我打開上下文時,我得到了這個: enter image description here這顯然說出了點問題,而且它不起作用的事實說明了:)

另外還有一個日志:

ationTypeMapping.java:102)
at org.springframework.core.annotation.AnnotationTypeMappings.addIfPossible(AnnotationTypeMappings.java:112)
at org.springframework.core.annotation.AnnotationTypeMappings.addIfPossible(AnnotationTypeMappings.java:105)
at org.springframework.core.annotation.AnnotationTypeMappings.addMetaAnnotationsToQueue(AnnotationTypeMappings.java:99)
at org.springframework.core.annotation.AnnotationTypeMappings.addAllMappings(AnnotationTypeMappings.java:79)
at org.springframework.core.annotation.AnnotationTypeMappings.<init>(AnnotationTypeMappings.java:68)
at org.springframework.core.annotation.AnnotationTypeMappings.<init>(AnnotationTypeMappings.java:46)
at org.springframework.core.annotation.AnnotationTypeMappings$Cache.createMappings(AnnotationTypeMappings.java:245)
at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(Unknown Source)
at org.springframework.core.annotation.AnnotationTypeMappings$Cache.get(AnnotationTypeMappings.java:241)
at org.springframework.core.annotation.AnnotationTypeMappings.forAnnotationType(AnnotationTypeMappings.java:199)
at org.springframework.core.annotation.AnnotationTypeMappings.forAnnotationType(AnnotationTypeMappings.java:182)
at org.springframework.core.annotation.AnnotationTypeMappings.forAnnotationType(AnnotationTypeMappings.java:169)
at org.springframework.core.annotation.TypeMappedAnnotations$IsPresent.doWithAnnotations(TypeMappedAnnotations.java:330)
at org.springframework.core.annotation.TypeMappedAnnotations$IsPresent.doWithAnnotations(TypeMappedAnnotations.java:279)
at org.springframework.core.annotation.AnnotationsScanner.processClassHierarchy(AnnotationsScanner.java:188)
at org.springframework.core.annotation.AnnotationsScanner.processClassHierarchy(AnnotationsScanner.java:171)
at org.springframework.core.annotation.AnnotationsScanner.processClass(AnnotationsScanner.java:106)
at org.springframework.core.annotation.AnnotationsScanner.process(AnnotationsScanner.java:86)
at org.springframework.core.annotation.AnnotationsScanner.scan(AnnotationsScanner.java:77)
at org.springframework.core.annotation.TypeMappedAnnotations.scan(TypeMappedAnnotations.java:242)
at org.springframework.core.annotation.TypeMappedAnnotations.isPresent(TypeMappedAnnotations.java:98)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:144)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:97)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:132)
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:52)
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:163)
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:198)
at mypackage.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:29)
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 lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:375)
at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:899)
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:262)
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:199)
at lambdainternal.AWSLambda.main(AWSLambda.java:193)
END RequestId: 29d504dc-3510-4d78-b010-3fe48a4e6f13
REPORT RequestId: 29d504dc-3510-4d78-b010-3fe48a4e6f13  Duration: 2278.06 ms    Billed Duration: 2279 ms    Memory Size: 512 MB Max Memory Used: 106 MB Init Duration: 940.24 ms    

如果有人對這個過程有一些了解以及我做錯了什么,請分享。 更重要的是,如果你知道如何解決它。我對此感到非常沮喪。

你也可以查看這個庫: https://github.com/MelonProjectCom/lambda-http-router

它像標准 Controller 一樣工作。

 @PathPostMapping("/example/test")
 public String example(@Body String body) {
    return "Hello World! - body: " + body;
 }

您的屏幕截圖顯示了您班級的錯誤包名稱。

它應該是

pryce_pick.search.StreamLambdaHandler::handleRequest

您可以使用寄存器 Function Bean,它將用作 Lambda 並支持所有 Spring 引導功能。

使用@Bean 注解創建 Function

@Bean
public Function<String, String> uppercase() {
  return value -> {
      return value.toUpperCase();
  };
}

默認情況下,此 Bean 將作為 Lambda 工作。

您還需要在 AWS Lambda 中添加org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleReques作為處理程序。

如果您想將相同的代碼庫與多個Bean Function作為 Lambda 一起使用,那么您可以有條件地啟用Bean ,如下所示:

@Bean
@ConditionalOnProperty(name="active.lambda", havingValue="MyLambdaOne")
public Function<String, String> uppercase() {
  return value -> {
      return value.toUpperCase();
  };
}

參考:

官方 Spring 文檔

Spring GitHub 回購

Serverless.com 文章

另一種方法(未測試)

這也可以像這里提到的那樣實現。 [未測試]

AWS 實驗室(亞馬遜附屬項目)有一個開源庫“aws-serverless-java-container”,它完全可以滿足您的需求,它支持 Spring、Spring Boot、Spark、Z3CDA26E0C8AEDBF662ADB42F923EF 框架。 and is a very thin wrapper over your existing application, In a nutshell, you exclude embedded tomcat from your dependencies, and package your jar using maven shade (instead of creating an executable jar via the spring boot maven plugin, and define a LambdaHandler where you configure 基本上告訴庫您的主要 class 是什么,以及它是響應式應用程序還是 webmvc 應用程序。以及一些其他配置(例如使用什么請求形狀(例如,ApiGateway v1、v2.等)和庫執行rest,很好,但是 Spring 不是這個用例的最佳框架,因為它的啟動時間很長,因為 Spring 引導使用反射來嘗試猜測你的應用程序的方式配置應該是(基於對你的類路徑的依賴。 等)(如果延遲對您來說是個問題),但好消息很快 Spring 3 將支持 graalvm。 也許功能 bean 注冊,所以啟動時間應該會在未來幾年顯着改善,當我不得不在生產中使用這個庫時,我發現使用 Spring 而不是 Spring 引導或禁用自動配置並手動顯式配置上下文會產生更好的效果啟動時間。 從類路徑中刪除所有不必要的依賴項也是如此。

https://github.com/awslabs/aws-serverless-java-container https://github.com/awslabs/aws-serverless-java-container/wiki/Quick-start---Spring-Boot2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM