请使用 spring-cloud-function 5.0.1 获取最新稳定版本!spring-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 Function框架的目标之一是提供必要的基础结构元素,以使简单的函数应用程序能够在特定环境中以特定方式进行交互。 简单的函数应用程序(在上下文中或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();
	}
}

It shows a complete Spring Boot application with a function bean defined in it. What’s interesting is that on the surface this is just another boot app, but in the context of AWS Adapter it is also a perfectly valid AWS Lambda application. No other code or configuration is required. All you need to do is package it and deploy it, so let’s look how we can do that.spring-doc.cadn.net.cn

为了简化操作,我们提供了一个可直接构建和部署的示例项目,您可以点击这里进行访问。spring-doc.cadn.net.cn

您只需执行./mvnw clean package即可生成JAR文件。所有必要的Maven插件都已设置好,以生成适用于AWS部署的JAR文件。(有关JAR布局的更多详细信息,请参阅关于JAR布局的说明)。spring-doc.cadn.net.cn

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

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

AWS deploy

这就是全部。保存并使用一些示例数据执行该函数,这些数据对于此函数来说应为一个字符串,函数将对其进行大写并返回。spring-doc.cadn.net.cn

虽然org.springframework.cloud.function.adapter.aws.FunctionInvoker是AWS的通用目的RequestHandler实现,旨在完全隔离您与AWS Lambda API的具体细节,但在某些情况下,您可能需要指定要使用的特定AWS的RequestHandler。下一节将向您解释如何完成这一点。spring-doc.cadn.net.cn

AWS 请求处理器

虽然 AWS Lambda 允许您实现各种 RequestHandlers,但是使用 Spring Cloud Function 就不需要实现任何东西了。相反地,您可以直接使用提供的org.springframework.cloud.function.adapter.aws.FunctionInvoker,它是对 AWS 的 RequestStreamHandler 的实现。
用户在部署函数时只需将其指定为AWS控制台中的“handler”。它将处理大多数情况,包括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>,我们将尝试将传入的流事件转换为Foo的实例。spring-doc.cadn.net.cn

如果事件类型未知或无法确定(例如 Function<?, ?>),我们将尝试将传入的流事件转换为通用的 Mapspring-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网关提供单一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不允许在环境变量名称中使用点.和/或连字符`-`,因此您可以利用boot支持并简单地用下划线替换点,并将连字符转换为驼峰命名法。例如,spring.cloud.function.definition变为spring_cloud_function_definition,而spring.cloud.function.routing-expression变为spring_cloud_function_routingExpressionspring-doc.cadn.net.cn

自定义运行时

您还可以利用 AWS Lambda 的 自定义运行时 功能,而 Spring Cloud Function 提供了所有必要的组件以简化操作。spring-doc.cadn.net.cn

从代码的角度来看,应用程序应该与任何其他Spring Cloud Function应用程序没有区别。您需要做的唯一事情是在zip/jar的根目录下提供一个bootstrap脚本,以运行Spring Boot应用程序,并在创建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

The com.example.LambdaApplication represents your application which contains function beans.spring-doc.cadn.net.cn

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

功能型 Bean 定义风格同样适用于自定义运行时,且比 @Bean 风格更快。即使在 Java Lambda 的功能型 Bean 实现中,自定义运行时的启动速度也可能更快——这主要取决于运行时需要加载的类的数量。Spring 在此处并不做太多操作,因此您可以通过在函数中仅使用基本数据类型(例如),避免在自定义 @PostConstruct 初始化器中执行任何操作,从而减少冷启动时间。spring-doc.cadn.net.cn

AWS 函数路由与自定义运行时

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

部署容器镜像

自定义运行时还负责处理容器映像部署。
当以类似描述在这里的方式部署容器映像时,重要的是记住要设置环境变量 DEFAULT_HANDLER 并使用函数名称。
spring-doc.cadn.net.cn

例如,对于下面所示的功能 Bean,DEFAULT_HANDLER 的值将是 readMessageFromSQSspring-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 适配器,因此在将 JAR 文件发送至 AWS 之前,可能需要排除这些依赖项。Lambda 应用程序必须进行打包(shaded),而 Spring Boot 独立应用程序则不需要,因此您可以使用两个独立的 JAR 文件运行同一应用程序(如示例所示)。该示例应用程序会创建两个 JAR 文件,其中一个包含aws用于在 Lambda 中部署的分类器,以及一个可执行(精简)JAR包,其中包含spring-cloud-function-web在运行时,Spring Cloud Function 将尝试从 JAR 文件的清单(manifest)中为您定位一个“主类”。Start-Class属性(如果您使用Starters父项目,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

为了使用 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 布局说明》(Notes on JAR Layout)中指出的那样,您需要一个“阴影”(shaded)JAR包才能将其上传至 AWS Lambda。您可以使用 Maven Shade Plugin 来完成此操作。上述示例中的 设置 可供参考。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 文件,该文件用于使用 Maven 将 Spring Cloud Function 应用部署到 AWS Lambda:此处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 布局说明中所指出的,您需要一个“阴影”(shaded)JAR 文件才能将其上传到 AWS Lambda。您可以使用Gradle Shadow 插件来实现此目的:spring-doc.cadn.net.cn

您可以使用 Spring Boot Gradle 插件和 Spring Boot Thin Gradle 插件来生成 瘦 JAR 包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 文件,用于使用 Gradle 将 Spring Cloud Function 应用程序部署到 AWS Lambda:此处spring-doc.cadn.net.cn