【问题标题】:Azure Functions Consumption Plan WCF Client Errors "attempt failed because the connected..."Azure Functions 消费计划 WCF 客户端错误“尝试失败,因为已连接...”
【发布时间】:2021-03-25 13:18:07
【问题描述】:

我们最近将基于 azure functions 持久功能的应用从专用的 s1/标准应用服务计划切换到动态 y1 计划以相同的金额,现在我们遇到了一个常见错误:

“连接尝试失败,因为连接方在一段时间后没有正确响应,或者建立连接失败,因为连接的主机没有响应。”

这会在应用运行大约一个小时后发生。异常来自 svcutil 生成的 wcf 客户端。我相当确定这与消费功能应用程序与“专用”应用程序计划的套接字连接限制有关,如https://docs.microsoft.com/en-us/azure/azure-functions/functions-scale#service-limits 所述,但并不完全相信,因为我没有看到日志消息“超出主机阈值:连接" 列于https://docs.microsoft.com/en-us/azure/azure-functions/manage-connections#connection-limit

我们的客户端实际上是围绕十几个 wcf 客户端的包装器,这些客户端在我们的包装器构造上实例化。包装器用 di 注册为单例

builder.Services.AddSingleton<IWrapperClient, OurSoapClient>();

public OurSoapClient(
            IMemoryCache memoryCache,
            IOptions<Options> options,
            ILogger<OurSoapClient> log
        )
        {
            this.options = options.Value;
            this.memoryCache = memoryCache;
            this.log = log;


            this.metaClient = new Meta.MetaWebServiceClient(
                Meta.MetaWebServiceClient.EndpointConfiguration.MetaWebServicePort,
                this.options.MetaHref
            );
            

            this.wmsClient = new Wms.WmsWebServiceClient(
                Wms.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsStageItemsClient = new Wms.Stage.Items.WmsWebServiceClient(
                Wms.Stage.Items.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsReceiptClient = new Wms.Stage.ExpectedReceipts.WmsWebServiceClient(
                Wms.Stage.ExpectedReceipts.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsStageRmaClient = new Wms.Stage.Rma.WmsWebServiceClient(
                Wms.Stage.Rma.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsStageShipmentsClient = new Wms.Stage.Shipments.WmsWebServiceClient(
                Wms.Stage.Shipments.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );


            this.wmsUpdateShipmentsClient = new Wms.Updates.ShippingResults.WmsWebServiceClient(
                Wms.Updates.ShippingResults.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsUpdatesReceivingResultsClient = new Wms.Updates.ReceivingResults.WmsWebServiceClient(
                Wms.Updates.ReceivingResults.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsUpdatesInventoryAdjustmentClient = new Wms.Updates.InventoryAdjustments.WmsWebServiceClient(
                Wms.Updates.InventoryAdjustments.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsInboundOrderClient = new Wms.Inbound.CurrentAndHistory.WmsWebServiceClient(
                Wms.Inbound.CurrentAndHistory.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsOutboundOrderClient = new Wms.Outbound.CurrentAndHistory.WmsWebServiceClient(
                Wms.Outbound.CurrentAndHistory.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsInboundOrderDetailsClient = new Wms.Inbound.CurrentAndHistoryDetails.WmsWebServiceClient(
                Wms.Inbound.CurrentAndHistoryDetails.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );

            this.wmsOutboundOrderDetailsClient = new Wms.Outbound.CurrentAndHistoryDetails.WmsWebServiceClient(
                Wms.Outbound.CurrentAndHistoryDetails.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
                this.options.WmsHref
            );
        }

切换回标准应用服务计划似乎可以消除这种情况。 我相当肯定持久函数不是这里的原因,但只是为了清楚所有对客户端的调用都是从 Orchestrator 或 Activity 函数发生的......我们在两种函数类型中看到相同的失败错误。

我注意到重复的一个轶事是错误似乎发生在第二个 OurWrapperClient 实例化之后(它再次实例化所有 wcf 客户端)......因为它是一个单例,所以它必须是 azure 函数控制平面旋转另一个我的应用实例

有几个问题:

  1. 知道如何证明这是与最大出站连接数相关的问题吗?
  2. 关于这成为问题的原因的任何建议
  3. 假设这与 WCF 有关
    1. 使用 wcf 客户端的正确方法是什么,是否应该使用 usings 为每个调用实例化它们,还是可以像我们一样在每个包装器客户端实例化一次,然后只释放一次?
    2. 我们是否应该使用 DI 将它们实例化为单例,然后注入它们?这意味着我相信 DI 会调用 Dispose
    3. 有什么方法可以将要使用的http 客户端传递给wcf 客户端生成的代码?许多 azure 函数最佳实践都说为所有 http I/O 注入一个 http 客户端,但我不知道如何使用 WCF 做到这一点。

【问题讨论】:

  • 这个问题的错误和你的一样,你可以看看:stackoverflow.com/questions/17693353/…
  • @TheobaldDu thx 但我的差异导致它不是立即的,只有在一段时间(〜小时)后它才会开始发生
  • MS 支持工单得出的结论是,分配给我的网络空间与我的目标存在通信问题,切换到不同的网络空间似乎可以解决问题

标签: wcf .net-core azure-functions wcf-client azure-durable-functions


【解决方案1】:

使用应用洞察力,我注意到大约需要一个小时的时间对应于我的应用在那个时候切换主机实例。最终我开始看到它在部署时会立即失败..即有一个“坏”主机。打开了一个 MS 支持案例,他们远程访问了一个错误的实例,发现他们无法从该主机进行 TCP ping。

您分配的每个网络空间都从 IP 池发出请求,我怀疑我的目标 WAF 出于某种原因阻止了其中一些 IP。切换到保证新网络空间的新区域(它们是在创建时分配的,但特定于区域)使问题消失了。

在此期间确实找到了https://github.com/dotnet/runtime/issues/35508,看起来很相似

【讨论】:

    猜你喜欢
    • 2022-01-24
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多