此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 spring-cloud-function 4.1.4! |
AWS Lambda
AWS 适配器采用 Spring Cloud Function 应用程序,并将其转换为可在 AWS Lambda 中运行的形式。
有关如何开始使用 AWS Lambda 的详细信息不在本文档的讨论范围之内,因此用户应有所熟悉 AWS 和 AWS Lambda,并希望了解 Spring 提供哪些附加价值。
开始
Spring Cloud Function 框架的目标之一是提供必要的基础设施元素,使简单的 Function 应用程序能够在特定环境中以某种方式进行交互。 简单的函数应用程序(在上下文或 Spring 中)是包含 Supplier、Function 或 Consumer 类型的 bean 的应用程序。 因此,使用 AWS 意味着应该以某种方式在 AWS Lambda 环境中识别和执行一个简单的函数 Bean。
让我们看一下这个例子:
@SpringBootApplication
public class FunctionConfiguration {
public static void main(String[] args) {
SpringApplication.run(FunctionConfiguration.class, args);
}
@Bean
public Function<String, String> uppercase() {
return value -> value.toUpperCase();
}
}
它显示了一个完整的 Spring Boot 应用程序,其中定义了一个函数 Bean。有趣的是,从表面上看,这只是 另一个启动应用程序,但在 AWS Adapter 的上下文中,它也是一个完全有效的 AWS Lambda 应用程序。无其他代码或配置 是必需的。您需要做的就是打包和部署它,所以让我们看看我们如何做到这一点。
为了简化操作,我们提供了一个可供构建和部署的示例项目,您可以在此处访问它。
您只需执行即可生成 JAR 文件。所有必要的 maven 插件都已设置好以生成
适当的 AWS 可部署的 JAR 文件。(您可以在 JAR 布局说明中阅读有关 JAR 布局的更多详细信息)。./mvnw clean package
然后,您必须将 JAR 文件(通过 AWS 控制面板或 AWS CLI)上传到 AWS。
当询问 handler 时,您可以指定哪个是通用请求处理程序。org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
就这样。保存并执行包含一些示例数据的函数,对于此函数,这些数据应为 String 的函数将大写并返回。
虽然是 AWS 的通用实施,旨在完全
将您与 AWS Lambda API 的具体内容隔离开来,在某些情况下,您可能需要指定所需的特定 AWS
使用。下一节将向您解释如何实现这一目标。org.springframework.cloud.function.adapter.aws.FunctionInvoker
RequestHandler
RequestHandler
AWS 请求处理程序
虽然 AWS Lambda 允许您实现各种 ,但使用 Spring Cloud Function,您无需实现任何 AWS 的 .
用户无需执行任何其他操作,只需在部署函数时在 AWS 控制面板上将其指定为 'handler'。
它将处理大多数情况,包括 Kinesis、流媒体等。RequestHandlers
org.springframework.cloud.function.adapter.aws.FunctionInvoker
RequestStreamHandler
如果您的应用程序具有多个 type etc. ,则您可以通过配置 property 或 environment 变量来选择要使用的一个。这些函数是从 Spring Cloud 中提取的。如果您未指定,框架将尝试按照搜索顺序查找默认值,首先搜索 for then 和 finally )。@Bean
Function
spring.cloud.function.definition
FunctionCatalog
spring.cloud.function.definition
Function
Consumer
Supplier
类型转换
Spring Cloud Function 将尝试透明地处理原始 input stream 和函数声明的类型。
例如,如果您的函数签名是这样的,我们将尝试将
传入 Stream 事件的实例。Function<Foo, Bar>
Foo
在事件类型未知或无法确定(例如)的情况下,我们将尝试
将传入流事件转换为泛型事件 。Function<?, ?>
Map
原始输入
有时您可能希望访问原始输入。在这种情况下,您只需声明
函数签名接受 .例如。在这种情况下
我们不会尝试任何转换,而是将原始输入直接传递给函数。InputStream
Function<InputStream, ?>
AWS 函数路由
Spring Cloud Function 的核心功能之一是 routing - 一种根据用户提供的 routing 指令将一个特殊函数委托给其他函数的能力。
在 AWS Lambda 环境中,此功能提供了一个额外的好处,因为它允许您绑定单个函数 (路由函数) 作为 AWS Lambda,因此是 API Gateway 的单个 HTTP 终端节点。因此,最终您只需管理一个功能和一个端点,同时受益 从许多功能中,这些函数可以成为您应用程序的一部分。
提供的示例中提供了更多详细信息, 但很少有一般的事情值得一提。
每当应用程序中有多个函数时,默认情况下将启用路由功能,因为无法确定要绑定为 AWS Lambda 的函数,因此默认为 。
这意味着您需要做的就是提供路由指令,您可以使用多种机制来完成这些指令(有关更多详细信息,请参见 sample )。org.springframework.cloud.function.adapter.aws.FunctionInvoker
RoutingFunction
另请注意,由于 AWS 不允许在环境变量名称中使用点和/或连字符'-',因此您可以从引导支持中受益,只需将
带下划线的点和带驼峰式大小写的连字符。因此,例如 become 和 become 。.
spring.cloud.function.definition
spring_cloud_function_definition
spring.cloud.function.routing-expression
spring_cloud_function_routingExpression
自定义运行时
您还可以从 AWS Lambda 的 AWS Lambda 自定义运行时功能中受益 Spring Cloud Function 提供了所有必要的组件来简化它。
从代码的角度来看,该应用程序看起来应该与任何其他 Spring Cloud Function 应用程序没有什么不同。
您唯一需要做的是在 zip/jar 的根目录中提供一个运行 Spring Boot 应用程序的脚本。
,然后在 AWS 中创建函数时选择“自定义运行时”。
下面是一个 'bootstrap' 文件示例:bootstrap
#!/bin/sh
cd ${LAMBDA_TASK_ROOT:-.}
java -Dspring.main.web-application-type=none -Dspring.jmx.enabled=false \
-noverify -XX:TieredStopAtLevel=1 -Xss256K -XX:MaxMetaspaceSize=128M \
-Djava.security.egd=file:/dev/./urandom \
-cp .:`echo lib/*.jar | tr ' ' :` com.example.LambdaApplication
这表示包含函数 Bean 的应用程序。com.example.LambdaApplication
将 AWS 中的处理程序名称设置为您的函数的名称。您也可以在此处使用函数组合(例如 )。
这差不多就是全部。将 zip/jar 上传到 AWS 后,您的函数将在自定义运行时中运行。
我们提供了一个示例项目,您还可以在其中了解如何配置 POM 以正确生成 zip 文件。uppercase|reverse
函数式 Bean 定义样式也适用于自定义运行时,并且
比 style 更快。自定义运行时的启动速度甚至比功能性 bean 实现快得多
的 Java lambda 中,这主要取决于运行时需要加载的类的数量。
Spring 在这里没有做太多事情,因此你可以通过在函数中仅使用原始类型来减少冷启动时间,例如,
并且不在自定义初始化器中执行任何工作。@Bean
@PostConstruct
使用自定义运行时的 AWS 函数路由
使用 Custom Runtime 时,Function Routing 的工作方式相同。您只需将函数名称指定为 handler 即可,就像使用函数名称作为 handler 一样。functionRouter
部署 Container 镜像
自定义运行时还负责处理容器映像部署。
当以类似于此处描述的方式部署容器镜像时,请务必
以记住 set 和 environment variable 函数的名称。DEFAULT_HANDLER
例如,对于下面显示的函数 bean,该值将为 。DEFAULT_HANDLER
readMessageFromSQS
@Bean
public Consumer<Message<SQSMessageEvent>> readMessageFromSQS() {
return incomingMessage -> {..}
}
此外,请务必记住确保 tht 也设置为 。这是默认的。spring_cloud_function_web_export_enabled
false
有关 JAR 布局的说明
在 Lambda 中,运行时不需要 Spring Cloud Function Web 或 Stream 适配器,因此您可能需要
在创建发送到 AWS 的 JAR 之前,需要排除这些 JAR。Lambda 应用程序必须
shaded,但 Spring Boot 独立应用程序没有,因此您可以使用 2
单独的罐子(根据
Samples)。示例应用程序创建 2 个 jar 文件,一个带有用于在 Lambda 中部署的分类器,另一个在运行时包含的可执行(精简)jar。Spring Cloud Function 将尝试从 JAR 文件中找到一个 “main class”
manifest,使用属性(将由 Spring Boot 为您添加
工具(如果使用 Starter 父级)。如果您的清单中没有,您可以
在将函数部署到 AWS 时使用环境变量或系统属性。aws
spring-cloud-function-web
Start-Class
Start-Class
MAIN_CLASS
如果您不使用函数式 bean 定义,而是依赖 Spring Boot 的自动配置,则
并且不依赖于 ,
然后,必须将其他转换器配置为 maven-shade-plugin 执行的一部分。spring-boot-starter-parent
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.4</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>aws</shadedClassifierName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
<resource>META-INF/spring.factories</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.components</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
构建文件设置
为了在 AWS Lambda 上运行 Spring Cloud Function 应用程序,您可以利用 Maven 或 Gradle 云平台提供商提供的插件。
Maven 系列
要使用 Maven 的适配器插件,请将插件依赖项添加到您的文件中:pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
</dependency>
</dependencies>
如 JAR 布局说明中所述,您需要一个带阴影的 jar 才能上传它 到 AWS Lambda。为此,您可以使用 Maven Shade 插件。 设置示例可以在上面找到。
您可以使用 Spring Boot Maven 插件生成精简的 jar。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>${wrapper.version}</version>
</dependency>
</dependencies>
</plugin>
您可以找到用于部署 Spring Cloud Function 的完整示例文件
使用 Maven 将应用程序迁移到 AWS Lambda。pom.xml
Gradle
要使用 Gradle 的适配器插件,请将依赖项添加到您的文件中:build.gradle
dependencies {
compile("org.springframework.cloud:spring-cloud-function-adapter-aws:${version}")
}
如 JAR 布局说明中所述,您需要一个带阴影的 jar 才能上传它 到 AWS Lambda。您可以使用 Gradle Shadow 插件来实现:
你可以使用 Spring Boot Gradle Plugin 和 Spring Boot Thin Gradle Plugin 来生成 那个薄罐子。
下面是一个完整的 gradle 文件
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0-M2'
id 'io.spring.dependency-management' version '1.1.3'
id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'maven-publish'
id 'org.springframework.boot.experimental.thin-launcher' version "1.0.31.RELEASE"
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
mavenLocal()
maven { url 'https://repo.spring.io/milestone' }
}
ext {
set('springCloudVersion', "2023.0.0-M1")
}
assemble.dependsOn = [thinJar, shadowJar]
publishing {
publications {
maven(MavenPublication) {
from components.java
versionMapping {
usage('java-api') {
fromResolutionOf('runtimeClasspath')
}
usage('java-runtime') {
fromResolutionResult()
}
}
}
}
}
shadowJar.mustRunAfter thinJar
import com.github.jengelman.gradle.plugins.shadow.transformers.*
shadowJar {
archiveClassifier = 'aws'
manifest {
inheritFrom(project.tasks.thinJar.manifest)
}
// Required for Spring
mergeServiceFiles()
append 'META-INF/spring.handlers'
append 'META-INF/spring.schemas'
append 'META-INF/spring.tooling'
append 'META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports'
append 'META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports'
transform(PropertiesFileTransformer) {
paths = ['META-INF/spring.factories']
mergeStrategy = "append"
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.cloud:spring-cloud-function-adapter-aws'
implementation 'org.springframework.cloud:spring-cloud-function-context'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
tasks.named('test') {
useJUnitPlatform()
}
您可以找到用于部署 Spring Cloud Function 的完整示例文件
使用 Gradle 向 AWS Lambda 的应用程序。build.gradle