多线程HttpListener,等待异步和任务

hal*_*ton 27 c# task async-await

这是一个多线程的可扩展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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我特意寻找一种不依赖于IIS的可扩展解决方案.而只是在http.sys(这是httplistener类) - 不依赖于iIS的原因是因为政府.我工作的区域需要极大减少的攻击面积.

Jam*_*nne 23

我在https://github.com/JamesDunne/Aardwolf做了类似的事情,并对此进行了一些广泛的测试.

有关核心事件循环的实现,请参阅https://github.com/JamesDunne/aardwolf/blob/master/Aardwolf/HttpAsyncHost.cs#L107中的代码.

我发现使用a Semaphore来控制多少并发GetContextAsync请求是活动的是最好的方法.本质上,主循环继续运行,直到信号量由于到达计数而阻塞线程.然后会有N个并发"连接接受"活动.每次接受连接时,都会释放信号量,并且新的请求可以取代它.

信号量的初始值和最大值计数值需要进行一些微调,具体取决于您希望接收的负载.这是您期望的并发连接数与客户所需的平均响应时间之间的微妙平衡.值越高意味着可以在平均响应时间慢得多的情况下维持更多连接; 将拒绝更少的连接.较低的值意味着可以在更快的平均响应时间内保持较少的连接; 更多连接将被拒绝.

我通过实验(在我的硬件上)发现,周围128的值允许服务器在可接受的响应时间处理大量并发连接(最多1,024).使用您自己的硬件进行测试并相应地调整参数.

我还发现单个WCAT实例不喜欢自己处理超过1,024个连接.因此,如果您认真对待负载测试,请在服务器上使用多台带有WCAT的客户端计算机,并确保通过快速网络(例如10 GbE)进行测试,并确保操作系统的限制不会降低您的速度.请务必在Windows Server SKU上进行测试,因为默认情况下桌面SKU受限制.

简介: 如何编写连接接受循环对于服务器的可伸缩性至关重要.


Cel*_*ish 5

从技术上讲,你是对的.为了使其可扩展,您可能希望同时运行多个GetContextAsync(性能测试需要确切知道多少,但"每个核心的一些"可能是正确的答案).

然后,正如评论所指出的那样; 不使用IIS意味着你需要非常认真地对待IIS给你"免费"的很多东西.