为啥我的 WCF 服务一次只处理 3 个并行请求?

Posted

技术标签:

【中文标题】为啥我的 WCF 服务一次只处理 3 个并行请求?【英文标题】:Why is my WCF service only processing 3 parallel requests at a time?为什么我的 WCF 服务一次只处理 3 个并行请求? 【发布时间】:2019-01-18 16:17:51 【问题描述】:

我有一个 WPF 应用程序做一些非常简单的事情。我只是让它触发4 对基本@9​​87654323@ 的请求。

private async Task MultipleWcfCalls()

    ServiceReference.Service1Client _proxy = new ServiceReference.Service1Client();
    _proxy.Open();
    var t1 = _proxy.GetDataAsync(0);
    var t2 = _proxy.GetDataAsync(0);
    var t3 = _proxy.GetDataAsync(0);
    var t4 = _proxy.GetDataAsync(0);
    await Task.WhenAll(t1, t2, t3, t4);

我的服务是做经典的Task.Delay(3000)

public async Task<string> GetDataAsync(int value)

    int other = 0;
    int workerThreadsAvail = 0;
    ThreadPool.GetMinThreads(out workerThreadsAvail, out other);
    await Task.Delay(3000);

    return workerThreadsAvail.ToString();

我希望4 请求被触发,而3 秒后,我希望所有四个请求都返回。嗯,实际发生的情况是所有四个请求都通过网络发送,前三个请求将返回,然后最后一个请求将在之后返回 3

节流

起初我以为这是我的问题。好吧,我添加了&lt;serviceThrottling maxConcurrentCalls="10"/&gt; int 我的web.config 并没有任何区别。所以,然后我读到它可能是我使用代理达到的连接限制,所以我将ServicePointManager.DefaultConnectionLimit=10; 添加到我的 WPF 应用程序中。

线程饥饿

然后,我不断遇到线程饥饿。因此,作为一个测试,我尝试将最小线程数设置为20,以确保我有足够的速度来处理4 请求。我将此添加到我的 WPF 应用程序ThreadPool.SetMinThreads(20, 20);。因此,为了确认有大量工作线程可用于处理请求,我决定让我的服务调用在进程开始时返回可用线程的数量。每个请求都返回1920

使用 Fiddler,我可以确认所有 4 请求都已从 WPF(客户端)应用程序通过网络发送。现在,我的 Wcf 正在使用 basicHttpBinding,所以它在 Per Call 实例模式下运行,所以并发模式应该无关紧要,但为了安全起见,我添加了 [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]

我已经使用System.Diagnostics.XmlWriterTraceListener 进行了一些堆栈跟踪,我可以确认我收到了3 请求同时记录(几乎),然后第四个请求在 3 秒后被记录。

Wcf 托管在IIS。如果需要更多信息,请告诉我,我会尽快添加。

根据要求,这是我的 WCF 界面。

namespace SampleWCF

    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IService1
    

        [OperationContract]
        System.Threading.Tasks.Task<string> GetData(int value);
    

【问题讨论】:

这是否与处理器中的核心有关,quad = 4, 4-1 = 3 thread。 @AnirudhaGupta 我不太了解这些东西,但我相信我在六核处理器上运行。 如果在 WCF 代码中执行 await Task.Delay(3000).ConfigureAwait(false) 是否相同?你能检查一下那里是否有任何同步上下文(SynchronizationContext.Current?.GetType()?.Name)吗? 另外请注意,WCF 和 WPF 中的异步是完全独立的——您可以调用同步的异步方法,反之亦然。所以忽略 WPF 部分,这都是关于 WCF 的。 @James,从您对 cme​​ts 的回答来看,很明显这是特定于您的 IIS 配置的。很难在无法复制的情况下进一步发展。我建议您尝试WorkerThreadPoolBehavior 并确保服务在其自己的 IIS 应用程序池中运行。这是另一篇有用的 MSKB 文章,用于进一步排除故障:Contention, poor performance, and deadlocks when you make calls to Web services from an ASP.NET application。如果您找到它,请发布您自己的答案。 【参考方案1】:

经过大量研究,this 是我发现的唯一可以解释这种行为的东西。我在Windows 10 上运行IIS 8。虽然我找不到我的确切版本组合的限制,但我认为这可能是问题所在。

微软似乎会限制同时请求的数量。对于某些基本版本,3 将是限制。我似乎无法在任何地方更改这些设置,所以如果您知道如何,请为遇到此问题的其他人发布另一个答案。

【讨论】:

确实很有趣,而且它在没有适当的解决方法之前就已经浮出水面(除了一些建议使用 IIS Express):***.com/q/33024015/1768303

以上是关于为啥我的 WCF 服务一次只处理 3 个并行请求?的主要内容,如果未能解决你的问题,请参考以下文章

带有命名管道的 WCF:如何允许并行调用?

httpd学习:http基础(续)

如何实现一次只为 1 个客户端提供服务的 WebSocket 服务器

运行 1000 个请求,这样一次只运行 10 个

HttpClient.GetAsync 一次只执行 2 个请求?

为啥 Spring Webflux 只能并行接受 256 个请求?