Microsoft Azure Functions
Azure 函数适配器,用于将 Spring Cloud Function 应用程序作为原生 Azure Java 函数部署。
Azure Functions 编程模型 大量依赖 Java 注解 来定义函数的处理方法及其输入和输出类型。在编译时,Azure Maven/Gradle 插件会处理带注解的类,以生成必要的 Azure Function 绑定文件、配置和打包工件。Azure 注解只是一种类型安全的方式,用于配置您的 Java 函数,使其被识别为 Azure 函数。
spring-cloud-function-adapter-azure 扩展了基本编程模型,以提供 Spring 和 Spring Cloud Function 支持。通过该适配器,您可以使用依赖注入构建 Spring Cloud Function 应用程序,然后将必要的服务自动装配到您的 Azure 处理方法中。
对于基于 Web 的函数应用程序,您可以用专门的 spring-cloud-function-adapter-azure-web 替换通用的 adapter-azure。使用 Azure Web 适配器,您可以将任何 Spring Web 应用程序部署为 Azure HttpTrigger 函数。此适配器隐藏了 Azure 注解的复杂性,而是使用熟悉的 Spring Web 编程模型。有关更多信息,请参阅下面的 Azure Web 适配器 部分。 |
Azure 适配器
为 Azure Functions 提供 Spring 和 Spring Cloud Function 集成。
依赖项
为了启用 Azure Function 集成,请将 Azure 适配器依赖项添加到您的 pom.xml 或 build.gradle 文件中
-
Maven
-
Gradle
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-azure</artifactId>
</dependency>
</dependencies>
dependencies {
implementation 'org.springframework.cloud:spring-cloud-function-adapter-azure'
}
需要 4.0.0+ 版本。类路径中存在适配器会激活 Azure Java Worker 集成。 |
开发指南
使用 @Component (或 @Service) 注解将任何现有 Azure Function 类(例如,带有 @FunctionName 处理程序)转换为 Spring 组件。然后,您可以自动装配所需的依赖项(或 函数目录 以进行 Spring Cloud Function 组合),并在 Azure 函数处理程序中使用它们。
@Component (1)
public class MyAzureFunction {
// Plain Spring bean - not a Spring Cloud Functions!
@Autowired private Function<String, String> uppercase; (2)
// The FunctionCatalog leverages the Spring Cloud Function framework.
@Autowired private FunctionCatalog functionCatalog; (2)
@FunctionName("spring") (3)
public String plainBean( (4)
@HttpTrigger(name = "req",
methods = { HttpMethod.POST },
authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
ExecutionContext context) {
return this.uppercase.apply(request.getBody().get());
}
@FunctionName("scf") (3)
public String springCloudFunction( (5)
@HttpTrigger(name = "req",
methods = { HttpMethod.POST },
authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
ExecutionContext context) {
// Use SCF composition. Composed functions are not just spring beans but SCF such.
Function composed = this.functionCatalog.lookup("reverse|uppercase"); (6)
return (String) composed.apply(request.getBody().get());
}
}
| 1 | 表示 MyAzureFunction 类是一个“组件”,Spring Framework 会将其视为自动检测和类路径扫描的候选。 |
| 2 | 自动装配在 HttpTriggerDemoApplication(下文)中定义的 uppercase 和 functionCatalog bean。 |
| 3 | @FunctionName 注解标识指定的 Azure 函数处理程序。当由触发器(如 @HttpTrigger)调用时,函数会处理该触发器以及任何其他输入,以产生一个或多个输出。 |
| 4 | plainBean 方法处理程序映射到使用自动装配的 uppercase Spring bean 计算结果的 Azure 函数。它演示了如何在 Azure 处理程序中使用“普通”Spring 组件。 |
| 5 | springCloudFunction 方法处理程序映射到另一个 Azure 函数,该函数使用自动装配的 FunctionCatalog 实例计算结果。 |
| 6 | 展示了如何利用 Spring Cloud Function 函数目录 组合 API。 |
| 使用 com.microsoft.azure.functions.annotation.* 包中包含的 Java 注解将输入和输出绑定到您的方法。 |
Azure 处理程序内部使用的业务逻辑实现看起来像一个普通的 Spring 应用程序
@SpringBootApplication (1)
public class HttpTriggerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(HttpTriggerDemoApplication.class, args);
}
@Bean
public Function<String, String> uppercase() { (2)
return payload -> payload.toUpperCase();
}
@Bean
public Function<String, String> reverse() { (2)
return payload -> new StringBuilder(payload).reverse().toString();
}
}
| 1 | 带 @SpringBootApplication 注解的类用作 Main-Class,如 主类配置 中所述。 |
| 2 | 在 Azure 函数处理程序中自动装配和使用的函数。 |
函数目录
Spring Cloud Function 支持用户定义函数的各种类型签名,同时提供一致的执行模型。为此,它使用 函数目录 将所有用户定义函数转换为规范表示。
Azure 适配器可以自动装配任何 Spring 组件,例如上面的 uppercase。但是,这些组件被视为普通 Java 类实例,而不是规范的 Spring Cloud Functions!
要利用 Spring Cloud Function 并访问规范函数表示,您需要自动装配 FunctionCatalog 并在处理程序中使用它,就像上面的 springCloudFunction() 处理程序中的 functionCatalog 实例一样。
访问 Azure ExecutionContext
有时需要访问 Azure 运行时提供的目标执行上下文,其形式为 com.microsoft.azure.functions.ExecutionContext。例如,其中一个需求是日志记录,以便它可以显示在 Azure 控制台中。
为此,AzureFunctionUtil.enhanceInputIfNecessary 允许您将 ExecutionContext 实例添加为消息头,以便您可以通过 executionContext 键检索它。
@FunctionName("myfunction")
public String execute(
@HttpTrigger(name = "req",
methods = { HttpMethod.POST },
authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
ExecutionContext context) {
Message message =
(Message) AzureFunctionUtil.enhanceInputIfNecessary(request.getBody().get(), context); (1)
return this.uppercase.apply(message);
}
| 1 | 利用 AzureFunctionUtil 工具,使用 AzureFunctionUtil.EXECUTION_CONTEXT 头键将 context 内联为消息头。 |
现在您可以从消息头中检索 ExecutionContext
@Bean
public Function<Message<String>, String> uppercase(JsonMapper mapper) {
return message -> {
String value = message.getPayload();
ExecutionContext context =
(ExecutionContext) message.getHeaders().get(AzureFunctionUtil.EXECUTION_CONTEXT); (1)
. . .
}
}
| 1 | 从头中检索 ExecutionContext 实例。 |
配置
要在 Microsoft Azure 上运行您的函数应用程序,您必须提供必要的配置,例如 function.json 和 host.json,并遵守强制性的 打包格式。
通常,Azure Maven(或 Gradle)插件用于从带注解的类生成必要的配置并生成所需的包格式。
Azure 打包格式 与默认的 Spring Boot 打包(例如 uber jar)不兼容。下面的 禁用 Spring Boot 插件 部分解释了如何处理此问题。 |
Azure Maven/Gradle 插件
-
Maven
-
Gradle
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-functions-maven-plugin</artifactId>
<version>1.22.0 or higher</version>
<configuration>
<appName>YOUR-AZURE-FUNCTION-APP-NAME</appName>
<resourceGroup>YOUR-AZURE-FUNCTION-RESOURCE-GROUP</resourceGroup>
<region>YOUR-AZURE-FUNCTION-APP-REGION</region>
<appServicePlanName>YOUR-AZURE-FUNCTION-APP-SERVICE-PLANE-NAME</appServicePlanName>
<pricingTier>YOUR-AZURE-FUNCTION-PRICING-TIER</pricingTier>
<hostJson>${project.basedir}/src/main/resources/host.json</hostJson>
<runtime>
<os>linux</os>
<javaVersion>11</javaVersion>
</runtime>
<appSettings>
<property>
<name>FUNCTIONS_EXTENSION_VERSION</name>
<value>~4</value>
</property>
</appSettings>
</configuration>
<executions>
<execution>
<id>package-functions</id>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
plugins {
id "com.microsoft.azure.azurefunctions" version "1.11.0"
// ...
}
apply plugin: "com.microsoft.azure.azurefunctions"
azurefunctions {
appName = 'YOUR-AZURE-FUNCTION-APP-NAME'
resourceGroup = 'YOUR-AZURE-FUNCTION-RESOURCE-GROUP'
region = 'YOUR-AZURE-FUNCTION-APP-REGION'
appServicePlanName = 'YOUR-AZURE-FUNCTION-APP-SERVICE-PLANE-NAME'
pricingTier = 'YOUR-AZURE-FUNCTION-APP-SERVICE-PLANE-NAME'
runtime {
os = 'linux'
javaVersion = '11'
}
auth {
type = 'azure_cli'
}
appSettings {
FUNCTIONS_EXTENSION_VERSION = '~4'
}
// Uncomment to enable local debug
// localDebug = "transport=dt_socket,server=y,suspend=n,address=5005"
}
禁用 Spring Boot 插件
不出所料,Azure Functions 在 Azure 执行运行时中运行,而不是在 SpringBoot 运行时中运行!此外,Azure 期望由 Azure Maven/Gradle 插件生成的特定打包格式,该格式与默认的 Spring Boot 打包不兼容。
您必须禁用 SpringBoot Maven/Gradle 插件,或者使用 Spring Boot Thin Launcher,如以下 Maven 代码片段所示
<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>
</dependency>
</dependencies>
</plugin>
主类配置
指定 Main-Class/Start-Class 指向您的 Spring 应用程序入口点,例如上面示例中的 HttpTriggerDemoApplication 类。
您可以使用 Maven 的 start-class 属性或设置 MANIFEST/META-INFO 的 Main-Class 属性
-
Maven
-
Gradle
<properties>
<start-class>YOUR APP MAIN CLASS</start-class>
...
</properties>
jar {
manifest {
attributes(
"Main-Class": "YOUR-APP-MAIN-CLASS"
)
}
}
或者,您可以使用 MAIN_CLASS 环境变量明确设置类名。对于本地运行,将 MAIN_CLASS 变量添加到您的 local.settings.json 文件中;对于 Azure 门户部署,在 应用程序设置 中设置该变量。 |
如果未设置 MAIN_CLASS 变量,Azure 适配器将查找类路径上找到的 JAR 包中的 MANIFEST/META-INFO 属性,并选择第一个带有 @SpringBootApplication 或 @SpringBootConfiguration 注解的 Main-Class:。 |
元数据配置
您可以使用共享的 host.json 文件来配置函数应用。
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
host.json 元数据文件包含影响函数应用程序实例中所有函数的配置选项。
如果文件不在项目顶层文件夹中,您需要相应地配置您的插件(例如 hostJson maven 属性)。 |
Azure Web 适配器
对于纯粹基于 Web 的函数应用程序,您可以用专门的 spring-cloud-function-adapter-azure-web 替换通用的 adapter-azure。Azure Web 适配器可以将任何 Spring Web 应用程序作为原生 Azure 函数部署,内部使用 HttpTrigger。它隐藏了 Azure 注解的复杂性,并依赖于熟悉的 Spring Web 编程模型。
要启用 Azure Web 适配器,请将适配器依赖项添加到您的 pom.xml 或 build.gradle 文件中
-
Maven
-
Gradle
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-azure-web</artifactId>
</dependency>
</dependencies>
dependencies {
implementation 'org.springframework.cloud:spring-cloud-function-adapter-azure-web'
}
本地运行
要在 Azure Functions 上本地运行,并部署到您的实时 Azure 环境,您需要安装 Azure Functions Core Tools 以及 Azure CLI(请参阅 此处)。对于某些配置,您还需要 Azurite 模拟器。
然后运行示例
-
Maven
-
Gradle
./mvnw azure-functions:run
./gradlew azureFunctionsRun
在 Azure 上运行
确保您已登录您的 Azure 帐户。
az login
并部署
-
Maven
-
Gradle
./mvnw azure-functions:deploy
./gradlew azureFunctionsDeploy
本地调试
以调试模式运行函数。
-
Maven
-
Gradle
./mvnw azure-functions:run -DenableDebug
// If you want to debug your functions, please add the following line
// to the azurefunctions section of your build.gradle.
azurefunctions {
...
localDebug = "transport=dt_socket,server=y,suspend=n,address=5005"
}
或者,将 JAVA_OPTS 值添加到您的 local.settings.json,如下所示
{
"IsEncrypted": false,
"Values": {
...
"FUNCTIONS_WORKER_RUNTIME": "java",
"JAVA_OPTS": "-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=127.0.0.1:5005"
}
}
这是一个 VSCode 远程调试配置的代码片段
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Attach to Remote Program",
"request": "attach",
"hostName": "localhost",
"port": "5005"
},
]
}
FunctionInvoker (已弃用)
传统的 FunctionInvoker 编程模型已弃用,将来将不再支持。 |
有关函数集成方法的更多文档和示例,请参阅 azure-sample README 和代码。