Deploying a Packaged Function

Spring Cloud Function 提供了一个“deployer”库,允许您使用隔离类加载器启动 jar 文件(或 exploded 存档,或 jar 文件集)并公开其中定义的函数。这是一个非常强大的工具,例如,它可以允许您在不更改目标 jar 文件的情况下,将函数适应各种不同的输入输出适配器。无服务器平台通常内置有这种类型的功能,因此您可以将其视为此类平台中函数调用程序的构建块(事实上, Riff Java 函数调用程序使用此库)。 标准入口点是向类路径添加 spring-cloud-function-deployer,该部署工具将启动并查找一些配置来告诉它在何处查找函数 jar。

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-function-deployer</artifactId>
	<version>${spring.cloud.function.version}</version>
</dependency>

用户至少必须提供一个 spring.cloud.function.location,它是一个包含函数的归档的 URL 或资源位置。它可以选择使用 maven: 前缀通过依赖关系查找来定位工件(有关完整详细信息,请参见 FunctionProperties)。Spring Boot 应用程序使用 MANIFEST.MF 从 jar 文件引导,以找到启动类,因此标准 Spring Boot fat jar 很奏效,例如。如果目标 jar 可以成功启动,则结果是注册在主应用程序的 FunctionCatalog 中的函数。即使函数是在独立类加载器中创建的(默认情况下),也可以通过主应用程序中的代码应用注册的函数。 下面是部署包含 “uppercase” 函数并调用它的 JAR 的示例。

@SpringBootApplication
public class DeployFunctionDemo {

	public static void main(String[] args) {
		ApplicationContext context = SpringApplication.run(DeployFunctionDemo.class,
				"--spring.cloud.function.location=..../target/uppercase-0.0.1-SNAPSHOT.jar",
				"--spring.cloud.function.definition=uppercase");

		FunctionCatalog catalog = context.getBean(FunctionCatalog.class);
		Function<String, String> function = catalog.lookup("uppercase");
		System.out.println(function.apply("hello"));
	}
}

下面是使用 Maven URI 的示例(取自 FunctionDeployerTests 中的一个测试):

@SpringBootApplication
public class DeployFunctionDemo {

	public static void main(String[] args) {
		String[] args = new String[] {
				"--spring.cloud.function.location=maven://oz.demo:demo-uppercase:0.0.1-SNAPSHOT",
				"--spring.cloud.function.function-class=oz.demo.uppercase.MyFunction" };

		ApplicationContext context = SpringApplication.run(DeployerApplication.class, args);
		FunctionCatalog catalog = context.getBean(FunctionCatalog.class);
		Function<String, String> function = catalog.lookup("myFunction");

		assertThat(function.apply("bob")).isEqualTo("BOB");
	}
}

请记住,使用 MavenProperties 的默认值解析了 maven 资源,如本地和远程存储库、用户、密码等,这些默认值有效地使用了本地默认值并适用于大多数情况。但是,如果您需要自定义,则可以简单地提供类型为 MavenProperties 的 bean,您可以在其中设置其他属性(参见以下示例)。

@Bean
public MavenProperties mavenProperties() {
	MavenProperties properties = new MavenProperties();
	properties.setLocalRepository("target/it/");
	return properties;
}

Supported Packaging Scenarios

目前 Spring Cloud Function 支持几种打包方案,以便在部署函数时提供最大的灵活性。

Simple JAR

此打包选项意味着不依赖于与 Spring 相关的任何内容。例如;考虑这样的 JAR 包含以下类:

package function.example;
. . .
public class UpperCaseFunction implements Function<String, String> {
	@Override
	public String apply(String value) {
		return value.toUpperCase();
	}
}

在部署此类程序包时,您只需指定 locationfunction-class 属性:

--spring.cloud.function.location=target/it/simplestjar/target/simplestjar-1.0.0.RELEASE.jar
--spring.cloud.function.function-class=function.example.UpperCaseFunction

在某些情况下,您可能希望将多个函数打包在一起。对于此类方案,您可以使用 spring.cloud.function.function-class 属性,以分号 (;) 为分隔符列出多个类。

例如,

--spring.cloud.function.function-class=function.example.UpperCaseFunction;function.example.ReverseFunction

这里我们正在标识两个要部署的函数,现在我们可以通过名称访问函数目录中的函数(例如,catalog.lookup("reverseFunction");)。

有关更多详细信息,请参阅 here 中提供的完整示例。您还可以在 FunctionDeployerTests 中找到相应的测试。

  • Component Scanning *

从 3.1.4 版本开始,您可以通过 [Function 组件扫描] 中描述的组件扫描功能简化配置。如果您将功能类放在名为 functions 的程序包中,则可以省略 spring.cloud.function.function-class 属性,因为框架将自动发现功能类并将其加载到函数目录中。在执行函数查找时请记住要遵循的命名约定。例如,函数类 functions.UpperCaseFunction 将在 FunctionCatalog 中以 upperCaseFunction 为名提供。

Spring Boot JAR

此打包选项意味着存在对 Spring Boot 的依赖,并且 JAR 已生成为 Spring Boot JAR。也就是说,由于已部署 JAR 在独立类加载器中运行,因此与实际部署程序使用的 Spring Boot 版本不会有任何版本冲突。例如;考虑这样的 JAR 包含以下类(可能有一些额外的 Spring 依赖项,提供 Spring/Spring Boot 在类路径上):

package function.example;
. . .
public class UpperCaseFunction implements Function<String, String> {
	@Override
	public String apply(String value) {
		return value.toUpperCase();
	}
}

与以前一样,在部署此类程序包时,您只需指定 locationfunction-class 属性:

--spring.cloud.function.location=target/it/simplestjar/target/simplestjar-1.0.0.RELEASE.jar
--spring.cloud.function.function-class=function.example.UpperCaseFunction

有关更多详细信息,请参阅 here 中提供的完整示例。您还可以在 FunctionDeployerTests 中找到相应的测试。

Spring Boot Application

此打包选项意味着您的 JAR 是完整的独立 Spring Boot 应用程序,其中函数作为受管的 Spring bean。与以前一样,有一个明显的假设是存在对 Spring Boot 的依赖,并且 JAR 已生成为 Spring Boot JAR。也就是说,由于已部署 JAR 在独立类加载器中运行,因此与实际部署程序使用的 Spring Boot 版本不会有任何版本冲突。例如;考虑这样的 JAR 包含以下类:

package function.example;
. . .
@SpringBootApplication
public class SimpleFunctionAppApplication {

	public static void main(String[] args) {
		SpringApplication.run(SimpleFunctionAppApplication.class, args);
	}

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

鉴于我们实际上正在处理另一个 Spring 应用程序上下文,并且函数是 Spring 管理 bean,除了 location 属性外,我们还指定 definition 属性而不是 function-class

--spring.cloud.function.location=target/it/bootapp/target/bootapp-1.0.0.RELEASE-exec.jar
--spring.cloud.function.definition=uppercase

有关更多详细信息,请参阅 here 中提供的完整示例。您还可以在 FunctionDeployerTests 中找到相应的测试。

此特定部署选项在其类路径上可能有或没有 Spring Cloud Function。从部署人员的角度来看,这并不重要。