131. 无服务器平台适配器

除了能够作为独立的 process 运行之外,Spring Cloud Function application 可以适用于运行现有的无服务器平台之一。在项目中有适用于AWS Lambda天蓝Apache OpenWhisk的适配器。 Oracle Fn 平台有自己的 Spring Cloud Function 适配器。并且里夫支持 Java 函数,其本身的Java Function Invoker行为是 Spring Cloud Function jars 的适配器。

131.1 AWS Lambda

AWS适配器使用 Spring Cloud Function 应用程序并将其转换为可在 AWS Lambda 中运行的表单。

131.1.1 简介

适配器有几个可以使用的通用请求处理程序。最通用的是SpringBootStreamHandler,它使用 Spring Boot 提供的 Jackson ObjectMapper来序列化和反序列化 function 中的 objects。还有一个SpringBootRequestHandler可以扩展,并提供输入和输出类型作为类型参数(使 AWS 能够检查 class 并自己进行 JSON 转换)。

如果您的应用程序有多个@Bean类型Function等,那么您可以通过在 AWS 中配置function.name(e.g. 作为FUNCTION_NAME环境变量)来选择要使用的那个。函数从 Spring Cloud FunctionCatalog中提取(首先搜索Function然后搜索Consumer,最后搜索Supplier)。

131.1.2 关于 JAR 布局的注释

在 Lambda 中,您不需要在运行时运行 Spring Cloud Function Web 或 Stream 适配器,因此您可能需要在创建发送给 AWS 的 JAR 之前排除这些适配器。 Lambda application 必须加阴影,但 Spring Boot 独立 application 不会,所以你可以使用 2 个单独的 jars 运行相同的应用程序(根据 sample)。 sample 应用程序创建 2 个 jar files,一个用于在 Lambda 中部署的aws分类器,以及一个在运行时包含spring-cloud-function-web的可执行文件(瘦)jar。 Spring Cloud Function 将尝试使用Start-Class属性从 JAR 文件清单中为您找到“main class”(如果您使用 starter parent,将由 Spring Boot 工具添加)。如果清单中没有Start-Class,则可以在将 function 部署到 AWS 时使用环境变量MAIN_CLASS

131.1.3 上传

spring-cloud-function-samples/function-sample-aws下建立 sample 并将-aws jar 文件上传到 Lambda。处理程序可以是example.Handlerorg.springframework.cloud.function.adapter.aws.SpringBootStreamHandler(class 的 FQN,而不是方法 reference,尽管 Lambda 确实接受方法 references)。

./mvnw -U clean package

使用 AWS 命令 line 工具,它看起来像这样:

aws lambda create-function --function-name Uppercase --role arn:aws:iam::[USERID]:role/service-role/[ROLE] --zip-file fileb://function-sample-aws/target/function-sample-aws-1.0.0.RELEASE-aws.jar --handler org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler --description "Spring Cloud Function Adapter Example" --runtime java8 --region us-east-1 --timeout 30 --memory-size 1024 --publish

AWS sample 中 function 的输入类型是 Foo,其中包含一个名为“value”的 property。所以你需要这个来测试它:

{
  "value": "test"
}

131.1.4 Platfom Specific Features

HTTP 和 API 网关

AWS 有一些 platform-specific 数据类型,包括消息的批处理,这比单独处理每个类型更有效。要使用这些类型,您可以编写一个依赖于这些类型的 function。或者您可以依赖 Spring 从 AWS 类型中提取数据并将其转换为 Spring Message。为此,您告诉 AWS function 是特定的通用处理程序类型(取决于 AWS 服务)并提供类型的 bean,其中ST是您的业务数据类型。如果_B类型有多个 bean,您可能还需要将 Spring Boot property function.name配置为目标 bean 的 name(e.g. 使用FUNCTION_NAME作为环境变量)。

下面列出了受支持的 AWS 服务和通用处理程序类型:

服务AWS 类型通用处理程序
API 网关APIGatewayProxyRequestEvent , APIGatewayProxyResponseEventorg.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler
室壁运动KinesisEventorg.springframework.cloud.function.adapter.aws.SpringBootKinesisEventHandler

例如,要在 API 网关后部署,请在 AWS 命令 line 中使用--handler org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler(通过 UI)并定义Function<Message<Foo>,Message<Bar>>类型Function<Message<Foo>,Message<Bar>>,其中FooBar是 POJO 类型(数据将由 AWS 使用 Jackson 编组和解组) 。

131.2 Azure 功能

天蓝适配器将 Azure framework 中的 Spring Cloud Function context 和 channels function calls 引导到用户函数中,必要时使用 Spring Boot configuration。 Azure Functions 具有相当独特但具有侵入性的编程 model,涉及用户 code 中特定于平台的 annotations。 Spring Cloud Function Azure 适配器交换了这些注释的便利性,以实现 function implementations 的可移植性。您不必使用 annotations 手动编写一些 JSON(至少目前为止)来引导平台调用适配器中的正确方法。

该项目为 Azure 上的 Spring Cloud Function application 提供了一个适配器层。您可以使用Function类型的单个@Bean编写应用程序,如果您正确布置了 JAR 文件,它将可以在 Azure 中部署。

适配器具有可以选择使用的通用 HTTP 请求处理程序。您必须扩展AzureSpringBootRequestHandler,并提供输入和输出类型作为类型参数(使 Azure 能够检查 class 并自行执行 JSON 转换)。

如果您的应用有多个@Bean类型Function等,那么您可以通过配置function.name来选择要使用的那个。这些函数是从 Spring Cloud FunctionCatalog中提取的。

131.2.1 关于 JAR 布局的注释

在 Azure 中运行时不需要 Spring Cloud Function Web,因此您需要在创建部署到 Azure 的 JAR 之前将其排除。 Azure 上的 function application 必须加阴影,但 Spring Boot 独立 application 不会,因此您可以使用 2 个单独的 jars 运行相同的应用程序(根据此处的 sample)。 sample 应用程序创建着色的 jar 文件,其中azure分类器用于在 Azure 中进行部署。

131.2.2 JSON Configuration

Azure 工具需要找到一些 JSON configuration files 来告诉它如何部署和集成 function(e.g. 哪个 Java class 用作入口点,哪个触发器使用)。可以使用 Maven 插件为 non-Spring function 创建那些 files,但是工具在当前形式的适配器中不起作用。 sample 中有一个 example function.json,它将 function 挂钩为 HTTP 端点:

{
  "scriptFile" : "../function-sample-azure-1.0.0.RELEASE-azure.jar",
  "entryPoint" : "example.FooHandler.execute",
  "bindings" : [ {
    "type" : "httpTrigger",
    "name" : "foo",
    "direction" : "in",
    "authLevel" : "anonymous",
    "methods" : [ "get", "post" ]
  }, {
    "type" : "http",
    "name" : "$return",
    "direction" : "out"
  } ],
  "disabled" : false
}

131.2.3 Build

./mvnw -U clean package

131.2.4 运行 sample

您可以在本地运行 sample,就像其他 Spring Cloud Function samples 一样:

curl -H "Content-Type: text/plain" localhost:8080/function -d '{"value": "hello foobar"}'

您将需要az CLI 应用程序和一些 node.js fu(有关详细信息,请参阅https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven)。要在 Azure 运行时上部署 function:

$ az login
$ mvn azure-functions:deploy

在另一个终端试试这个:curl https://<azure-function-url-from-the-log>/api/uppercase -d '{"value": "hello foobar!"}'。请确保您使用上述功能的正确 URL。或者,您可以在 Azure 仪表板 UI 中测试 function(单击 function name,转到右侧并单击“Test”,然后单击右下角的“ Run”)。

Azure sample 中 function 的输入类型是 Foo,其中包含一个名为“value”的 property。因此,您需要使用以下内容对其进行测试:

{
  "value": "foobar"
}

131.3 Apache Openwhisk

OpenWhisk适配器采用可执行的 jar 形式,可以在 docker 镜像中使用,以部署到 Openwhisk。该平台在 request-response 模式下工作,在特定端点上侦听 port 8080,因此适配器是一个简单的 Spring MVC application。

131.3.1 快速入门

实现 POF(务必使用functions包):

package functions;

import java.util.function.Function;

public class Uppercase implements Function<String, String> {

	public String apply(String input) {
		return input.toUpperCase();
	}
}

将其安装到本地 Maven repository 中:

./mvnw clean install

创建一个提供 Maven 坐标的function.properties文件。例如:

dependencies.function: com.example:pof:0.0.1-SNAPSHOT

将 openwhisk runner JAR 复制到工作目录(与 properties 文件相同的目录):

cp spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk/target/spring-cloud-function-adapter-openwhisk-1.0.0.RELEASE.jar runner.jar

使用上面的 properties 文件从 runner JAR 的--thin.dryrun生成 m2 repo:

java -jar -Dthin.root=m2 runner.jar --thin.name=function --thin.dryrun

使用以下 Dockerfile:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY m2 /m2
ADD runner.jar .
ADD function.properties .
ENV JAVA_OPTS=""
ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "runner.jar", "--thin.root=/m2", "--thin.name=function", "--function.name=uppercase"]
EXPOSE 8080

您可以使用 Spring Cloud Function 应用程序,而不仅仅是带有 POF 的 jar,在这种情况下,您必须更改应用程序在容器中运行的方式,以便它将主 class 作为源文件。对于 example,您可以更改上面的ENTRYPOINT并添加--spring.main.sources=com.example.SampleApplication

Build Docker 镜像:

docker build -t [username/appname] .

推动 Docker 镜像:

docker push [username/appname]

使用 OpenWhisk CLI(在vagrant ssh之后 e.g. )创建操作:

wsk action create example --docker [username/appname]

调用动作:

wsk action invoke example --result --param payload foo
{
    "result": "FOO"
}