使用Azure SDK创建Private Endpoint时遇请求解析错误
问题解决:Azure Java SDK创建Private Endpoint报InvalidRequestFormat错误
环境配置
OS: MacOS with Apple chip IDE: IntelliJ 2022.3.2 Libraries: implementation group: 'com.azure', name: 'azure-core', version: '1.28.0' implementation group: 'com.azure', name: 'azure-identity', version: '1.5.1' implementation group: 'com.azure', name: 'azure-core-management', version: '1.10.1' implementation group: 'com.azure', name: 'azure-resourcemanager', version: '2.23.0'
问题现象
创建Private Endpoint时触发400错误,异常信息如下:
Exception in thread "main" com.azure.resourcemanager.network.models.ErrorException: Status code 400, "{\n \"error\": {\n \"code\": \"InvalidRequestFormat\",\n \"message\": \"Cannot parse the request.\",\n \"details\": []\n }\n}\": Cannot parse the request. at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:710) at com.azure.core.http.rest.ResponseExceptionConstructorCache.invoke(ResponseExceptionConstructorCache.java:56) at com.azure.core.http.rest.RestProxy.instantiateUnexpectedException(RestProxy.java:439) at com.azure.core.http.rest.RestProxy.lambda$ensureExpectedStatus$2(RestProxy.java:393) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:113) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:160) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onComplete(MonoFlatMapMany.java:260) at reactor.core.publisher.FluxIterable$IterableSubscription.fastPath(FluxIterable.java:362) at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:227) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribeInner(MonoFlatMapMany.java:150) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onSubscribe(MonoFlatMapMany.java:245) at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) at reactor.core.publisher.Flux.subscribe(Flux.java:8466) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:195) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) at reactor.core.publisher.MonoCacheTime.subscribeOrReturn(MonoCacheTime.java:151) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.complete(MonoIgnoreThen.java:292) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onNext(MonoIgnoreThen.java:187) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:160) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onComplete(MonoFlatMapMany.java:260) at reactor.core.publisher.FluxIterable$IterableSubscription.fastPath(FluxIterable.java:362) at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:227) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribeInner(MonoFlatMapMany.java:150) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onSubscribe(MonoFlatMapMany.java:245) at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) at reactor.core.publisher.Flux.subscribe(Flux.java:8466) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:195) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.signalCached(MonoCacheTime.java:337) at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.onNext(MonoCacheTime.java:354) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:129) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onComplete(FluxDoFinally.java:128) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onComplete(FluxDoFinally.java:128) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:400) at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:419) at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:473) at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:702) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:113) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1373) at io.netty.handler.ssl.SslHandler.decodeNonJdkCompatible(SslHandler.java:1247) at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1287) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:468) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:829) Suppressed: java.lang.Exception: #block terminated with an error at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99) at reactor.core.publisher.Mono.block(Mono.java:1707)
所用代码
public static void createPrivateEndpoint(com.azure.resourcemanager.AzureResourceManager azure) { PrivateEndpointInner privateEndpointInner = new PrivateEndpointInner() .withLocation("eastus") .withSubnet( new SubnetInner() .withId( "/subscriptions/valid_subscription_ID/resourceGroups/valid_resource_group/providers/Microsoft.Network/virtualNetworks/valid_vnet/subnets/valid_subnet")) .withPrivateLinkServiceConnections( Arrays .asList( new PrivateLinkServiceConnection() .withPrivateLinkServiceId( "/subscriptions/valid_subscription_ID/resourceGroups/valid_resource_group/providers/Microsoft.Network/privateLinkServices/valid_private_link_service") )); azure.networks().manager().serviceClient().getPrivateEndpoints().createOrUpdate( "valid_resource_group_name", "valid_private_endpoint_name", privateEndpointInner, Context.NONE); }
问题原因与修复方案
问题出在PrivateLinkServiceConnection的配置上——你遗漏了必填的groupIds参数。Azure要求创建Private Endpoint时,必须明确指定要连接的Private Link Service对应的资源组ID(Group ID),门户和CLI会自动填充或引导选择该参数,但Java SDK需要显式设置。
修改后的代码如下,添加withGroupIds方法指定Group ID(通常Private Link Service的Group ID为pls,也可以从Azure门户的Private Link Service详情页获取准确值):
public static void createPrivateEndpoint(com.azure.resourcemanager.AzureResourceManager azure) { PrivateEndpointInner privateEndpointInner = new PrivateEndpointInner() .withLocation("eastus") .withSubnet( new SubnetInner() .withId( "/subscriptions/valid_subscription_ID/resourceGroups/valid_resource_group/providers/Microsoft.Network/virtualNetworks/valid_vnet/subnets/valid_subnet")) .withPrivateLinkServiceConnections( Arrays.asList( new PrivateLinkServiceConnection() .withPrivateLinkServiceId( "/subscriptions/valid_subscription_ID/resourceGroups/valid_resource_group/providers/Microsoft.Network/privateLinkServices/valid_private_link_service") .withGroupIds(Collections.singletonList("pls")) // 新增该行,替换为实际Group ID )); azure.networks().manager().serviceClient().getPrivateEndpoints().createOrUpdate( "valid_resource_group_name", "valid_private_endpoint_name", privateEndpointInner, Context.NONE); }
另外建议将Azure Resource Manager SDK升级至最新稳定版本,旧版本可能存在请求序列化的兼容问题,新版本通常会修复这类细节问题。
内容的提问来源于stack exchange,提问作者ADITHYA AR
相关产品推荐
相关产品推荐

