- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
因此,我正在创建一个使用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/
因此,我正在创建一个使用HTTP API来获取约50,000个帐户中每个帐户状态的应用程序。该代码循环遍历每个帐户,并为其发送HTTP请求。当我根据某些条件收到http请求的响应时,将创建一个新线程来
我是一名优秀的程序员,十分优秀!