Les améliorations réseau de .NET 7

Par:
fredericmazue

lun, 12/12/2022 - 16:34

.NET 7 est sorti mi-novembre. Ses grosses nouveautés, C#11, NET MAUI, support d'ARM entre autres, ont fait de l'ombre à de nombreuses améliorations mineures en compraraison, mais néanmoins très intéressantes. Voici par exemples quelques améliorations de la prise en charge du réseau par la plate-forme .NET 7.

HTTP : Amélioration de la gestion des échecs de tentative de connexion

Dans les versions antérieures à .NET 6, s'il n'y a pas de connexion immédiatement disponible dans le pool de connexions, une nouvelle requête HTTP lancera toujours une nouvelle tentative de connexion et l'attendra (si les paramètres du gestionnaire le permettent). L'inconvénient est que s'il faut un certain temps pour établir cette connexion et qu'une autre connexion devient disponible entre-temps, cette demande continuera d'attendre la connexion qu'elle a engendrée, ce qui affectera la latence. .NET 6.0 proposait déjà quelque chose pour traiter cela, mais l'implémentation s'est avérée problématique pour certains utilisateurs, selon les termes de Microsoft.

Dans .NET 7.0, Microsoft a implémenté les modifications suivantes :

  • Une tentative de connexion qui échoue ne peut échouer que dans sa requête initiale, et jamais une requête non liée. Si la demande d'origine a été traitée au moment où une connexion échoue, l'échec de la connexion est ignoré
  • Si une demande initie une nouvelle connexion, mais est ensuite traitée par une autre connexion du pool, la nouvelle tentative de connexion en attente expirera silencieusement après une courte période, indépendamment de ConnectTimeout. Avec cette modification, les connexions bloquées ne bloqueront pas les requêtes non liées

Détections des erreurs de protocole HTTP/2 et HTTP/3

Les protocoles HTTP/2 et HTTP/3 définissent des codes d'erreur au niveau du protocole dans RFC 7540 Section 7 et RFC 9114 Section 8.1, par exemple, REFUSED_STREAM (0x7) dans HTTP/2 ou dans H3_EXCESSIVE_LOAD (0x0107) HTTP/3. Contrairement aux codes d'état HTTP, il s'agit d'informations d'erreur de bas niveau qui ne sont pas importantes pour la plupart des utilisateurs de HttpClient, mais elles sont utiles dans les scénarios HTTP/2 ou HTTP/3 avancés, notamment grpc-dotnet, où la distinction des erreurs de protocole est essentielle pour implémenter les tentatives client .

Microsoft a défini une nouvelle exception, HttpProtocolException, pour contenir le code d'erreur au niveau du protocole dans sa propriété ErrorCode.

QUIC

QUIC est un nouveau protocole de couche transport. Il a été récemment standardisé dans la RFC 9000. Il utilise UDP comme protocole sous-jacent et il est présenté comme étant intrinsèquement sécurisé car il impose l'utilisation de TLS 1.3. Une autre différence intéressante par rapport aux protocoles de transport bien connus tels que TCP et UDP est qu'il a un multiplexage de flux intégré sur la couche de transport. Cela permet d'avoir plusieurs flux de données simultanés et indépendants qui ne s'affectent pas les uns les autres.

Pour Microsoft, le protocole QUIC offre de nombreux avantages par rapport à TCP avec TLS. Par exemple, un établissement de connexion plus rapide car il ne nécessite pas autant d'allers-retours que TCP avec TLS en plus. Ou éviter le problème de blocage de tête de ligne où un paquet perdu ne bloque pas les données de tous les autres flux.

Microsoft avait introduit l'implémentation QUIC dans la bibliothèque QUIC de .NET 5. Cependant, jusqu'à présent, la bibliothèque était strictement interne et ne servait qu'à sa propre implémentation de HTTP/3. Avec la sortie de .NET 7, Microsoft rend la bibliothèque publique et nous expose ses API. Ces API sont en preview pour le moment.

System.Net.Quic est documenté ici.

WebSocket

Avant .NET 7, la partie réponse du serveur de la poignée de main (handshake) d'ouverture de WebSocket (réponse HTTP à la demande de mise à niveau) était masquée dans l'implémentation ClientWebSocket. Toutes les erreurs de poignée de main provoquaient une levée de WebSocketException sans trop de détails à côté du message d'exception. Cependant, les informations sur les en-têtes de réponse HTTP et le code d'état peuvent être importantes dans les scénarios d'échec et de réussite.

.NET 7 ajoute un paramètre CollectHttpResponseDetails à ClientWebSocketOptions qui permet de collecter les détails de la réponse de mise à niveau dans une instance ClientWebSocket pendant l'appel ConnectAsync. Vous pouvez accéder ultérieurement aux données à l'aide des propriétés HttpStatusCode et HttpResponseHeaders de l'instance ClientWebSocket, même dans le cas où ConnectAsync lève l'exception. 

.NET 7 ajoute également la possibilité d'utiliser le protocole WebSocket sur HTTP/2, comme décrit dans RFC 8441 . Avec cela, la connexion WebSocket est établie sur un seul flux sur la connexion HTTP/2. Cela permet de partager une seule connexion TCP entre plusieurs connexions WebSocket et requêtes HTTP en même temps, ce qui permet une utilisation plus efficace du réseau.