WCF 在大约 10 次左右调用后停止响应(限制)

Posted

技术标签:

【中文标题】WCF 在大约 10 次左右调用后停止响应(限制)【英文标题】:WCF stops responding after about 10 or so calls (throttling) 【发布时间】:2010-10-18 20:48:19 【问题描述】:

我有一个 WCF 服务和一个带有对它的服务引用的应用程序,并且对于该应用程序,我有一个循环,并且在每次迭代中它都会调用此 wcf Web 服务中的方法。

问题是在大约 9 次调用之后,它就停止了……如果你点击 VS 的 Pause 按钮,你会看到它卡在它发出调用的线路上。

等待一段时间后,抛出这个TimeoutException

请求通道超时,而 等待回复后 00:00:59.9970000。增加超时 传递给 Request 调用的值或 增加 SendTimeout 值 捆绑。分配给这个的时间 操作可能是一个 更长的超时时间。


我对此进行了一些研究,发现了一些涉及在应用程序中编辑 app.config 的解决方案,以下是其中的摘录:

<serviceBehaviors>
    <behavior name="ThrottlingIssue">
        <serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" />
    </behavior>
</serviceBehaviors>

.

<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" 
 maxArrayLength="2147483647" 
 maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 

然后,在我停止调试后,几分钟后,弹出一条错误消息,告诉我发生了灾难性故障

我该如何解决这个问题?当我使用普通的 Web 服务时,我没有遇到这个问题。


供参考,这里是整个app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="ThrottlingIssue">
                    <serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IDBInteractionGateway" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Windows" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Windows" negotiateServiceCredential="true"
                            algorithmSuite="Default" establishSecurityContext="true" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:28918/DBInteractionGateway.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDBInteractionGateway"
                contract="DBInteraction.IDBInteractionGateway" name="WSHttpBinding_IDBInteractionGateway">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

[更新]解决方案:

显然,每次请求后,您必须Close 连接...我现在在每次请求后关闭连接,它的工作就像一个魅力。

虽然我仍然无法理解的是,在我的 app.config 中,我将 maxConcurrentCalls 和 maxConcurrentSessions 设置为 500,但我只能设置 10。任何人对此都有任何答案? (也许我在上面发布的 app.config 中有问题)

上述问题的答案(现在虚线)是因为我正在编辑客户端app.config,而不是服务配置文件(web.config

【问题讨论】:

过去两天一直在努力解决这个问题,谢谢! 希望我能多次支持这个问题。 我处于完全相同的情况...无法帮助您的帖子解决我的问题,您能看看这个问题吗? ***.com/questions/10305671/… 【参考方案1】:

允许的默认并发连接数为 10。 您的客户端很可能没有关闭连接。

要增加并发调用的数量,您必须将行为添加到服务配置,而不是客户端。

【讨论】:

在我的 app.config 中,我将 maxConcurrentCalls 和 maxConcurrentSessions 设置为 500,但我只能设置 10。我的 app.config 有什么问题吗? 您是否在服务元素上设置了 serviceBehavior 以使用行为配置。 看起来您发布了客户端 app.config ? - 您需要更改服务配置.. 但是我的 WCF 项目中没有 app.config 文件。应该有吗? 允许的并发连接是不够的。他仍然需要关闭连接。【参考方案2】:

调用 clientservice.close() 将解决问题。

【讨论】:

是的,这就是我在解决方案 [更新] 中提到的问题。【参考方案3】:

这周我遇到了这个问题,我无法完全弄清楚发生了什么。 实际上,我确实将对服务的调用更改为服务客户端 Dispose(),但它似乎没有任何效果。显然,在某处潜伏着另一个服务调用。

值得注意的是,是什么让我决定不是问题:这个限制与到 web 服务的实际套接字连接数无关。当您达到maxConcurrentSessions 限制时,仍然只有一个实际的套接字连接。我正在使用netstat 进行检查,这让我得出了错误的结论。所以,不要将会话与套接字混淆

我们为所有 WCF 服务定义了接口,所以我现在计划在我的代码中调整这种模式:

IMyService service = new MyServiceClient();
using (service as IDisposable)

    service.MyServiceMethod();

同样有趣的是,当服务(和网站)托管在 IIS 上时,我并没有出现这个问题。配置(几乎)相同,但我无法在该机器上重现此行为。我想这是件好事:)

@John Saunders(关于using 中的变量赋值):

我通常会将变量赋值放在using 语句中。但是生成的 IMyService 不能隐式转换为IDisposable。如果您真的想要那里的作业,我想替代方案是:

IService service;
using ((service = new ServiceClient()) as IDisposable)


这仍然存在变量作用域错误的问题。对IService service 的引用不可用,但仍在范围内。所以在这方面会更好:

using (IDisposable serviceDisposable = new ServiceClient())

     IService service = (IService)serviceDisposable;

这需要我引入一个额外的变量名。 *嗯*

【讨论】:

为什么不把赋值也放到 using 块中呢? 另见iserviceoriented.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspx。 我通常这样做,但using (IMyService service = new MyServiceClient()) 不起作用(在 using 语句中使用的类型必须隐式转换为 'System.IDisposable')。在using 中进行分配和强制转换对我来说似乎有点混乱。 那篇文章中的委托解决方案有点优雅,但我不确定我上面的代码 sn-p 是否需要这样的解决方案。除非您的应用死机,否则执行在这两行之间不太可能中断? using (var service = new ServiceClient())【参考方案4】:

这可以通过创建单例类作为 Web 服务引用和应用程序之间的接口来解决。然后它将只创建一个服务引用实例。

class ServiceInterface

     private static ServiceInterface  _instance;
     private ServiceClient _service = new ServiceClient ;
     private ServiceInterface()
     
       //Prevent accessing default constructor
     

     public static ServiceInterface GetInstance()
     

     if(_instance == null)

     

      _instance = new ServiceInterface();

    

        return _instance;



 


   // You can add your functions to access web service here

    Public int PerformTask()
    
         return _service.PerformTask();
    

【讨论】:

在每个请求上创建一个客户端比保持单例更健壮。我试过这个方法,如果客户端出现故障(即Status == Fault),那么新的请求就会失败。【参考方案5】:

你能configure tracing 运行循环吗?可能是通道出现故障导致客户端超时。

【讨论】:

【参考方案6】:

在解决了Close()Dispose() 都没有解决的很多 类似问题之后,我想添加一个简单的解决方案,让我很开心,即增加@ 987654321@,默认为 2。

“DefaultConnectionLimit 属性设置 ServicePointManager 对象在创建 ServicePoint 对象时分配给 ConnectionLimit 属性的默认最大并发连接数。”

在我的情况下,我的应用程序成功连接到我的远程服务 2 次,在第三次尝试时它根本没有尝试连接到该服务。相反,它在超时之前等待了一段时间,并出现与上述问题相同的错误消息。增加DefaultConnectionLimit 解决了这个问题。更令人沮丧的是,这种行为有点随机 - 在 10 次的情况下,Web 服务被成功调用了多次 (>2) 次。

解决方案源于这两个线程并进一步讨论:wcf-timeout-exception-detailed-investigation 和wcf-service-throttling。解决了我的问题。

【讨论】:

以上是关于WCF 在大约 10 次左右调用后停止响应(限制)的主要内容,如果未能解决你的问题,请参考以下文章

稳步减慢从 javascript 对 WCF 服务的 ajax 调用

如何限制 WCF 服务的请求执行时间?

WCF服务需要调用异步

构建项目后,WCF 方法被调用 2 次

WCF 调用的 IIS 请求限制回收

对 Async WCF 的所有其他调用都很慢