2016-04-29 13 views
2

Ich benutze System.Net.HttpListener BeginGetContext/EndGetContext, um mehrere HTTP-Anforderungen gleichzeitig zu behandeln. Dies funktioniert gut auf meinem 16-Kern Windows 7 SP1-Desktop, der 16 Anfragen gleichzeitig behandelt. Auf der Prozessor-VM von Windows Server 2012 R2 16 werden die ersten 2 von 20 Anforderungen gleichzeitig behandelt, und dann wird die Anforderung sequenziell, z. Die Antwort für die dritte Anforderung muss gesendet werden, bevor die Anforderung für die vierte Anforderung geprüft wird.HttpListener, das asynchron verwendet wird, verhält sich synchron

Ich möchte, dass der Server die Anforderungen auf die gleiche Weise wie der Desktop m/c verarbeitet. um 20 Anfragen in 8 Sekunden anstatt der aktuellen 95 Sekunden zu verarbeiten.

Das folgende Protokoll zeigt das Verhalten auf der Windows 7-Maschine (gut). Sowohl Client- als auch Server-Prozesse werden unter Windows 7 m/c ausgeführt.

Dies ist das Protokoll des Clients. Jede Zeile enthält die ursprüngliche Anforderung durch den Client, die vom Server zurückgesendet wird, wobei der Zeitpunkt der Verarbeitung durch den Server hinzugefügt wird. Die ursprüngliche Anfrage umfasst eine Sequenznummer und den Zeitpunkt, zu dem der Client die Anfrage gestellt hat.

Beachten Sie, dass alle Anfragen um 12:46 Minuten nach der vollen Stunde gestellt werden und 16 bis 12:51 und der letzte um 12:54 Uhr.

http://localhost:8894/dostuff?val=1-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=17-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=15-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=2-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=7-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=3-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=13-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=18-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=9-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=14-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=0-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=6-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=10-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=5-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=19-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=11-client-12:46-server-12:51 
http://localhost:8894/dostuff?val=12-client-12:46-server-12:52 
http://localhost:8894/dostuff?val=16-client-12:46-server-12:53 
http://localhost:8894/dostuff?val=8-client-12:46-server-12:53 
http://localhost:8894/dostuff?val=4-client-12:46-server-12:54 

Das folgende Protokoll zeigt das Verhalten auf dem Server 2012 Windows-Maschine (sehr schlecht). Sowohl Client- als auch Serverprozesse werden unter Windows Server 2012 m/c ausgeführt.

Beachten Sie, dass die ersten zwei Anforderungen gleichzeitig verarbeitet werden, aber jede nachfolgende Anforderung sequenzielle 5 Sekunden erfordert.

Beachten Sie, dass die ersten zwei Anforderungen gleichzeitig verarbeitet werden, aber jede nachfolgende Anforderung sequenzielle 5 Sekunden erfordert. Alle Anfragen werden 46 Minuten und 39 Sekunden nach der vollen Stunde gesendet. Die ersten 2 Anfragen werden 46 Minuten 44 Sekunden nach der vollen Stunde beantwortet, aber die letzte Antwort wird 48 Minuten und 14 Sekunden nach der vollen Stunde empfangen.

http://localhost:8895/dostuff?val=5-client-46:39-server-46:44 
http://localhost:8895/dostuff?val=1-client-46:39-server-46:44 
http://localhost:8895/dostuff?val=2-client-46:39-server-46:49 
http://localhost:8895/dostuff?val=6-client-46:39-server-46:54 
http://localhost:8895/dostuff?val=3-client-46:39-server-46:59 
http://localhost:8895/dostuff?val=4-client-46:39-server-47:4 
http://localhost:8895/dostuff?val=7-client-46:39-server-47:9 
http://localhost:8895/dostuff?val=9-client-46:39-server-47:14 
http://localhost:8895/dostuff?val=8-client-46:39-server-47:19 
http://localhost:8895/dostuff?val=10-client-46:39-server-47:24 
http://localhost:8895/dostuff?val=11-client-46:39-server-47:29 
http://localhost:8895/dostuff?val=12-client-46:39-server-47:34 
http://localhost:8895/dostuff?val=13-client-46:39-server-47:39 
http://localhost:8895/dostuff?val=14-client-46:39-server-47:44 
http://localhost:8895/dostuff?val=15-client-46:39-server-47:49 
http://localhost:8895/dostuff?val=16-client-46:39-server-47:54 
http://localhost:8895/dostuff?val=18-client-46:39-server-47:59 
http://localhost:8895/dostuff?val=17-client-46:39-server-48:4 
http://localhost:8895/dostuff?val=19-client-46:39-server-48:9 
http://localhost:8895/dostuff?val=0-client-46:39-server-48:14 

Der folgende Code kann einige Hinweise geben, aber ich vermute, dass es wahrscheinlicher ist, einige Quote oder Drosselung Problem auf dem Server zu sein.

// SERVER build with "csc program.cs" run as program.exe 
using System; 
using System.Net; 
using System.Text; 
using System.Threading; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     HttpListener listenerLocal = new HttpListener(); 
     listenerLocal.Prefixes.Add("http://*:8895/"); 
     listenerLocal.Start(); 
     while (true) 
     { 
      //var result = listener.BeginGetContext(RequestCallback, listener); 
      var resultLocal = listenerLocal.BeginGetContext((result) => 
      { 
       HttpListener listener = (HttpListener)result.AsyncState; 
       HttpListenerContext context = listener.EndGetContext(result); 
       Thread.Sleep(5000); 
       byte[] buffer = Encoding.UTF8.GetBytes(
        context.Request.Url.OriginalString + string.Format(
        "-server-{0}:{1}", DateTime.Now.Minute, DateTime.Now.Second)); 
       context.Response.ContentLength64 = buffer.Length; 
       System.IO.Stream output = context.Response.OutputStream; 
       output.Write(buffer, 0, buffer.Length); 
       output.Close(); 
      } 
      , listenerLocal); 
      resultLocal.AsyncWaitHandle.WaitOne(); 
     } 
    } 
} 

// CLIENT build with "csc program.cs" run as program.exe 
using System; 
class Program 
{ 
    static void Main(string[] args) 
    { 
     for (int ii = 0; ii < 20; ii++) 
     { 
      var thr = new System.Threading.Thread((ctr) => 
      { 
       var data = new System.Net.WebClient().OpenRead(
        string.Format("http://localhost:8895/dostuff?val={0}-client-{1}:{2}" 
        ,ctr, DateTime.Now.Minute, DateTime.Now.Second)); 
       var reader = new System.IO.StreamReader(data); 
       Console.WriteLine(reader.ReadToEnd()); 
       data.Close(); 
       reader.Close(); 
      }); 
      thr.Start(ii); 
     } 
     Console.ReadLine(); 
    } 

} 

Antwort

1

ThreadPool ist nicht für Burst-Aufgaben am besten, sondern können Thread

verwenden für Ihren Server

using System; 
using System.Text; 
using System.Net; 
using System.Threading; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     HttpListener listenerLocal = new HttpListener(); 
     listenerLocal.Prefixes.Add("http://*:8895/"); 
     listenerLocal.Start();  

     int count = 0; 
     while (true) 
     { 
      if (count == 20) 
       continue; 

      Interlocked.Increment(ref count); 

      var thr = new Thread(ctr => 
      { 
       var l = ctr as HttpListener; 
       HttpListenerContext context = l.GetContext(); 

       Thread.Sleep(5000); 

       byte[] buffer = Encoding.UTF8.GetBytes(context.Request.Url.OriginalString + string.Format(
        "-server-{0}:{1}", DateTime.Now.Minute, DateTime.Now.Second)); 
       context.Response.ContentLength64 = buffer.Length; 
       System.IO.Stream output = context.Response.OutputStream; 
       output.Write(buffer, 0, buffer.Length); 
       output.Close(); 

       Interlocked.Decrement(ref count); 
      }); 
      thr.Start(listenerLocal); 
     } 
    } 
} 
Ebene verwenden
Verwandte Themen