2017-06-23 5 views
1

Ich versuche viele gleichzeitige Benutzer (> 2000) zu simulieren, um einen Web Service zu testen. Jeder Benutzer führt Aktionen an einer bestimmten vordefinierten Zeit, zum Beispiel:Viele parallele WebRequests senden

  • Benutzer A: 09.10.02, 09.10.03, 09:10:08
  • Benutzer B: 9.10 : 03, 09.10.05, 09:10:07
  • Benutzer C: 09.10.03, 09.10.09, 09.10.15, 09:10:20

I Jetzt möchten Sie Web-Anfrage in Echtzeit zu jeder dieser Zeiten senden. Ich kann eine Verzögerung von höchstens ~ 2 Sekunden tolerieren. Was ich bereits ohne Erfolg versucht:

a) Aggregate alle mal in einer einzigen Liste, sortiert nach Zeit es dann iterieren:

foreach (DateTime sendTime in times) { 
    while (DateTime.now < sendTime) 
     Thread.Sleep(1); 
    SendRequest(); 
} 

b) für jeden Benutzer einen Thread erstellen, mit jedem Thread Prüfung für die gleiche Bedingung wie oben aber eine längere Schlafzeit

Beide Ansätze funktionieren, aber die Verzögerung zwischen der Zeit, die die Anfrage gesendet werden sollte und der Zeit, die es tatsächlich gesendet wurde, ist viel zu hoch. Gibt es eine Möglichkeit, die Anfragen mit höherer Präzision zu senden?

Edit: Die vorgeschlagenen Ansätze arbeiten wirklich gut. Die Verzögerung ist jedoch immer noch extrem hoch für viele Anfragen. Apparantly, der Grund dafür ist, meine Sendrequest() Methode:

private static async Task SendRequest() 
{ 
    // Log time difference 
    string url = "http://www.request.url/newaction"; 
    WebRequest webRequest = WebRequest.Create(url); 
    try 
    { 
     WebResponse webResponse = await webRequest.GetResponseAsync(); 
    } 
    catch (Exception e) { } 
} 

Beachten Sie, dass meine Web-Service keine Antwort zurückgibt, vielleicht ist dies der Grund für die Verlangsamung? Kann ich die Anfrage senden, ohne auf die Antwort zu warten?

+1

und Ihre Frage? –

+0

Ich habe eine genauere Frage hinzugefügt – aseipel

Antwort

2

würde ich vorschlagen, ein Timer-Objekt verwenden, um die Anforderungen zu triggern:

// In Form_Load or another init method 
Timer tRequest = new Timer(); 
tRequest.Interval = 500; 
tRequest.Tick += TRequest_Tick; 

private void TRequest_Tick(object sender, EventArgs e) 
{ 
    var sendTimes = times.Where(t => t.AddMilliseconds(-500) < DateTime.Now && t.AddMilliseconds(500) > DateTime.Now); 

    foreach(DateTime sendTime in sendTimes) 
    { 
     SendRequest(); 
    } 
} 
2

Warum Sie diese mit mehrere Thread tun? Threading erfordert eine langsame Umschaltung zwischen Ruhezustand und Ruhezustand. Sie könnten dies alles mit Timern/Async-Aufrufen tun.

List<DateTime> scheduledTimes = ...; 
List<Task> requests = scheduledTimes 
         .Select(t => t - DateTime.Now) 
         .Select(async delay => 
         { 
          await Task.Delay(delay); 
          SendRequest(); 
         }) 
         .ToList(); 

await Task.WhenAll(requests); 

Der obige Code wird in einem Thread Zeitplan alle Anforderungen an die SynchronizationContext und sie laufen.

Einfach.

+0

Vielen Dank, das funktioniert wirklich gut. Allerdings ist die Verzögerung bei vielen Anfragen wegen meiner SendRequest() - Methode immer noch ziemlich hoch. Ich habe meinen Beitrag für weitere Informationen bearbeitet. – aseipel

+1

@aseipel Ich denke, der Grund dafür ist, dass Sie die Grenzen von connectionManager treffen. Es ist auch möglich, dass Sie die Grenzen Ihres http-Servers erreichen (IIS auf Nicht-Server-Windows wird absichtlich auch mit einem Verbindungslimit eingeschränkt). – Aron

+0

Wie kann ich prüfen, ob dies der Fall ist? Ich habe bereits das Attribut maxconnection in meiner App.config, das IIS-Verbindungslimit meines Dienstes und den Anwendungspool queueLength erhöht. – aseipel