Multi-thread HttpListener avec async et await Tâches
Serait-ce un bon exemple d'une solution évolutive HttpListener qui est multi-thread?
Est-ce de cette manière, par exemple, un réel IIS serait-il le faire?
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");
}
}
Je suis spécifiquement à la recherche d'une solution évolutive qui NE repose PAS sur IIS. Au lieu de cela seulement sur http.sys (qui est la classe httplistener) -- La raison pour ne pas s'appuyer sur iIS est parce que le gouv. la zone je travail exige extrêmement réduit la surface d'attaque.
Vous devez vous connecter pour publier un commentaire.
J'ai fait quelque chose de similaire à https://github.com/JamesDunne/Aardwolf et avons fait de nombreux tests sur ce.
Voir le code à https://github.com/JamesDunne/aardwolf/blob/master/Aardwolf/HttpAsyncHost.cs#L107 le noyau de la boucle d'événement de mise en œuvre.
Je trouve que l'utilisation d'un
Semaphore
pour contrôler la façon dont de nombreux simultanéesGetContextAsync
demandes sont actives est la meilleure approche. Essentiellement, la boucle principale continue de fonctionner jusqu'à ce que le sémaphore bloque le thread en raison du comte étant atteint. Ensuite, il y aura N simultanées de la connexion "accepte" active. Chaque fois qu'une connexion est acceptée, le sémaphore est libéré et une nouvelle demande peut prendre sa place.Le sémaphore initiale de max et les valeurs de nombre de nécessiter quelques ajustements, en fonction de la charge que vous vous attendez à recevoir. C'est un équilibre délicat entre le nombre de connexions simultanées que vous attendez vs la moyenne des temps de réponse aux clients de désir. Des valeurs plus élevées signifient plus de connexions peut être maintenue encore beaucoup moins que la moyenne des temps de réponse; moins de connexions sera rejetée. Une valeur plus faible signifie moins de connexions peut être maintenue encore beaucoup plus rapidement moyenne des temps de réponse; plus de connexions sera rejetée.
J'ai trouvé, expérimentalement (sur mon matériel), que les valeurs autour de
128
autoriser le serveur à gérer de grandes quantités de connexions simultanées (jusqu'à 1 024) au temps de réponse acceptable. Test à l'aide de votre propre matériel et régler vos paramètres en conséquence.J'ai aussi trouvé qu'une seule instance de WCAT n'aime pas gérer plus de 1 024 connexions de lui-même. Donc, si vous êtes sérieux au sujet de test de charge, l'utilisation de plusieurs machines clientes avec WCAU sur votre serveur et assurez-vous de tester sur un réseau rapide par exemple 10 GbE et que votre système d'exploitation, les limites ne sont pas vous ralentir. Assurez-vous de tester sur Windows Server Références parce que le Bureau Références sont limitées par défaut.
Résumé:
La façon dont vous écrivez votre connexion accepter la boucle est critique à l'évolutivité de votre serveur.
ServicePointManager.DefaultConnectionLimit
gère les connexions HTTP pour clients et ne devrait pas affecter la connexion du serveur d'accepter/capacité de manutention.Techniquement, vous avez raison. Pour le rendre évolutif, vous voudrez probablement avoir plusieurs GetContextAsync cours d'exécution dans le même temps (tests de performance nécessaire de savoir exactement combien, mais "un peu par cœur" est probablement la bonne réponse).
Puis, naturellement, comme l'a souligné commentaires; ne pas utiliser IIS signifie que vous devez être très sérieux au sujet de la sécurité pour un tas de choses IIS vous donne "gratuitement".
Je sais que je suis énormément en retard à la fête, mais j'ai publié une bibliothèque (source ici https://github.com/jchristn/WatsonWebserver) sur NuGet qui encapsule un async serveur.