我在.Net中编写了一个简单的http客户端,需要每秒发出100k(或左右)的http请求来对Web服务进行压力测试。 Web服务与客户端在同一台计算机上运行。
我似乎在4核开发机器上以20k请求/秒击中了墙。 CPU使用率仅为50%。
此外,它似乎无法很好地扩展 - 我在12核CPU服务器上只能获得每秒50k的请求。 GFlops中的服务器性能比开发机器大5倍。
在这两种情况下,服务器服务的运行速度大约是发出请求的客户端CPU使用率的1/3,因此我似乎只是对客户端进行压力测试...
我尝试使用异步请求在多个线程上运行紧密循环(尽管我不确定我是否正确使用了这些)。如果我将线程数量增加得太高,性能实际上会下降,可能是由于上下文切换。
是否有一种模式可以达到我的目标?或者我只是不想使用WebClient来达到它?
注意:下面的代码不完整且无法编译,为清晰起见省略了很多内容
Class MainWindow
Public Sub Init() Handles MyBase.Loaded
ServicePointManager.DefaultConnectionLimit = 1000
ServicePointManager.Expect100Continue = False
ServicePointManager.MaxServicePoints = 1000
ServicePointManager.UseNagleAlgorithm = False
ApiInterface.HostDomain = Me.HostDomain
ApiInterface.Authenticate("SomeUsername", "Password")
For i As Integer = 1 To Environment.ProcessorCount * 4
Dim Thread As New System.Threading.Thread(AddressOf ApiInterface.RandomApiCall)
Thread.Start()
Next
End Sub
End Class
Public Class ApiCalls
Public ApiCalls As New List(Of ApiCallDelegate)
Public Sub New()
ApiCalls.Add(AddressOf Me.ForumRequest)
ApiCalls.Add(AddressOf Me.SessionListRequest)
ApiCalls.Add(AddressOf Me.MemberSearchRequest)
ApiCalls.Add(AddressOf Me.ChatRequest)
End Sub
Public Delegate Sub ApiCallDelegate()
Public Sub MemberSearchRequest()
Dim Request As New Api.Search.MemberSearchRequest
Request.StartAt = ThreadSafeRandom.Next(0, 999)
Request.Auth = Me.Auth
Request.Count = ThreadSafeRandom.Next(0, 100)
Request.Country = Countries.GetRandomCountryCode
ApiCall(Me.HostDomain & "/api/search/members", Request)
End Sub
Private Sub ApiCall(Uri As String, Data As Object)
Dim Client As New WebClient
AddHandler Client.UploadStringCompleted, AddressOf OnRequestComplete
Client.UploadStringAsync(New System.Uri(Uri), JsonConvert.SerializeObject(Data))
End Sub
Public Sub OnRequestComplete(Sender As Object, Args As UploadStringCompletedEventArgs)
If Args.Error Is Nothing Then
Interlocked.Increment(Status200Count)
Else
Select Case CType(CType(Args.Error, WebException).Response, HttpWebResponse).StatusCode
Case HttpStatusCode.InternalServerError
Interlocked.Increment(Status500Count)
Case HttpStatusCode.BadRequest
Interlocked.Increment(Status400Count)
Case HttpStatusCode.Unauthorized
Interlocked.Increment(Status401Count)
Case Else
Interlocked.Increment(StatusOtherCount)
End Select
End If
If Not Me.Stopping Then RandomApiCall()
End Sub
Public Sub RandomApiCall()
Me.ApiCalls(Rand.Next(0, Me.ApiCalls.Count)).Invoke()
End Sub
End Class