使用Java AzureResourceManager异步提交ARM模板的技术疑问
问题描述
我正在编写一个服务,通过Azure Java客户端API提交ARM模板以创建各类Azure资源,示例代码如下:
Mono<Deployment> deploymentMono = arm.deployments() .define(deploymentName) .withNewResourceGroup(resourceGroup, Region.US_WEST2) .withTemplate(templateJson) .withParameters(parametersJson) .withMode(DeploymentMode.INCREMENTAL) .createAsync();
我希望在Azure Functions中运行该服务,但部分部署耗时较长。理想情况下,我希望提交部署后立即从服务器获取成功/错误响应及可用于后续查询状态的ID,但目前在客户端API中仅看到两种选项:
- 使用
create()并阻塞至部署完成(显然不符合需求); - 使用
createAsync()等待事件,但有用的事件只有doOnSubscribe(触发过早)和doOnNext(需等待部署完成才触发)。
我可以调用subscribe()后轮询部署状态:
Deployment deployment = arm.deployments().getByResourceGroup(resourceGroup, deploymentName); if (deployment.provisioningState().equals("Running"))...
但似乎遗漏了某些方法,应该存在一种仅提交ARM模板、获取Azure ResourceManager已接收处理的确认且无需等待完成的方法,对吗?
解决方案
你需要的是**异步提交部署请求并立即获取部署元数据(包括ID)**的方式,Azure Java SDK确实提供了对应的能力,核心是利用beginCreate方法替代create或createAsync:
1. 提交部署并立即获取初始确认
使用beginCreate方法提交部署,该方法会立即返回一个PollerFlux对象,包含ARM已接收部署的初始状态,无需等待部署完成:
PollerFlux<Deployment, Deployment> poller = arm.deployments() .define(deploymentName) .withNewResourceGroup(resourceGroup, Region.US_WEST2) .withTemplate(templateJson) .withParameters(parametersJson) .withMode(DeploymentMode.INCREMENTAL) .beginCreate();
2. 提取部署ID与初始状态
通过poller.first()可以快速获取ARM刚接收部署时的响应,此时就能拿到部署ID和ProvisioningState(通常为Accepted或Running)的确认:
poller.first() .subscribe(initialDeployment -> { String deploymentId = initialDeployment.id(); String provisioningState = initialDeployment.provisioningState(); // 立即返回部署ID给调用方,后续可通过该ID异步跟踪状态 }, error -> { // 处理提交失败的情况,比如模板语法错误、权限不足等 });
3. 后续状态跟踪
如果需要后续监控部署状态,可以保留PollerFlux对象,通过poll()方法定期获取最新状态,或用last()等待部署完成(按需使用):
// 轮询状态示例 poller.poll() .subscribe(latestDeployment -> { String currentState = latestDeployment.provisioningState(); if ("Succeeded".equals(currentState) || "Failed".equals(currentState)) { // 部署完成,处理最终结果 } });
关键说明
createAsync之所以不符合需求,是因为它会等待部署完全结束后才返回最终的Deployment对象;而beginCreate是Azure SDK专为异步长操作设计的模式,既可以快速拿到提交确认,又支持后续的状态跟踪,完全适配Azure Functions这类需要快速响应的场景。
内容的提问来源于stack exchange,提问作者Eric McNeill

