Spring Cloud Function 2.0 和 Azure Functions

工程 | Dave Syer | 2018年9月25日 | ...

Spring Cloud Function 自1.0版本以来一直支持Microsoft Azure Functions,但在最新的2.0版本(仍处于里程碑阶段)中,我们决定稍微更改编程模型。本文介绍了这些更改对用户的意义,并简要介绍了这一转变背后的原因。Spring团队在开发过程中与Microsoft团队进行了很多愉快的合作,为我们的用户提供了这两项技术的最佳结合。

适用于 Java 的 Azure Functions

Microsoft 一直以来都为 Azure Functions 提供 Java 支持,这使开发人员能够轻松编写和部署 Java 代码,从而以无服务器方式连接到 Azure 中的各种平台服务(事件、数据库、存储、HTTP 网关等)。它采用基于注解的编程模型,将函数实现置于 Java 方法中。因此,您可以编写一个方法并使用 `@FunctionName` 注解它,它就变成了一个 Azure 函数。它提供了一套丰富的基于 Maven 插件(目前)的工具,可以驱动 Azure 命令行,并用于构建函数、在本地运行和调试函数以及将其部署到云端。Azure 网站上有一个快速入门指南,可以帮助您安装和运行所有先决条件,并且关于 Azure Functions 如何工作的更详细文档可在开发者指南中找到。

这些注解还将函数方法参数和返回类型与部署时使用的服务绑定。例如,如果您想在部署时绑定到 HTTP 网关,可以使用 `@HttpTrigger`。

@FunctionName("uppercase")
public Bar execute(
    @HttpTrigger(name = "req", methods = { HttpMethod.GET, HttpMethod.POST },
        authLevel = AuthorizationLevel.ANONYMOUS) Foo foo,
    ExecutionContext context) {
  return new Bar(foo.getValue());
}

在这个例子中,我们接受传入的 HTTP POST 请求,Azure 将其主体绑定到类型为 `Foo` 的 POJO。我们将 `Foo` 转换为 `Bar`,并将其返回给调用者作为 HTTP 响应。

HTTP 触发器是 Azure Functions 中排名前五的集成方式,但更受欢迎的是基于事件的以及基于存储或数据库的触发器。完整的列表可以在触发器和绑定文档中找到——有一个表格,您可以在其中点击特定的绑定或触发器,它会将您带到参考页面,其中包含所有语言(包括 Java)的代码示例。

这是一个使用 Azure 事件中心作为输入和 Cosmos DB 作为输出的另一个示例。此示例位于github上。

@FunctionName("uppercase")
public Bar execute(
  @EventHubTrigger(name = "data", eventHubName = "events",
        connection = "TRANSACTIONS_EVENT_HUB_CONNECTION_STRING")
    Foo data,
    @CosmosDBOutput(name = "document", databaseName = "inventory",
        collectionName = "messages",
        connectionStringSetting = "PRODUCT_ITEMS_DOCUMENTDB_CONNECTION_STRING",
        createIfNotExists = true)
    OutputBinding<Bar> document,
    final ExecutionContext context) {
  return document.setValue(new Bar(foo.getValue()));
}

注意

如果传入的 JSON 无法转换为函数输入类型(在本例中为 `Foo`),您将看到 Azure 失败并显示令人困惑的 `no such method` 错误。如果您看到这种情况,您可以将 `@FunctionName` 方法更改为 `String` 输入并查看数据,以确保它可以绑定到所需的输入类型。

这些注解通过对环境变量的间接引用来传递连接凭据信息,这些环境变量在函数部署中配置。所有这些操作的配置都在构建 `pom.xml` 中通过 Azure Functions Maven 插件进行。例如

<plugin>
  <groupId>com.microsoft.azure</groupId>
  <artifactId>azure-functions-maven-plugin</artifactId>
  <configuration>
    <resourceGroup>${functionResourceGroup}</resourceGroup>
    <appName>${functionAppName}</appName>
    <region>${functionAppRegion}</region>
    <appSettings>
            <property>
              <name>FUNCTIONS_EXTENSION_VERSION</name>
              <value>beta</value>
            </property>
            <property>
              <name>TRANSACTIONS_EVENT_HUB_CONNECTION_STRING</name>
            <value>${TRANSACTIONS_EVENT_HUB_CONNECTION_STRING}</value>
            </property>
            <property>
              <name>PRODUCT_ITEMS_DOCUMENTDB_CONNECTION_STRING</name>
              <value>${PRODUCT_ITEMS_DOCUMENTDB_CONNECTION_STRING}</value>
            </property>
            <property>
              <name>MSDEPLOY_RENAME_LOCKED_FILES</name>
              <value>1</value>
            </property>
    </appSettings>
  </configuration>
  <executions>
    <execution>
            <id>package-functions</id>
            <goals>
              <goal>package</goal>
            </goals>
    </execution>
  </executions>
</plugin>

在这种情况下,环境变量名称将插件配置链接到函数绑定声明。例如,`@EventHubTrigger` 具有一个 `connection` 属性,该属性将在运行时从 `TRANSACTIONS_EVENT_HUB_CONNECTION_STRING` 环境变量填充。插件使用具有相同名称的本地环境变量(注意 `${}` 占位符)远程配置它,开发人员或 CI 流程负责在运行时设置它。

您自己的连接字符串是机密信息,可以在Azure 仪表板中找到——当您点击相关资源时,通常会看到一个“连接字符串”(或类似的)链接,您可以将其复制粘贴到本地进程(例如,在本地运行但未签入源代码管理的脚本中)。例如,您可以使用这样的 `setup-env.sh` 脚本

export PRODUCT_ITEMS_DOCUMENTDB_CONNECTION_STRING="AccountEndpoint=https://..."
export TRANSACTIONS_EVENT_HUB_CONNECTION_STRING="Endpoint=sb://..."

并在终端会话开始时对其进行引用。

示例中 `pom.xml` 中还有一些其他的插件声明。它们都很重要,但基本上是样板代码——您应该能够复制它们并在所有 Azure 函数应用程序中重复使用相同的配置。

Spring Cloud Function

当应用程序开发人员声明 `java.util.Function` 类型的 Spring bean 时,Spring Cloud Function 旨在支持类似的无服务器用例。在 Azure 上使用 Spring Cloud Function 而不是普通 Java 函数的优势在于,实际的业务逻辑代码(原则上)可移植到其他平台,并且对于现有的 Spring 用户来说是一个熟悉的编程模型。此外,Spring 的所有常用优势都适用:依赖注入以及与许多其他 Java 库的全面集成。

上面两个示例的等效项将是一个 `@Bean`

@Bean
public Function<Foo, Bar> uppercase() {
  return foo -> new Bar(foo.getValue().toUpperCase());
}

在 Spring Cloud Function 1.0 版本中,用户必须手动将 Microsoft 注解映射到 JSON 部署描述符,并将其手动包装到具有平台正确布局的存档中。此过程很脆弱(但独立于 Azure Java 编程模型)。

在 2.0 版本中,这仍然有效,但我们选择更明确地支持 Azure 注解的使用。因此,现在我们有一个基类,应用程序开发人员可以扩展它并使用 Azure 注解进行装饰。上面的示例将完全相同 `@Bean`,并且上面的 `execute` 方法之一将插入到 Spring Cloud 处理程序的子类中。示例

public class UppercaseHandler extends AzureSpringBootRequestHandler<Foo, Bar> {
  @FunctionName("uppercase")
    @HttpTrigger(name = "req", methods = { HttpMethod.GET,
        HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) Foo foo,
    ExecutionContext context) {
  return super.handle(foo, context);
}

请注意,基类 `AzureSpringBootRequestHandler` 是通用的,具有输入和输出类型参数。您必须将输入类型与传入的事件数据匹配,Azure 将使用 Jackson 在 Spring 进行任何操作之前将其以 JSON 格式呈现并转换。基类中有两个实用程序方法,一个(`handle`)返回响应对象,另一个(`handleOutput`)接受 `OutputBinding` 并将其绑定到用户 `Function` 的输出。

注意

基类纯粹是样板代码,仅作为将您的 Spring 函数绑定到无服务器平台服务的外部表示。如果您在其他平台或本地通过 Spring Cloud Function Web 适配器运行,则 Azure 绑定将被忽略。将来可能可以用接口声明替换它——Azure 平台目前不允许这样做,但这是我们正在与 Microsoft 团队一起研究的内容。

有各种配置选项可以驱动 Azure 函数的运行时行为。最重要(也是唯一强制性)的一个是 `MAIN_CLASS`,它是包含 `Function`(或 `Functions`)声明的主要 `@SpringBootApplication` 类。您可以将其指定为环境变量,也可以将其指定为应用程序 jar 清单中的 `Main-Class` 条目。只要您的应用程序具有一个具有精确一个函数的主类,就不需要执行任何其他操作。在示例应用程序中,我们使用清单来定义主类

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <mainClass>example.FunctionApplication</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

如果您的应用程序有多个 `Function` bean,则可以通过 `@FunctionName` 注解将其映射到 Azure 函数——bean 名称(更准确地说是在 `FunctionCatalog` 中的名称)与函数名称匹配。通过这种方式,您可以创建一个 Azure 函数应用程序,这是一个函数组的单个部署工件。如果您愿意,也可以使用任意 `@FunctionName` 并通过环境变量 `FUNCTION_NAME` 或 `application.properties` 中的 `function.name` 配置 Spring Cloud 函数名称。

项目存储库中还有另一个关于如何将 Spring Cloud Function 设置为 Azure 函数的简单示例——这是一个从 Azure 角度来看的 HTTP 触发器,但 Spring Cloud Function 部分非常相似。

注意

如果您本周参加了Spring One Platform,欢迎参加Jeff Hollan(微软)和Oleg Zhurakousky(Pivotal)关于Spring和Azure Functions的演讲

获取Spring新闻简报

关注Spring新闻简报

订阅

领先一步

VMware提供培训和认证,助您快速提升技能。

了解更多

获取支持

Tanzu Spring在一个简单的订阅中提供OpenJDK™、Spring和Apache Tomcat®的支持和二进制文件。

了解更多

即将举行的活动

查看Spring社区中所有即将举行的活动。

查看全部