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

发布于 2024-07-16 17:14:02 字数 3900 浏览 4 评论 0原文

我有一个 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>

[更新]解决方案:

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

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

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

I have a WCF Service and an application with a Service Reference to it, and with the application I have a loop and in each iteration it's making a call to a method in this wcf web-service.

The problem is that after about 9 calls or so, it just stops...and if you hit Pause button of VS, you will see that it's stuck on the line where it makes the call.

After some time waiting for it, this TimeoutException is thrown:

The request channel timed out while
waiting for a reply after
00:00:59.9970000. Increase the timeout
value passed to the call to Request or
increase the SendTimeout value on the
Binding. The time allotted to this
operation may have been a portion of a
longer timeout.


I researched a bit on this, and found some solutions that involved editing the app.config in the application, and here are excerpts of it:

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

.

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

Then, after I stop debugging, after a couple of minutes, an error message pops up telling me that a Catastrophic failure has occurred.

How can I fix this problem? I did not have this issue when I was working with a normal Web Service.


For reference, here is the whole 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>

[Update] Solution:

Apparently, after each request you have to Close the connection...I am now closing the connection after each request and it's working like a charm.

Although what I still can't understand is that in my app.config, I set my maxConcurrentCalls and maxConcurrentSessions to 500, and yet, I can only make 10. Anyone has any answer for that one? (maybe I have something wrong in my app.config posted above)

The answer for the above question (now dashed) is because I was editing the client app.config, not the service config file (web.config)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

归途 2024-07-23 17:14:02

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

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

The default number of allowed concurrent connections is 10.
Most likely your client is not closing the connections.

To increase the number of concurrent calls, you will have to add your behavior to the service configuration, not the client.

幸福丶如此 2024-07-23 17:14:02

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

A call to clientservice.close() will solve the problem.

一袭水袖舞倾城 2024-07-23 17:14:02

这周我遇到了这个问题,但我无法完全弄清楚发生了什么。
实际上,我确实将对服务的调用更改为服务客户端的 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 服务 的引用不可用,但仍在范围内。 因此,这在这方面会更好:

using (IDisposable serviceDisposable = new ServiceClient())
{
     IService service = (IService)serviceDisposable;
}

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

I ran into this problem this week and I wasn't able to quite figure out what was going on.
I actually did change my call to my service to Dispose() the service client, but it didn't seem to have any effect. Apparently, there was another service call lurking somewhere.

What may be interesting to note is what made me decide that this was not the problem: this limit is not related to the actual number of socket connections to the webservice. When you hit the maxConcurrentSessions limit, there is still only one actual socket connection. I was checking this with netstat, which brought me to the wrong conclusion. So, don't confuse sessions with sockets.

We have interfaces defined for all our WCF services, so I'm planning to adapt this pattern in my code now:

IMyService service = new MyServiceClient();
using (service as IDisposable)
{
    service.MyServiceMethod();
}

What's also interesting, is that the problem did not occur for me when the services (and website) were hosted on IIS. The configuration is (almost) identical, yet I could not reproduce this behavior on that machine. I guess that's a good thing :)

@ John Saunders (about variable assignment in using):

I usually do put the variable assignment in the using statement. But the IMyService that's generated is not implicitly convertible to IDisposable. If you really wanted the assignment in there, I suppose the alternative would be:

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

That still leaves the problem of the variable scope being wrong though. The reference to IService service is unusable, but still in scope. So this would be better in that respect:

using (IDisposable serviceDisposable = new ServiceClient())
{
     IService service = (IService)serviceDisposable;
}

That requires me to introduce an extra variable name though. *Meh*

垂暮老矣 2024-07-23 17:14:02

这可以通过创建单例类作为 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();
    }
}

This can be solved by creating singleton class as interface between web service reference and application. Then it will create only one instance of service reference.

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();
    }
}
酷遇一生 2024-07-23 17:14:02

您可以配置跟踪并运行循环吗? 通道可能出现故障并导致客户端超时。

Can you configure tracing and run the loop? It may be that the channel is becoming faulted and causing the client to time out.

清风挽心 2024-07-23 17:14:02

在我对一个很多类似的问题感到烦恼之后,这个问题没有通过 Close()Dispose() 解决,我想添加一个简单的让我开心的解决方案,即增加 ServicePointManager.DefaultConnectionLimit 默认为 2。

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

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

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

After pulling my hairs over a much similar problem that was not solved by either Close() or Dispose() I would like to add a simple solution that made my day, namely by increasing the ServicePointManager.DefaultConnectionLimit which is by default 2.

"The DefaultConnectionLimit property sets the default maximum number of concurrent connections that the ServicePointManager object assigns to the ConnectionLimit property when creating ServicePoint objects."

In my case my application successfully connected to my remote service 2 times, on the third attempt it simply did not try to connect to the service. Instead it waited for a while before timing out with the same error message as in the question above. Increasing DefaultConnectionLimit resolved this. To add to the frustration this behavior was somewhat random - in one case of 10 the webservice was invoked successfully multiple (>2) times.

The solution originates and are further discussed these two threads: wcf-timeout-exception-detailed-investigation and wcf-service-throttling. solved my issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文