对于最新的稳定版本,请使用 spring-cloud-function 4.3.0spring-doc.cadn.net.cn

AWS Lambda

AWS 适配器采用 Spring Cloud Function 应用程序,并将其转换为可以在 AWS Lambda 中运行的形式。spring-doc.cadn.net.cn

有关如何开始使用 AWS Lambda 的详细信息超出了本文档的范围,因此期望用户对 AWS 和 AWS Lambda,并希望了解 spring 提供了哪些额外价值。spring-doc.cadn.net.cn

开始

Spring Cloud 函数框架的目标之一是提供必要的基础设施元素,使简单的函数应用程序能够在特定环境中以某种方式进行交互。 简单函数应用程序(在上下文或 Spring 中)是包含 Supplier、Function 或 Consumer 类型的 bean 的应用程序。 因此,对于 AWS,这意味着一个简单的函数 bean 应该以某种方式在 AWS Lambda 环境中被识别和执行。spring-doc.cadn.net.cn

让我们看一下例子:spring-doc.cadn.net.cn

@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 应用程序。没有其他代码或配置 是必需的。您需要做的就是打包并部署它,所以让我们看看如何做到这一点。spring-doc.cadn.net.cn

为了简化作,我们提供了一个可供构建和部署的示例项目,您可以在此处访问它。spring-doc.cadn.net.cn

您只需执行./mvnw clean package生成 JAR 文件。所有必要的 maven 插件都已经设置好,可以生成 适当的 AWS 可部署 JAR 文件。(您可以在 JAR 布局的注释中阅读有关 JAR 布局的更多详细信息)。spring-doc.cadn.net.cn

然后,您必须将 JAR 文件(通过 AWS 控制面板或 AWS CLI)上传到 AWS。spring-doc.cadn.net.cn

当被问及处理程序时,请指定org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest这是一个通用请求处理程序。spring-doc.cadn.net.cn

AWS 部署

就这样。保存并执行带有一些示例数据的函数,对于此函数,这些示例数据应为 字符串,哪个函数将大写并返回。spring-doc.cadn.net.cn

org.springframework.cloud.function.adapter.aws.FunctionInvoker是通用 AWS 的RequestHandler实施旨在完全 将您与 AWS Lambda API 的细节隔离开来,在某些情况下,您可能需要指定哪些特定的 AWSRequestHandler你想要 使用。下一节将向您解释如何实现这一目标。spring-doc.cadn.net.cn

AWS 请求处理程序

虽然 AWS Lambda 允许您实施各种RequestHandlers,使用 Spring Cloud Function,您不需要实现任何,而是使用提供的org.springframework.cloud.function.adapter.aws.FunctionInvoker这是 AWS 的RequestStreamHandler. 用户无需执行任何其他作,只需在 AWS 仪表板上将其指定为“处理程序”即可部署函数。 它将处理大多数情况,包括 Kinesis、流媒体等。spring-doc.cadn.net.cn

如果您的应用有多个@Bean类型Function等,然后您可以通过配置来选择要使用的一种spring.cloud.function.definition属性或环境变量。这些函数是从 Spring Cloud 中提取的FunctionCatalog.如果您未指定spring.cloud.function.definition框架将尝试按照它首先搜索的搜索顺序查找默认值Function然后Consumer最后Supplier).spring-doc.cadn.net.cn

类型转换

Spring Cloud Function 将尝试透明地处理原始 输入流和函数声明的类型。spring-doc.cadn.net.cn

例如,如果您的函数签名是这样的Function<Foo, Bar>我们将尝试将incoming stream 事件转换为Foo.spring-doc.cadn.net.cn

在事件类型未知或无法确定的情况下(例如,Function<?, ?>) 我们将尝试将传入的流事件转换为泛型Map.spring-doc.cadn.net.cn

原始输入

有时您可能希望访问原始输入。在这种情况下,您所需要做的就是声明您的函数签名以接受InputStream. 例如Function<InputStream, ?>. 在这种情况下我们不会尝试任何转换,而是将原始输入直接传递给函数。spring-doc.cadn.net.cn

AWS 函数路由

Spring Cloud Function 的核心特性之一是路由 - 能够根据用户提供的路由指令将一个特殊函数委托给其他函数。spring-doc.cadn.net.cn

在 AWS Lambda 环境中,此功能提供了一个额外的好处,因为它允许您绑定单个函数(路由函数)作为 AWS Lambda,从而成为 API Gateway 的单个 HTTP 端点。因此,最终您只管理一个函数和一个端点,同时受益来自许多可以成为您应用程序一部分的函数。spring-doc.cadn.net.cn

更多详细信息可在提供的示例中找到,但很少有值得一提的一般性事情。spring-doc.cadn.net.cn

默认情况下,只要应用程序中有多个函数,就会启用路由功能,因为org.springframework.cloud.function.adapter.aws.FunctionInvoker无法确定要绑定哪个函数作为 AWS Lambda,因此默认为RoutingFunction. 这意味着您需要做的就是提供路由指令,您可以使用多种机制来完成这些指令(有关更多详细信息,请参阅示例)。spring-doc.cadn.net.cn

另外,请注意,由于 AWS 不允许点.和/或连字符'-',您可以从引导支持中受益,只需将带下划线的点和带驼峰式大小写的连字符替换。所以例如:spring.cloud.function.definition成为spring_cloud_function_definitionspring.cloud.function.routing-expression成为spring_cloud_function_routingExpression.spring-doc.cadn.net.cn

自定义运行时

您还可以受益于 AWS Lambda 的 AWS Lambda 自定义运行时功能Spring Cloud Function 提供了所有必要的组件,使其变得简单。spring-doc.cadn.net.cn

从代码的角度来看,该应用程序看起来应该与任何其他 Spring Cloud Function 应用程序没有什么不同。您唯一需要做的就是提供一个bootstrap运行 Spring Boot 应用程序的 zip/jar 根目录中的脚本。并在 AWS 中创建函数时选择“自定义运行时”。这是一个示例“bootstrap”文件:spring-doc.cadn.net.cn

#!/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

com.example.LambdaApplication表示包含函数 bean 的应用程序。spring-doc.cadn.net.cn

将 AWS 中的处理程序名称设置为函数的名称。您也可以在此处使用函数组合(例如uppercase|reverse). 这几乎就是全部。将 zip/jar 上传到 AWS 后,您的函数将在自定义运行时中运行。我们提供了一个示例项目,您还可以在其中了解如何配置 POM 以正确生成 zip 文件。spring-doc.cadn.net.cn

函数式 bean 定义样式也适用于自定义运行时,并且比@Bean风格。 自定义运行时的启动速度甚至比函数式 bean 实现要快得多- 这主要取决于您需要在运行时加载的类数量。Spring 在这里没有做太多事情,因此您可以通过在函数中仅使用原始类型来减少冷启动时间,例如并且不在自定义中执行任何工作@PostConstruct初始值设定项。spring-doc.cadn.net.cn

使用自定义运行时的 AWS 函数路由

使用自定义运行时函数路由时,其工作方式相同。您只需要指定functionRouter作为 AWS Handler 的方式与使用函数名称作为处理程序的方式相同。spring-doc.cadn.net.cn

部署容器镜像

自定义运行时还负责处理容器映像部署。 以类似于此处描述的方式部署容器映像时,重要的是 记住设置和环境变量DEFAULT_HANDLER替换为函数的名称。spring-doc.cadn.net.cn

例如,对于下面显示的函数 beanDEFAULT_HANDLER值将为readMessageFromSQS.spring-doc.cadn.net.cn

@Bean
public Consumer<Message<SQSMessageEvent>> readMessageFromSQS() {
	return incomingMessage -> {..}
}

此外,重要的是要记住确保spring_cloud_function_web_export_enabled也设置为false.默认情况下是。spring-doc.cadn.net.cn

JAR 布局说明

在 Lambda 中运行时不需要 Spring Cloud Function Web 或 Stream 适配器,因此您可能 在创建发送到 AWS 的 JAR 之前,需要排除这些内容。Lambda 应用程序必须是 shaded,但 Spring Boot 独立应用程序没有,因此您可以使用 2 单独的罐子(根据 Samples)。示例应用创建 2 个 jar 文件,其中一个文件带有aws用于在 Lambda 中部署的分类器,以及一个包含spring-cloud-function-web在运行时。Spring Cloud Function 将尝试从 JAR 文件中为您找到一个“主类” manifest,使用Start-Class属性(将由 Spring Boot 工具(如果使用入门父级)。如果没有Start-Class在您的清单中,您可以 使用环境变量或系统属性MAIN_CLASS当您将函数部署到 AWS 时。spring-doc.cadn.net.cn

如果您没有使用功能 Bean 定义,而是依赖于 Spring Boot 的自动配置, 并且不依赖于spring-boot-starter-parent, 然后必须将其他转换器配置为 maven-shade-plugin 执行的一部分。spring-doc.cadn.net.cn

<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 云平台提供商提供的插件。spring-doc.cadn.net.cn

专家

为了将适配器插件用于 Maven,请将插件依赖项添加到pom.xml文件:spring-doc.cadn.net.cn

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-function-adapter-aws</artifactId>
	</dependency>
</dependencies>

正如 JAR 布局注释中指出的,您需要一个阴影 jar 才能将其上传到 AWS Lambda。为此,您可以使用 Maven Shade 插件。可以在上面找到设置示例。spring-doc.cadn.net.cn

您可以使用 Spring Boot Maven 插件来生成瘦 jarspring-doc.cadn.net.cn

<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>

您可以找到整个示例pom.xml用于部署 Spring Cloud Function 的文件应用程序到 AWS Lambda 和 Maven 点击此处spring-doc.cadn.net.cn

Gradle

要使用 Gradle 的适配器插件,请将依赖项添加到build.gradle文件:spring-doc.cadn.net.cn

dependencies {
	compile("org.springframework.cloud:spring-cloud-function-adapter-aws:${version}")
}

正如 JAR 布局注释中所指出的,您需要一个着色的 jar 才能上传它 到 AWS Lambda。您可以使用 Gradle Shadow 插件spring-doc.cadn.net.cn

您可以使用 Spring Boot Gradle 插件和 Spring Boot Thin Gradle 插件来生成 薄罐子。spring-doc.cadn.net.cn

下面是一个完整的 gradle 文件spring-doc.cadn.net.cn

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()
}

您可以找到整个示例build.gradle用于部署 Spring Cloud Function 的文件 使用 Gradle 向 AWS Lambda 的应用程序,请点击此处spring-doc.cadn.net.cn