高い負荷を扱う私は(.NET 4.5に)同時に複数の要求を提供するために、以下の簡単なHttpListener
を作成しました:シンプルなタスクを返す非同期HtppListener非同期/で待つと
class Program {
static void Main(string[] args) {
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://+:8088/");
listener.Start();
ProcessAsync(listener).ContinueWith(task => { });
Console.ReadLine();
}
static async Task ProcessAsync(HttpListener listener) {
HttpListenerContext ctx = await listener.GetContextAsync();
// spin up another listener
Task.Factory.StartNew(() => ProcessAsync(listener));
// Simulate long running operation
Thread.Sleep(1000);
// Perform
Perform(ctx);
await ProcessAsync(listener);
}
static void Perform(HttpListenerContext ctx) {
HttpListenerResponse response = ctx.Response;
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}
私はApacheのベンチマークを使用これをテストする負荷ツール。 1回のリクエストをすると、リクエストの最大待ち時間が1秒になります。たとえば、10回のリクエストを行うと、応答の最大待ち時間は2秒になります。
上記のコードを効率的にするにはどうすればよいでしょうか?
編集
@ JonSkeetの答えの後、私は以下のようにコードを変更しました。最初は、ブロッキングコールをシミュレートしようとしましたが、それがコアの問題だったと思います。だから、@ JonSkeetの提案をとり、それをTask.Delay(1000)に変更しました。さて、以下のコードはmaxを与える。おおよその待ち時間。 10個の同時要求のための1秒:あなたはリスナーの分岐点になってしまいますよう
class Program {
static bool KeepGoing = true;
static List<Task> OngoingTasks = new List<Task>();
static void Main(string[] args) {
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://+:8088/");
listener.Start();
ProcessAsync(listener).ContinueWith(async task => {
await Task.WhenAll(OngoingTasks.ToArray());
});
var cmd = Console.ReadLine();
if (cmd.Equals("q", StringComparison.OrdinalIgnoreCase)) {
KeepGoing = false;
}
Console.ReadLine();
}
static async Task ProcessAsync(HttpListener listener) {
while (KeepGoing) {
HttpListenerContext context = await listener.GetContextAsync();
HandleRequestAsync(context);
// TODO: figure out the best way add ongoing tasks to OngoingTasks.
}
}
static async Task HandleRequestAsync(HttpListenerContext context) {
// Do processing here, possibly affecting KeepGoing to make the
// server shut down.
await Task.Delay(1000);
Perform(context);
}
static void Perform(HttpListenerContext ctx) {
HttpListenerResponse response = ctx.Response;
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}
完全なソリューションを提供いただき、ありがとうございます。 –
@JonSkeet上記のパターンに**サーバー送信イベント**を提供できるようにするためには、どのような変更が必要でしょうか?その場合、応答ストリームは決して実際には "閉じ"ません。たとえば、これを使用して、接続されたクライアントにデータを「**継続的にプッシュ**」するにはどうすればよいですか? –
@CharlesO私は試していませんが、出力ストリームで 'output.Close();'を呼び出さず、各プッシュでFlushを呼び出すと、正常に動作するはずです(もちろん、SSE )。これも同様に役立ちます:http://channel9.msdn.com/Events/TechDays/Techdays-2012-the-Netherlands/2287 – tugberk