【问题标题】:Client-Side CommunicationException while Service works properly服务正常工作时出现客户端通信异常
【发布时间】:2013-03-15 10:27:42
【问题描述】:

目前我面临一个我不明白的问题。我有一个 wcf 客户端,它同时通过多个线程(都在同一台机器上)调用 wcf 服务。有时,我会遇到众所周知的 System.ServiceModel.CommunicationException

"接收对 xxx 的 HTTP 响应时发生错误。这可能是由于服务端点绑定未使用 HTTP 协议。这也可能是由于 HTTP 请求上下文被服务器中止(可能由于服务关闭)。有关更多详细信息,请参阅服务器日志。”

有时它会起作用。如果服务调用成功,这似乎是完全随机的。

请求非常小,它只是一个 (int, bool, enum) 调用。该请求包含约。来自 MSSQL 数据库的 300-500 KB 记录。

我在数百个网站上搜索了解决方案,增加了客户端和服务端的超时值、缓冲区值、请求和响应大小值。如果缺少它们,我添加了 [DataContract] 和 [DataMember] 属性。仍然没有任何变化。

我激活了完全跟踪,只是为了看到一个非常奇怪的行为:

来自客户端的调用因给定异常而在本地停止 - 但服务器处理它们并发送响应,该响应永远不会到达客户端。检查给定跟踪的时间 - 客户端中止,服务器继续。

在跟踪中,我看到了这个图中的重:

请问,谁能帮忙停止这种无休止的搜索?

更新 1:

我上传了 clientserver 配置,也许这​​会有所帮助。

更新 2:

按照 Yahia 的建议,我们为 ConnectionLimit (connection=80) 添加了 config parameter。目前,这似乎解决了问题,但我们仍在尝试重现错误。

更新 3:

该死的。三个小时后,我可以再次看到相同的行为......我们有另一个建议:如您所见,我们在客户端使用quartz.net,从20个线程开始。石英引擎执行的作业连接到我们的服务。现在我试着想象如果 7 个线程同时尝试连接服务会发生什么。

更新 4:

我们已经在注册表和配置中设置了 tcp 参数。重新启动后,完全没有变化:(

这些是注册表更改:

HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters - TcpNumConnections=65534
HKLM\System\CurrentControlSet\Services\Tcpip\Parameters - MaxUserPort=65534
HKCU\Software\Microsoft\Windows\CurrentVersion\Internet 设置 - MaxConnectionsPer1_0Server=20
HKLM\Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_MAXCONNECTIONSPERSERVER - iexplore.exe=20
HKLM\Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_MAXCONNECTIONSPERSERVER - MyClientsExeName.exe=20

更新 5:

更新 6:

[DataContract]
public class Currency
{
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Code { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public ForeignNoteDetails ForeignNoteDetails { get; set; }

    [DataMember]
    public CurrencyRates Rates { get; set; }

    [DataMember]
    public PreciousMetallDetails PreciousMetallDetails { get; set; }

    [DataMember]
    public CurrencyType Type { get; set; }
}

[DataContract]
public class ForeignNoteDetails
{
    [DataMember]
    public double CardholderBillingCurrencyCode { get; set; }

    [DataMember]
    public string Country { get; set; }

    [DataMember]
    public string CountryCode { get; set; }

    [DataMember]
    public int CurrencyUnit { get; set; }

    [DataMember]
    public List<string> Notes { get; set; }
}

[DataContract]
public class CurrencyRates
{
    [DataMember]
    public ExchangeRate PurchaseRate { get; set; }

    [DataMember]
    public ExchangeRate SellRate { get; set; }
}

[DataContract]
public class PreciousMetallDetails
{
    [DataMember]
    public string PreciousMetalType { get; set; }

    [DataMember]
    public double Fineness { get; set; }
}

致电服务:

        protected IEnumerable<Currency> GetCurrencyLevel(int id, bool netRate = true, RatesCalculationSource ratesSource = RatesCalculationSource.ReutersRates)
    {
        return this.calculationClient.GetCurrencyLevel(new RatesCalculationSetting() { CalculationLevelId = id, CalculateGrossRates = !netRate, Soruce = ratesSource });
    }

客户端创建:

protected ICalculationServiceClientService calculationClient = IoC.DependencyManager.Resolve<ICalculationServiceClientService>();

对服务的另一个调用(工作):

this.calculationClient.DistributeTradingOfficeRatesLevels(branchOfficeLevelId, tradingLevelId);

这里定义为

void DistributeTradingOfficeRatesLevels(int branchOfficeRatesLevelId, int tradingOfficeRatesLevelId)

更新 7:

【问题讨论】:

  • 我假设您已经在服务器和客户端绑定上设置了 TransportBindingElement 的 MaxReceivedMessageSize 属性。
  • 您需要全局更改设置(通过注册表)... Quartz.net 可能正在做一些事情,阻止您的配置设置被正确应用(也许他们正在重用线程或类似的)...
  • 非常好 - 我会尝试重现您的问题并在几分钟内通知您。
  • 你能把对象初始化器从调用和测试中分离出来吗? protected IEnumerable GetCurrencyLevel(int id, bool netRate = true, RatesCalculationSource ratesSource = RatesCalculationSource.ReutersRates) { var myObj = new RatesCalculationSetting() { CalculationLevelId = id, CalculateGrossRates = !netRate, Soruce = ratesSource }; var 结果 = this.calculationClient.GetCurrencyLevel(myObj);返回结果; }
  • 您能否显示您在 wcfclient 跟踪中收到的错误消息的详细信息?我的意思是该行的详细信息:“抛出异常”。

标签: c# asp.net .net wcf exception


【解决方案1】:

好的,这就是发生的事情 - 您的网卡出现故障,几个小时后过热,当发生这种情况时,它开始短路,结果您的客户端“认为”服务器已关闭。故事结束 - 100% 确定。我的赏金呢?

顺便说一句:它过热的原因可能是设计不良,尤其是在您使用笔记本电脑时,或者由于其中已经存在损坏。

【讨论】:

  • 我第一次不敢相信,但似乎将url更改为localhost时,网卡被忽略了。在此更改之后,我们没有任何错误 - 现在已经有好几天了。太好了,谢谢!
【解决方案2】:

HTTP 协议定义了同一 Web 服务器的 2 个连接的限制...

由于您使用的是 http,因此您看到的行为可能与该限制有关...

对此有一个 registry setting 和一个 programatic way - 您可能需要增加对客户端的限制(取决于您使用的线程数量)...

其他相关设置(客户端)可以在here找到。

【讨论】:

  • 感谢您的回答。这很有趣 - 我稍后会检查并发布我的结果。
  • 这个限制不能解释为什么有时一个请求出错而没有其他请求正在运行。有什么想法吗?
  • @user2173257 是的,确实如此......因为http连接通常有一些“保持活动时间”(这是可配置的,但在标准IIRC中有一个默认值)它可能仍然是一个干扰客户端(任何应用程序!)和特定服务器之间的任何其他先前连接!
  • 查看我上面的更新编辑。只要这似乎可以解决问题,我就会接受您的好主意作为答案。谢谢!
  • @jgauffin 在RFC 2616 Section 8.1.4 中的最后一句话。
【解决方案3】:

我建议验证 2 点:

  1. 服务器上的Throttling,点赞

    行为名称="节流"
    服务节流
    maxConcurrentCalls="1"
    maxConcurrentSessions="1"
    maxConcurrentInstances="1"

  2. 未关闭 WCF 会话 - 使用后是否关闭所有会话(客户端代理)?
    在我的情况下,当我将所有超时扩大到最大时,我遇到了在 X 调用后服务变得“卡住”的情况。当我更改超时时,我收到了像你一样的异常。

那是几年前的事了,所以我记不太清了。 另外,我记得我找到了一篇很好的文章,描述了如何以及为什么要更改服务实例模式来解决这个(会话)问题。

【讨论】:

  • 感谢您的回答。我会尝试将小跑节点添加到我的行为中。 2.的答案是:没有。因为我们重复使用它们,所以我们不会在每次调用后关闭会话。
  • 我们在我们的行为中添加了 (20 以确保所有线程可以同时行动),但同样,没有变化
【解决方案4】:

尝试在 WCF 端启用跟踪,您将获得有关服务器端发生的情况的详细信息。

当客户端发送大量请求时,有时 WCF 通道工厂会突然关闭。当我们对 WCF 使用证书身份验证时,我们遇到了类似的问题。在这一点上,我们已经围绕这个瞬态错误设置了 RetryPolicy。如果我们得到这个错误,我们会中止通道工厂,重新创建并再次发送,而不是抛出异常。

 while (retryCount <= MAXRETRY)
            {
                try
                {
                    return _proxyService.GetData(); // _proxyService is WCF proxy class
                }
                catch (CommunicationException transientException)
                {
                     if (SLEEPINTERVAL> 0)
                    {
                        Thread.Sleep(SLEEPINTERVAL);
                    }
                    ((IClientChannel) _proxyService).Abort();
                    _proxyService = functionToCreateProxy();
                }

                retryCount++;
            }

【讨论】:

  • 如您所见,wcf 已启用但显示出奇怪的行为。对我来说,重新创建将是“最后一次机会”——我确信在没有解决方法的情况下可以做到这一点——我的客户端一定有问题。
【解决方案5】:

我遇到了同样的问题。就我而言,这是我的错误。我在启动线程后关闭了 channelFactory(代理)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    • 2014-11-07
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多