Отправка 100 000+ запросов / с с помощью WebClient?
Я написал простой http-клиент в.Net, который должен выдавать 100 тыс. (Или около того) http-запросов в секунду для стресс-тестирования веб-службы. Веб-сервис работает на той же машине, что и клиент.
Кажется, я столкнулся со скоростью 20 тыс. Запросов / с на 4-х ядерном компьютере для разработки. Загрузка процессора составляет всего 50%.
Кроме того, кажется, что он плохо масштабируется - я получаю только 50 тыс. Запросов в секунду на 12-ядерном сервере с 25% -ной загрузкой процессора. Сервер примерно в 5 раз более производительный в GFlops, чем машина dev.
В обоих случаях служба сервера работает примерно на 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