Microsoft Azure Functions
Azure 函数适配器,用于将 Spring Cloud Function
应用程序部署为原生 Azure Java 函数。
Azure Functions
的 编程模型 很大程度上依赖于 Java 注解 来定义函数的处理程序方法及其输入和输出类型。在编译时,提供的 Azure Maven/Gradle 插件会处理带注解的类,以生成必要的 Azure 函数绑定文件、配置和包工件。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 适配器
提供 Spring
和 Spring Cloud Function
对 Azure Functions 的集成。
依赖项
为了启用 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 工作器集成。 |
开发指南
使用 @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 框架会将其视为自动检测和类路径扫描的候选对象。 |
2 | 自动连接在 HttpTriggerDemoApplication (如下所示)中定义的 uppercase 和 functionCatalog bean。 |
3 | @FunctionName 注解标识指定的 Azure 函数处理程序。当由触发器(例如 @HttpTrigger )调用时,函数会处理该触发器以及任何其他输入,以生成一个或多个输出。 |
4 | plainBean 方法处理程序映射到一个 Azure 函数,该函数使用自动连接的 uppercase Spring bean 来计算结果。它演示了如何在 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 函数!
要利用 Spring Cloud Function 并访问规范函数表示形式,您需要自动连接 FunctionCatalog
并在处理程序中使用它,例如上面 springCloudFunction()
处理程序中的 functionCatalog
实例。
访问 Azure ExecutionContext
有时需要以 com.microsoft.azure.functions.ExecutionContext
的形式访问 Azure 运行时提供的目标执行上下文。例如,此类需求之一是日志记录,以便它可以显示在 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 实用程序将 context 内联为消息标头,使用 AzureFunctionUtil.EXECUTION_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-plugins]] === 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 适配器可以使用 HttpTrigger 在内部部署任何 Spring Web 应用程序作为原生 Azure 函数。它隐藏了 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 的自述文件和代码。