6. AWS APIGateway, AWS Lambda与Spring boot集成实现serverless

AWS Lambda简介 AWS Lambda 是一项计算服务,可使用户无需预配置或管理服务器即可运行代码。
在使用 AWS Lambda 时,只需负责自己的代码。AWS Lambda 管理提供内存、CPU、网络和其他资源均衡的计算机群。
AWS Lambda 概念 函数
函数是一个资源,您可以调用它来在 AWS Lambda 中运行您的代码。一个函数具有处理事件的代码,以及在 Lambda 与函数代码之间传递请求和响应的运行时。您负责提供代码,并且可以使用提供的运行时或创建自己的运行时。
Runtime 运行时
AWS Lambda 通过使用运行时支持多种语言。您可以在创建函数时选择运行时,并且可以通过更新函数的配置来更改运行时。底层执行环境提供了您可通过函数代码访问的额外的库和环境变量。
Event
事件是 JSON 格式的文档,其中包含函数要处理的数据。Lambda 运行时将事件转换为一个对象,并将该对象传递给函数代码。在调用函数时,可以确定事件的结构和内容。
并发
并发性是您的函数在任何给定时间所服务于的请求的数目。在调用函数时,Lambda 会预配置其实例以处理事件。当函数代码完成运行时,它会处理另一个请求。如果当仍在处理请求时再次调用函数,则预配置另一个实例,从而增加该函数的并发性。
并发性受区域级别限制的约束。
Trigger
触发器是调用 Lambda 函数的资源或配置。这包括可配置为调用函数的 AWS 服务、您开发的应用程序以及事件源映射。事件源映射是 Lambda 中的一种资源,它从流或队列中读取项目并调用函数。
AWS Lambda 功能 编程模型
【6. AWS APIGateway, AWS Lambda与Spring boot集成实现serverless】代码编写细节因运行时而异,但所有运行时都共用一个通用的编程模型,该模型定义了代码与运行时代码之间的接口。通过在函数配置中定义处理程序来告诉运行时运行哪个方法,然后运行时会运行该方法。运行时将对象(例如函数名和请求 ID)传递给包含调用事件以及上下文的处理程序。
扩展
Lambda 管理运行代码的基础设施,并且会自动扩展以响应传入请求。当您的函数的调用速度快于函数的单个实例可处理事件的速度时,Lambda 会通过运行其他实例来进行扩展。当流量减少时,不活动的实例将被冻结或停止。您只需为函数初始化或处理事件的时间付费。
并发控制
要使函数能够在延迟不发生波动的情况下进行扩展,请使用预配置并发。对于需要很长时间才能初始化的函数,或者所有调用需要极低延迟的函数,预配置并发使您能够预先初始化函数的实例并保持它们始终运行。
异步调用
调用函数时,您可以选择同步或异步调用。使用同步调用时,您将等待函数处理该事件并返回响应。使用异步调用时,Lambda 会将事件排队等待处理并立即返回响应。
事件源映射
要处理流或队列中的项,您可以创建事件源映射。事件源映射是 Lambda 中的一个资源,它从 Amazon SQS 队列、Amazon Kinesis 流或 Amazon DynamoDB 流中读取项目,并将它们批量发送到您的函数。您的函数处理的每个事件可以包含数百个或数千个项。
目标
目标是接收函数调用记录的 AWS 资源。对于异步调用,您可以配置 Lambda 以将调用记录发送到队列、主题、函数或事件总线。您可以为成功调用和处理失败的事件配置单独的目标。调用记录包含有关事件、函数的响应和记录发送原因的详细信息。
AWS Lambda 限制 AWS Lambda 将限制可用来运行和存储函数的计算和存储资源量。以下限制按区域应用,并且可以提高这些限制。

资源 默认限制
并发执行
1,000
函数和层存储
75 GB
每个 VPC 的弹性网络接口数
250
以下限制适用于函数配置、部署和执行。无法对其进行更改。
资源 限制
函数内存分配
128 MB 到 3,008 MB,以 64 MB 为增量。
函数超时
900 秒(15 分钟)
函数环境变量
4 KB
函数基于资源的策略
20 KB
函数层
5 层
函数突增并发
500 - 3000(每个区域各不相同)
每个区域的调用频率(每秒请求数)
10 倍并发执行限制(同步 – 所有资源)
10 倍并发执行限制(异步 – 非 AWS 资源)
无限制(异步 – AWS 服务资源)
每个函数版本或别名的调用频率(每秒请求数)
10 x 分配的预配置并发
此限制仅适用于使用预配置并发的函数。
调用负载(请求和响应)
6 MB(同步)
256 KB(异步)
部署程序包大小
50 MB(已压缩,可直接上传)
250 MB(解压缩,包括层)
3 MB(控制台编辑器)
测试事件(控制台编辑器)
10
/tmp 目录存储
512 MB
文件描述符
1,024
执行进程/线程
1,024
aws-serverless-java-container 使用aws-serverless-java-container可以轻松的使用AWS Lambda运行Spring,Spring Boot,Apache Struts,Jersey或Spark之类的框架编写的Java应用程序。
工作原理 aws-serverless-java-container的基本作用是作为一个Servlet container; 从lambda接收事件对象并将其翻译成框架所需的request对象, 同时将框架返回的responses对象翻译成对API Gateway有效的返回值。
AWS Lambda与Spring boot集成 创建social-network-serverless-lambda子模块 该子模块主要用于提供各种aws ambda的服务,与lambda相关的所有代码都会放在该模块中。
选中social-network-serverless project,然后Intellij -> File -> New Project,在弹出的对话框中选择Maven, 使用默认配置,然后Next进入下一步配置。
配置项目的名称,位置和artifact信息(可以根据自己需要进行配置),点击Finish完成模块创建。
Parent:social-network-serverless
Name:social-network-serverless-lambda
Grouop: com.jessica
Artifact:social-network-serverless-lambda
在父模块中对子模块以及lambda相关的包进行版本管理 social-network-serverless父模块的pom文件,在dependencyManagement中加入social-network-serverless-lambda
com.jessica social-network-serverless-lambda ${project.version}

修改social-network-serverless父模块的pom文件,添加对aws-serverless-java-container的版本管理
com.amazonaws.serverless aws-serverless-java-container-springboot2 1.5

在lambda子模块中添加需要的依赖 social-network-serverless-lambda子模块需要依赖web子模块以及ws-serverless-java-container
com.amazonaws.serverless aws-serverless-java-container-springboot2 com.jessica social-network-serverless-web

在lambda子模块中创建handler
public class StreamLambdaHandler implements RequestStreamHandler { private static SpringBootLambdaContainerHandler handler; static { try { handler = SpringBootLambdaContainerHandler.getAwsProxyHandler( SocialNetworkServerlessWebApplication.class); } catch (ContainerInitializationException e) { // if we fail here. We re-throw the exception to force another cold start e.printStackTrace(); throw new RuntimeException("Could not initialize Spring Boot application", e); } }@Override public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { handler.proxyStream(inputStream, outputStream, context); } }

配置lambda子模块的打包方式 这里需要将lambda子模块依赖到的所有包全部打包进lambda子模块的jar包,需要用到maven-shade-plugin.
修改social-network-serverless父模块的pom文件对插件的版本进行管理
org.apache.maven.plugins maven-shade-plugin 2.3

在lambda子模块中添加maven-shade-plugin
org.apache.maven.plugins maven-shade-plugin false package shade ${project.artifactId} false org.apache.tomcat.embed:*

修改web子模块的plugin,删除spring-boot-maven-plugin,整个模块可以删除。
配置lambda部署文件 在social-network-serverless-lambda子模块根目录下创建serverless.yml文件
service: social-network-serverless frameworkVersion: ">=1.2.0 <2.0.0" plugins: - serverless-pseudo-parameterscustom: configFile: ${file(../config.yml)}provider: name: aws stage: ${self:custom.configFile.stage} variant: ${self:custom.configFile.variant} runtime: java8 region: ${self:custom.configFile.region} timeout: 30 # The default is 6 seconds. Note: API Gateway current maximum is 30 seconds memorySize: 1024 # Overwrite the default memory size. Default is 1024. Increase by 64. deploymentBucket: ${self:custom.configFile.deploymentBucket} environment: ${file(../config.yml)} stackName: ${self:provider.stage}-${self:provider.variant}-${self:service}package: artifact: target/social-network-serverless-lambda.jarfunctions: socialNetworkServerless: # name must have length less than or equal to 64 name: ${self:provider.stage}-${self:provider.variant}-socialNetworkServerless handler: com.jessica.social.network.serverless.lambda.handler.StreamLambdaHandler events: - http: path: /{proxy+} method: any timeout: 30

http类型的event即将lambda函数映射到 apigateway,当访问apigateway对应的url时会自动调用lambda函数.
部署lambda 首先在social-network-serverless-lambda目录下运行: mvn package命令对模块进行打包
然后在social-network-serverless-lambda目录下运行:serverless deploy -v 对lambda进行部署
$ sls deploy -v Serverless: Packaging service... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service .zip file to S3 (37.42 MB)... Serverless: Validating template... Serverless: Creating Stack... Serverless: Checking Stack create progress... CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - develop-jessica-social-network-serverless CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - SocialNetworkServerlessLogGroup CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - SocialNetworkServerlessLogGroup CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::RestApi - ApiGatewayRestApi CloudFormation - CREATE_COMPLETE - AWS::Logs::LogGroup - SocialNetworkServerlessLogGroup CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - SocialNetworkServerlessLambdaFunction CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceProxyVar CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceProxyVar CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceProxyVar CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - SocialNetworkServerlessLambdaFunction CloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - SocialNetworkServerlessLambdaFunction CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - SocialNetworkServerlessLambdaVersionwmoOmOF3BHjvcbAxMI7VsbbkxSYANSTdQ7qT8NbbZE CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodProxyVarAny CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodProxyVarAny CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - SocialNetworkServerlessLambdaPermissionApiGateway CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - SocialNetworkServerlessLambdaPermissionApiGateway CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodProxyVarAny CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - SocialNetworkServerlessLambdaVersionwmoOmOF3BHjvcbAxMI7VsbbkxSYANSTdQ7qT8NbbZE CloudFormation - CREATE_COMPLETE - AWS::Lambda::Version - SocialNetworkServerlessLambdaVersionwmoOmOF3BHjvcbAxMI7VsbbkxSYANSTdQ7qT8NbbZE CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1590485883742 CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1590485883742 CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1590485883742 CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - SocialNetworkServerlessLambdaPermissionApiGateway CloudFormation - CREATE_COMPLETE - AWS::CloudFormation::Stack - develop-jessica-social-network-serverless Serverless: Stack create finished... Service Information service: social-network-serverless stage: develop region: ap-southeast-1 stack: develop-jessica-social-network-serverless api keys: None endpoints: ANY - https://******.execute-api.ap-southeast-1.amazonaws.com/develop/{proxy+} functions: socialNetworkServerless: social-network-serverless-develop-socialNetworkServerless layers: None

部署过程会自动创建apigateway对应的资源,包括:
  • AWS::ApiGateway::RestApi - ApiGatewayRestApi
  • AWS::ApiGateway::Resource - ApiGatewayResourceProxyVar
  • AWS::ApiGateway::Method - ApiGatewayMethodProxyVarAny
  • AWS::ApiGateway::Deployment - ApiGatewayDeployment1590485883742
部署成功后的endpoints即为lambda对应的apigateway的地址,访问该地址即可自动调用lambda函数.
endpoints: ANY - https://******.execute-api.ap-southeast-1.amazonaws.com/develop/{proxy+}

测试 从部署的输出结果中可以看到服务的url,这里默认都加上了/develop的context-path。
endpoints: ANY - https://******.execute-api.ap-southeast-1.amazonaws.com/develop/{proxy+}

访问 https://*****.execute-api.ap-southeast-1.amazonaws.com/develop/swagger-ui.html,由于timeout的问题,需要多等一会,或者多刷新几次页面将js和css之类的静态文件先由浏览器缓存下来,之后再访问就可以看到swagger的页面。
6. AWS APIGateway, AWS Lambda与Spring boot集成实现serverless
文章图片

此时在swagger页面上无法直接发送请求,因为页面上直接发送的请求都不带/develop的context-path, 可以使用postman等工具进行测试:
6. AWS APIGateway, AWS Lambda与Spring boot集成实现serverless
文章图片

参考 https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/welcome.html
https://epsagon.com/blog/aws-lambda-and-java-spring-boot-getting-started/
https://github.com/awslabs/aws-serverless-java-container
https://github.com/awslabs/aws-serverless-java-container/wiki/Quick-start---Spring-Boot2
https://skryvets.com/blog/2018/06/02/spring-boot-aws-lambda-guide/
https://github.com/awsdocs/aws-lambda-developer-guide/blob/master/sample-apps/java-events-v1sdk/template.yml

    推荐阅读