使用WebClient发送100k +请求/秒?

时间:2014-06-05 05:08:48

标签: .net multithreading http asynchronous webclient

我在.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

0 个答案:

没有答案