.net - .NET应用程序中超过3000个线程的瓶颈(HttpWebReqsuest.BeginGetResponse)

标签 .net vb.net multithreading

因此,我正在创建一个使用HTTP API来获取约50,000个帐户中每个帐户状态的应用程序。该代码循环遍历每个帐户,并为其发送HTTP请求。当我根据某些条件收到http请求的响应时,将创建一个新线程来管理该帐户。

现在正常情况下,我可以很容易地每秒发送大约1K个请求,但是一旦我碰到了大约3,100个 Activity 线程,http请求循环就会开始变慢并冻结到每秒仅大约1个请求。然后它突然跳回到每秒3k,然后冻结了几秒钟...等等。重要的是,它似乎并没有逐渐退化的趋势。它发生得非常突然。

显然,某个地方存在瓶颈,但是我不确定在哪里。我确保将TCP参数(可用端口的最大数量)设置为高限制。我将servicepoint.defaultconnection限制设置为int.maxvalue。

我的CPU是具有专用1Gbps的4核(带有HT的8线程)。我正在考虑迁移到更大的计算机(32核2x CPU)。但是我不确定它是否会带来任何好处。我想知道是否有人意识到我可能遇到的其他瓶颈。

我什至没有用光我所有的带宽或内存,我知道那不是问题。

这大致就是我的代码的样子

Sub Main()
    While 1
        For each account As Account in GetAccountsFromDatabase()'~50K Accounts
            dim request = HttpWebRequest.Create("http://api.com?id=" & account.name)
            request.BeginGetResponse(New AsyncCallback(AddressOf HandleResponse), request)
            RequestsSent += 1
            Console.Writeline("Request")

            'After ~3000 active threads in the process, this loop begins freezing/slowing down.

            if RequestsSent > 5000 then 'Limit
                Thread.Sleep(5000)
                RequestsSent = 0
            end if

        Next
    End While
End Sub

Sub HandleResponse(ByVal asynchronousResult As IAsyncResult)
    Dim webRequest As HttpWebRequest = DirectCast(asynchronousResult.AsyncState, HttpWebRequest)
    Dim webResponse As HttpWebResponse = webRequest.EndGetResponse(asynchronousResult)
    Dim stream As New StreamReader(webResponse.GetResponseStream())
    Dim response = stream.ReadToEnd

    if response.contains("somestuff") then    
        dim t As New Thread(AddressOf ProcessAccount)
        t.Start(account) 
    end if

End Sub

Sub ProcessAccount(acc As Account)
    'Process the account. Involves some other loops, http requests...etc
End Sub

最佳答案

好吧,您正在异步启动请求,但是一旦BeginGetResponse完成,您就会同步处理该请求。这最终可能会消耗池中的许多线程。也许您的配置中的池限制为3000个线程左右。

您需要扔掉它。一旦进入数百个线程,并且肯定进入了1000个线程,就需要切换到异步非阻塞IO。使用await,这变得非常容易。

使流读取部分异步(ReadToEnd)。可能应该删除所有代码,并用var str = await new HttpClient().GetAsync(url);(C#)替换。

接下来,运行50,000(!)个线程是不明智的。仅此一项就将为您设置50 GB(!)的堆栈内存。操作系统也开始安排我在测试中发现的所有这些线程有麻烦。例如,尽管鼠标驱动程序具有很高的优先级,但鼠标仍会停止移动几秒钟。显然,内核团队并不在乎这种情况。

可能应该以给定的并行度处理帐户。例如,仅同时处理100个。

如果出于某种原因需要同时处理它们,那么ProcessAccount也必须是异步的。别无退路。

关于.net - .NET应用程序中超过3000个线程的瓶颈(HttpWebReqsuest.BeginGetResponse),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30426701/

相关文章:

.net - 如何在单独的线程上设置全局键盘 Hook ?

Java客户端-服务器套接字,重用客户端套接字抛出 "java.io.StreamCorruptedException: invalid type code: AC"

c# - 为什么空字符串不是连接的标识?

.net - 在 VS2010 中调试故障转储

c# - 在 VS2008 中找不到 System.Web.Hosting

c# - 在 winforms ComboBox 中为单个项目上色?

vb.net - 将数组保存到文件

vb.net - 尝试在 VB.NET 中调用重载构造函数时出现编译器错误

c# - 如何确定给定类型 (System.Type) 是否继承自特定基类(在 .Net 中)?

java - 停止阵列中正在运行的线程