1. 概述
本教程将深入探讨 Azure Java Functions。Azure Function 是一种无服务器计算服务,能响应来自 Azure 服务或自定义应用的事件触发执行代码。我们可以使用 Python、PowerShell、JavaScript、C# 和 TypeScript 等语言编写事件驱动的代码。
这项特性让自动化工程师能够开发处理各类 Azure 服务事件的程序。Azure Function 提供了无服务器托管环境,无需管理基础设施即可运行代码,从而实现快速部署、自动扩展和轻松维护。
2. 高级应用场景
以下是一些 典型应用场景:
Azure Function 是优秀的无服务器服务,擅长处理来自不同 Azure 服务或自定义应用的事件/数据。此外,我们可以配置函数按特定计划运行,从各种源轮询数据并执行后续处理。自定义应用也可通过 HTTP 协议向 Function App 发送消息。
函数能从事件上下文读取数据,进行转换或增强后发送到目标系统。事件可能是 Blob 存储容器的新文件上传、队列存储的新消息,或 Kafka 流服务中的主题。其他服务也有类似场景。
更重要的是,Azure Event Grid 服务能通过发布-订阅架构集中管理事件。服务可向 Event Grid 发布事件,订阅者应用则消费这些事件。Function App 可消费并处理来自 Event Grid 的事件。
3. 核心概念
编码前需了解 Azure Functions 编程模型的几个关键概念,如绑定和触发器。
部署代码到 Azure Functions 时,必须提供触发方式信息。Azure 根据这些信息调用函数——这就是触发器。**Azure Java Function 库 提供框架,通过注解声明式指定触发器**。
类似地,函数需要触发源的相关数据进行处理,这可通过输入绑定提供。当函数需要向目标系统发送数据时,输出绑定就能派上用场。与触发器不同,绑定是可选的。
假设每当 Blob Storage 上传文件时,需将其内容插入 Cosmos DB 数据库:
- 触发器定义 Blob Storage 的文件上传事件
- 通过触发器获取文件内容
- 输出绑定提供目标 Cosmos DB 信息
- 本质上它也帮助从函数返回数据
后续章节将通过实例阐明这些概念。
4. 前置要求
实际体验 Azure Function 需要:
- 活跃的 Azure 订阅 创建云资源
- 开发环境(推荐 IntelliJ + Azure Toolkit 插件)
虽然插件会自动添加 Maven 依赖,但核心依赖如下:
<dependency>
<groupId>com.microsoft.azure.functions</groupId>
<artifactId>azure-functions-java-library</artifactId>
<version>3.1.0</version>
</dependency>
Azure functions Maven 插件 负责打包部署:
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-functions-maven-plugin</artifactId>
<version>1.24.0</version>
</plugin>
插件配置示例(包含应用设置):
<configuration>
<appName>${functionAppName}</appName>
<resourceGroup>java-functions-group</resourceGroup>
<appServicePlanName>java-functions-app-service-plan</appServicePlanName>
<region>westus</region>
<runtime>
<os>windows</os>
<javaVersion>17</javaVersion>
</runtime>
<appSettings>
<property>
<name>FUNCTIONS_EXTENSION_VERSION</name>
<value>~4</value>
</property>
<property>
<name>AZURE_STORAGE</name>
<value>DefaultEndpointsProtocol=https;AccountName=functiondemosta;AccountKey=guymcrXX..XX;EndpointSuffix=core.windows.net</value>
</property>
</appSettings>
</configuration>
每个触发接口生成的 function.json 定义入口点和绑定:
{
"scriptFile" : "../azure-functions-1.0.0-SNAPSHOT.jar",
"entryPoint" : "com.baeldung.functions.BlobTriggerJava.run",
"bindings" : [ {
"type" : "blobTrigger",
"direction" : "in",
"name" : "content",
"path" : "feeds/{name}.csv",
"dataType" : "binary",
"connection" : "AZURE_STORAGE"
}, {
"type" : "cosmosDB",
"direction" : "out",
"name" : "output",
"databaseName" : "organization",
"containerName" : "employee",
"connection" : "COSMOS_DB"
} ]
}
在 IntelliJ 执行 Maven 目标 clean compile package azure-functions:deploy
即可部署:
⚠️ 部署时会自动创建/更新 Function 服务及相关资源:
5. Azure Function SDK 核心组件
Java 开发主要使用注解声明触发器和绑定。关键触发器包括:
@HttpTrigger
@BlobTrigger
@CosmosDBTrigger
@EventGridTrigger
@TimerTrigger
输入绑定注解(如 @BlobInput
、@CosmosDBInput
)辅助函数访问事件源数据,应用于函数输入参数。
输出绑定注解(如 @BlobOutput
、@CosmosDBOutput
)应用于 OutputBinding<T>
类型参数,用于将数据写入 Blob、Cosmos DB 等目标系统。
常用接口:
ExecutionContext
:访问运行时环境(日志器、调用ID等)HttpRequestMessage<T>
:接收 HTTP 请求HttpResponseMessage.Builder
/HttpResponseMessage<T>
:构建 HTTP 响应OutputBinding<T>
:输出绑定
6. Java 实现实战
6.1. HTTP 请求数据存入存储表
实现接收员工数据并写入 Azure 存储表的函数:
@FunctionName("addEmployee")
@StorageAccount("AZURE_STORAGE")
public HttpResponseMessage run(@HttpTrigger(name = "req", methods = { HttpMethod.POST }, route = "employee/{partitionKey}/{rowKey}",
authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage<Optional<Employee>> empRequest,
@BindingName("partitionKey") String partitionKey,
@BindingName("rowKey") String rowKey,
@TableOutput(name = "data", tableName = "employee") OutputBinding<Employee> employeeOutputBinding,
final ExecutionContext context) {
context.getLogger().info("Received a http request: " + empRequest.getBody().toString());
Employee employee = new Employee(empRequest.getBody().get().getName(),
empRequest.getBody().get().getDepartment(),
empRequest.getBody().get().getSex(),
partitionKey, rowKey);
employeeOutputBinding.setValue(employee);
return empRequest.createResponseBuilder(HttpStatus.OK)
.body("Employee Inserted")
.build();
}
客户端通过 POST 请求触发:https://{Azure Function URL}/api/employee/{partitionKey}/{rowKey}?code={function access key}
请求体为 JSON 格式员工数据,分区键和行键通过路径变量传递。@BindingName
将路径变量绑定到方法参数。
@StorageAccount
指定存储账户连接字符串(配置在应用设置中):
6.2. Blob 数据迁移到 Cosmos DB
实现 Blob 文件上传自动触发函数,将数据写入 Cosmos DB:
@FunctionName("BlobTriggerJava")
@StorageAccount("AZURE_STORAGE")
public void run(
@BlobTrigger(name = "content", path = "feeds/{name}.csv", dataType = "binary") byte[] content,
@BindingName("name") String fileName,
@CosmosDBOutput(name = "output",
databaseName = "organization",
connection = "COSMOS_DB",
containerName = "employee") OutputBinding<List<Employee>> employeeOutputBinding,
final ExecutionContext context) {
context.getLogger().info("Java Blob trigger function processed a blob. Name: " + fileName + "\n Size: " + content.length + " Bytes");
employeeOutputBinding.setValue(getEmployeeList(content));
context.getLogger().info("Processing finished");
}
@BlobTrigger
的 path
属性指定监听的 Blob 文件路径。函数通过 @CosmosDBOutput
注解配置目标 Cosmos DB,连接字符串存储在环境变量 COSMOS_DB
中。
7. 总结
本文系统介绍了 Azure Functions 的 Java 编程模型。框架设计精良且易于理解,但掌握基础故障排查技巧至关重要——当函数触发失败或无法更新目标系统时,需理解 Azure Functions 与存储账户、Application Insight 等配套服务的协作机制。
完整代码示例可在 GitHub 获取。