目标:我有一个spring Boot 应用程序,我想让它使用lambda。
意义:我想创建一个可以上传到lambda函数的jar,当我用API Gateway调用它时,它将返回与我在计算机上用java -jar
运行它相同的结果。
我有一个@RestController
,我创建了一个名为:StreamLambdaHandler.java
,它应该处理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
函数作为lambda函数的入口点:
enter image description here
我试着和山姆做。我的山姆。
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用户界面中测试了lambda函数。
我得到了这个结果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
如果有人对这个过程和我做错了什么有一些见解,请分享。更重要的是,如果你知道如何解决它。我对此感到非常沮丧。
4条答案
按热度按时间wyyhbhjk1#
AWS实验室(Amazon的一个附属项目)有一个开源库“aws-serverless-java-container”,它完全可以做你想做的事情!它支持Spring、Sping Boot 、Spark、Jersey、Struts和其他流行的框架,并且是现有应用程序上的一个非常薄的 Package 器。简而言之,你可以从依赖项中排除嵌入式Tomcat,用Maven shade Package 你的jar(而不是通过Sping Boot Maven插件创建一个可执行jar,并定义一个LambdaHandler,在其中配置基本上告诉库你的主类是什么,以及它是否是React式或WebMVC应用,还有一些其他的配置(比如使用什么样的请求形式(例如ApiGateway v1、v2等))和库来完成剩下的工作。它很棒,但是Spring不是这个用例的最佳框架,因为它的启动时间很长,因为Sping Boot 使用反射来尝试和猜测应用程序的配置应该是什么(基于对类路径的依赖性等)(如果延迟对你来说是个问题的话)但是好消息是很快Spring 3就会支持Graalvm,也许还有函数bean注册,所以启动时间在未来几年会有很大的改善。我发现使用Spring over Sping Boot 或者禁用自动配置并显式地手动配置上下文可以缩短启动时间,从类路径中删除所有不必要的依赖项也是如此。
https://github.com/awslabs/aws-serverless-java-containerhttps://github.com/awslabs/aws-serverless-java-container/wiki/Quick-start---Spring-Boot2
e4yzc0pl2#
您也可以检查此库:https://github.com/MelonProjectCom/lambda-http-router
它的工作原理与标准控制器相同。
bd1hkmkf3#
屏幕截图显示了类的错误包名。
应该是
pryce_pick.search.StreamLambdaHandler::handleRequest
vsnjm48y4#
您可以使用register Function Bean,它将作为Lambda工作并支持所有Spring Boot特性。
创建带有@Bean注解的函数
默认情况下,此Bean将作为Lambda工作。
您还需要添加
org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleReques
作为AWS Lambda中的处理程序。如果您希望使用相同的代码库,并将多个
Bean
Function
用作Lambda,则可以有条件地启用Bean
,如下所示:Spring 正式单据
Spring GitHub Repo
Serverless.com Article
另一种方法(未测试)
这也可以通过here实现。[未测试]