2012-06-23 33 views
21

これはマルチスレッドのスケーラブルなHttpListenerの良い例ですか?非同期とタスクを待つマルチスレッドのHttpListener

これは実際のIISがどうやって行うのでしょうか?

public class Program 
{ 
    private static readonly HttpListener Listener = new HttpListener(); 

    public static void Main() 
    { 
     Listener.Prefixes.Add("http://+:80/"); 
     Listener.Start(); 
     Listen(); 
     Console.WriteLine("Listening..."); 
     Console.WriteLine("Press any key to exit..."); 
     Console.ReadKey(); 
    } 

    private static async void Listen() 
    { 
     while (true) 
     { 
      var context = await Listener.GetContextAsync(); 
      Console.WriteLine("Client connected"); 
      Task.Factory.StartNew(() => ProcessRequest(context)); 
     } 

     Listener.Close(); 
    } 

    private static void ProcessRequest(HttpListenerContext context) 
    { 
     System.Threading.Thread.Sleep(10*1000); 
     Console.WriteLine("Response"); 
    } 
} 

私は特にIISに依存しないスケーラブルなソリューションを探しています。代わりにhttp.sys(これはhttplistenerクラス)のみです。 - iISに依存しない理由は、govt。私が働く場所は、攻撃の表面積を非常に小さくする必要があります。

答えて

19

私はhttps://github.com/JamesDunne/Aardwolfで同様のことをしており、これについていくつかの広範なテストを行っています。

コアイベントループの実装については、コードhttps://github.com/JamesDunne/aardwolf/blob/master/Aardwolf/HttpAsyncHost.cs#L107を参照してください。

Semaphoreを使用して、いくつの同時並行GetContextAsync要求がアクティブになっているかを制御するのが最善の方法です。本質的に、メインループは、カウントに達したためにセマフォがスレッドをブロックするまで実行を継続します。次に、N個の同時の「接続受け入れ」がアクティブになります。接続が受け入れられるたびに、セマフォーが解放され、新しい要求が代わることができます。

セマフォの初期値と最大カウント値には、受信すると予想される負荷に応じて微調整が必​​要です。それはあなたが期待する同時接続数とクライアントが望む平均応答時間との間の繊細なバランスの取れた動作です。値が高いほど、平均レスポンス時間がはるかに遅くても、より多くの接続を維持できることを意味します。より少ない接続が拒否されます。値が小さいほど、平均レスポンス時間がはるかに短くても接続を維持できることを意味します。より多くの接続が拒否されます。

128の値は、実験的に(私のハードウェア上で)、サーバが受け入れ可能な応答時間で大量の同時接続(最大1024件)を処理できることがわかりました。独自のハードウェアを使用してテストし、それに応じてパラメータを調整します。

また、WCATの1つのインスタンスでは、1024以上の接続自体を処理したくないことがわかりました。したがって、負荷テストを真剣に検討している場合は、サーバーに対してWCATを使用して複数のクライアントマシンを使用し、高速ネットワーク経由でテストしてください。あなたのOSの限界があなたを減速させていないことを確認してください。デスクトップSKUはデフォルトで制限されているため、Windows Server SKUでテストしてください。

要約: 接続の受け入れループの記述方法は、サーバーのスケーラビリティにとって重要です。

+0

リンクは死んでいます... –

+0

リンクを更新しました。コメントありがとう! –

+0

セマフォとServicePointManager.DefaultConnectionLimitの使用に違いはありますか? –

5

技術的には正しいです。スケーラビリティを実現するためには、複数のGetContextAsyncを同時に実行させたいかもしれません(パフォーマンステストでは、どれくらいの数のコアが必要かを知る必要がありますが、それぞれのコアに対してはおそらく正しい答えでしょう)。

当然ながら、コメントで指摘されているように、 IISを使用していないということは、IISがあなたに "無料で"提供する多くの事柄について、セキュリティについてかなり深刻である必要があることを意味します。

1

私はこれでパーティーに非常に遅れていることは知っていますが、非同期Webサーバーをカプセル化するNuGetにライブラリ(source here https://github.com/jchristn/WatsonWebserver)を公開しました。