java 如何制作λ支架 Spring Boot

8tntrjer  于 2023-01-24  发布在  Java
关注(0)|答案(4)|浏览(89)

目标:我有一个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

如果有人对这个过程和我做错了什么有一些见解,请分享。更重要的是,如果你知道如何解决它。我对此感到非常沮丧。

wyyhbhjk

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

e4yzc0pl

e4yzc0pl2#

您也可以检查此库:https://github.com/MelonProjectCom/lambda-http-router
它的工作原理与标准控制器相同。

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

bd1hkmkf3#

屏幕截图显示了类的错误包名。
应该是
pryce_pick.search.StreamLambdaHandler::handleRequest

vsnjm48y

vsnjm48y4#

您可以使用register Function Bean,它将作为Lambda工作并支持所有Spring Boot特性。
创建带有@Bean注解的函数

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

默认情况下,此Bean将作为Lambda工作。
您还需要添加org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleReques作为AWS Lambda中的处理程序。
如果您希望使用相同的代码库,并将多个BeanFunction用作Lambda,则可以有条件地启用Bean,如下所示:

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

Spring 正式单据
Spring GitHub Repo
Serverless.com Article

另一种方法(未测试)

这也可以通过here实现。[未测试]

相关问题