IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Python Discussion :

Client HTTP 2/3 avec connection multiplexée, sécurité avancée et DNS-over-HTTPS, DNS-over-QUIC, etc..


Sujet :

Contribuez Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    Directeur technique
    Inscrit en
    Octobre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 12
    Par défaut Client HTTP 2/3 avec connection multiplexée, sécurité avancée et DNS-over-HTTPS, DNS-over-QUIC, etc..
    Bonjour,

    Je propose à la communauté de découvrir un client HTTP qui remplace (drop-in) Requests.
    C'est le seul client de l'écosystème Python à réellement exploiter HTTP/2 et HTTP/3. Votre code existant se migre sans effort particulier.

    Source: https://github.com/jawah/niquests

    Voici un extrait des fonctionnalités desservies:

    • DNS over HTTPS, DNS over QUIC, DNS over TLS, and DNS over UDP
    • Plus besoin de certifi, validation des certificats avec l'aide du store de votre système.
    • OCSP: Vérification de la Révocation du Certificat
    • Visualisation des timings réseau avancée (timings) DNS, Connection, Handshake TLS, etc..
    • Certificat (CAs, and mTLS) en mémoire (sans fichier)
    • Contrôle avancée de la connexion réseau
    • Headers orientés objet
    • Annotations typage statique
    • HTTP/2 par défaut
    • HTTP/3 over QUIC
    • Connexion multiplexée!
    • 3x plus rapide avec une connexion multiplexée en single thread.
    • Thread-safe!
    • DNSSEC!
    • Async!


    Vous l'aurez compris, le projet à du potentiel, du moins j'aime à le croire.
    Je sollicite la communauté francophone pour soutenir cette initiative en testant, interagir avec le GitHub, etc..

    Bonne découverte!

  2. #2
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Bonjour,

    Tout d'abord bravo pour ce travail, j'aurai peut-être choisi une autre organisation concernant l'architecture générale, mais c'est suffisamment clair et le code est propre.

    J'ai quelques questions tout de même,
    1. Quelle sont les plus-values avec requests ?
    2. Quelle sont les plus-values avec aiohttp ?
    3. Penses-tu y placer la notion de server sur ce module ?


    requests et aiohttp sont des modules matures, il est toujours difficile de sortir des sentiers battus sur ce genre d'outil.

  3. #3
    Membre habitué
    Homme Profil pro
    Directeur technique
    Inscrit en
    Octobre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 12
    Par défaut
    Merci pour votre retour,

    Pour ce qui est de vos questions,

    Quelle sont les plus-values avec requests ?
    Quelle sont les plus-values avec aiohttp ?
    Les deux projets sont bloqués avec HTTP/1.1
    Async est initialement arrivée pour pallier l'impossibilité d'émettre des requêtes HTTP concurrentes sans avoir de multiple thread.

    Aujourd'hui Niquests n'a plus besoin d'async pour émettre en volume important des requêtes concurrentes. Ce projet permet, de manière significative, d'améliorer le ROI sans async.
    A savoir que async est une surcharge qui coute du temps CPU (cooperative multitask sur wait I/O), vous pouvez aisément battre vos records de TPS/RPS sans async en HTTP/2 ou 3 avec une seule connexion multiplexée en synchrone.

    Ensuite, sécurité, aiohttp et requests ne mettent pas la barre haute. Aucun moyen simple d'utiliser un DNS sécurisé sans y passer trop de temps, aucune confidence sur les certificats TLS révoqués, les négociations TLS laissent des paramètres non sécurisés (par ex. Cipher faible ou renégociation autorisée). Et peu de contrôle des aspects réseaux sans effort important (parfois impossible sans monkeypatch).
    Et bien plus.

    Article (10 raisons de quitter votre client HTTP): https://medium.com/dev-genius/10-rea...t-98fd4c94bef3
    Code de démonstration: https://replit.com/@ahmedtahri4/Python#main.py

    Petite note sur requests, le support est assez mort et les développements sont gelés.

    Penses-tu y placer la notion de server sur ce module ?
    Non, ce n'est pas prévu. Je considère que le champ "client HTTP" est assez large et la surface à maintenir est assez importante.
    C'est plus sage d'utiliser un projet dédié "serveur" selon moi.

    requests et aiohttp sont des modules matures, il est toujours difficile de sortir des sentiers battus sur ce genre d'outil.
    Pour commencer, tout a été fait pour rendre la migration transparente, vous n'avez rien à réapprendre. Réinventer la roue ne fais pas partie de notre ADN.

    C'est exactement ce que j'entends le plus. "C'est génial mais l'usage est plus important là-bas", "Super! mais je vois pas trop de monde l'utiliser", "Les habitudes ont la vie dure".
    Ce que je réponds à cela, c'est que nous devons prendre une posture scientifique. Il y a 400 ans, une poignée de scientifique ont affirmés que la terre n'est pas plate la terre n'est pas au centre à contre courant, pourtant de nos jours nous continuons de choisir le camps du nombre face à la rationalité.

    Le constant immédiat c'est que le projet est intéressant, ayons une approche incrémentale. Vous découvrirez les nombreux avantages au fil de l'eau.

    Posons-nous les bonnes questions:

    - Qu'est ce que je gagne à rester là où je suis ?
    - Qu'est ce que je gagne en migrant ?
    - Quelle sont les plus-values?

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par Ousret Voir le message
    Il y a 400 ans, une poignée de scientifique ont affirmés que la terre n'est pas plate à contre courant, pourtant de nos jours nous continuons de choisir le camps du nombre face à la rationalité.
    Il y a 400 ans, le sujet était plutôt de savoir si le soleil tournait autour de la terre ou le contraire.
    Et on savait que la terre n'était pas plate voir l'article de wikipedia à ce sujet.

    Citation Envoyé par Ousret Voir le message
    Le constant immédiat c'est que le projet est intéressant, ayons une approche incrémentale. Vous découvrirez les nombreux avantages au fil de l'eau.
    Il y a déjà des bibliothèques "expérimentales" comme http3, aioquic, urllib3, ... pour ceux qui veulent tester (à ce jour, pas sûr que tous les bouts soient finalisés/standardisés).

    Pour le reste, adopter un nouveau paradigme (la terre est sphérique) n'a d'intérêt que pour le bénéfice que ça va apporter sans trop d'effort. (revoir l'application pour espérer de meilleurs temps de reprise en cas d'erreur réseau... pas sûr que ça emballe les foules).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre habitué
    Homme Profil pro
    Directeur technique
    Inscrit en
    Octobre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 12
    Par défaut
    Il y a 400 ans, le sujet était plutôt de savoir si le soleil tournait autour de la terre ou le contraire.
    Super. L'idée est la même. Vous m'excuserez, mon expertise est tout d'abord sur la programmation.

    Il y a déjà des bibliothèques "expérimentales" comme http3, aioquic, urllib3, ... pour ceux qui veulent tester
    Je sais pas quoi dire. Votre connaissance de y'a 400 ans est meilleurs que celle de nos jours. Vous mentionnez des programmes sans en connaitre les tenant et les aboutissants.
    Ce qui est là n'a rien d'expérimental.

    Pour le reste, adopter un nouveau paradigme (la terre est sphérique) n'a d'intérêt que pour le bénéfice que ça va apporter sans trop d'effort. (revoir l'application pour espérer de meilleurs temps de reprise en cas d'erreur réseau... pas sûr que ça emballe les foules).
    Beaucoup de mal à comprendre le raisonnement. Votre phrase ne fait que peu de sens.
    Vous n'avez pas pris le temps d'approfondir le sujet. Dommage.

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par Ousret Voir le message
    Beaucoup de mal à comprendre le raisonnement. Votre phrase ne fait que peu de sens. Vous n'avez pas pris le temps d'approfondir le sujet. Dommage.
    QUIC/Http3 ne datent pas d'hier. Ceux qui veulent se faire la main dessus le peuvent depuis 4/5 ans (mais les concepts sont bien plus anciens). Ce qui leur permet de publier travaux et recommandations (qu'on n'est pas obligé de suivre) qui construisent ce qu'on appelle l'état de l'art. (à défaut d'avoir le temps de faire soi-même)

    Voilà de quoi on est supposé partir (l'informatique reste une science "dure"...).

    Après vous faites un peu ce que vous voulez... mais il ne faut pas confondre technique et marketing.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Merci aussi pour ton retour,

    Semaine prochaine, je le teste, tu as attisé ma curiosité

  8. #8
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Hello,

    J'ai testé sur un téléchargement de 50 MP3 (liste python d'URLs)

    Avec niquests

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    async def download_mp3(url, filename):    
        async with AsyncSession() as session:
            response = await session.get(url, stream=True)
            if response.status_code == 200:
                with open(filename, 'wb') as f:
                    for chunk in response.iter_content(1024):
                        f.write(chunk)
     
    async def main():
        tasks = [download_mp3(url, filename) for url, filename in mp3_links]
        await asyncio.gather(*tasks)
     
    start = perf_counter()
    asyncio.run(main())
    print(f"time : {perf_counter() - start}")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time : 23.999902139999904
    avec aiohttp (que je connais mieux)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    async def download_mp3(url, filename):    
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                if response.status == 200:
                    with open(filename, 'wb') as f:
                        while True:
                            chunk = await response.content.read(1024)
                            if not chunk:
                                break
                            f.write(chunk)
     
    async def main():
        tasks = [download_mp3(url, filename) for url, filename in mp3_links]
        await asyncio.gather(*tasks)
     
    start = perf_counter()
    asyncio.run(main())
    print(f"time : {perf_counter() - start}")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time : 5.988816148001206
    Le score est sans appel, qu'ai-je fais de mal dans l'utilisation de niquests ?

    Je signale que la liste est stricto identique pour les deux tests

  9. #9
    Membre habitué
    Homme Profil pro
    Directeur technique
    Inscrit en
    Octobre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 12
    Par défaut
    Excellente question.

    Voici pourquoi.

    response.iter_content
    n'est pas asynchrone, cela bloque votre event loop et la rend inefficace.
    j'essaie de proposer un AsyncResponse dans le cas stream=True, mais ce n'est pas encore prêt, mais bientôt.

    essayez avec stream=False pour le moment.
    Aussi, tentez de faire la même chose en synchrone et multiplex et (stream=True + stream=False)

  10. #10
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Merci

    Je suis quasi équivalent à aiohttp, il y a 2 secondes de plus tout de même... mais on est plutôt dans des temps très raisonnables sur 50 mp3.

    Je teste synchrone et multiplex dès que j'ai du temps (hâte de voir le résultat)

  11. #11
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Voici mes tests en synchrone + multiplexed + stream=True

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    def download_mp3(url, filename):    
        with Session(multiplexed=True) as session:
            response = session.get(url, stream=True)
            if response.status_code == 200:
                with open(filename, 'wb') as f:
                    for chunk in response.iter_content(1024):
                        f.write(chunk)
     
    def main():
        for url, filename in mp3_links:
            download_mp3(url, filename)
     
    start = perf_counter()
    main()
    print(f"time : {perf_counter() - start}")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time : 24.594879195999965
    équivalent à asynchrone + stream=True

    En synchrone avec multiplexed et stream=False, j'ai des erreurs de timeout, j'ai dû modifier un peu le code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def download_mp3(url, filename):    
        try:
            with Session(multiplexed=True) as session:
                response = session.get(url, stream=False, timeout=60)
                if response.status_code == 200:
                    with open(filename, 'wb') as f:
                        for chunk in response.iter_content(1024):
                            f.write(chunk)
        except RequestException as e:
            print(f"Erreur lors du téléchargement de {url}: {e}")
     
    def main():
        for url, filename in mp3_links:
            download_mp3(url, filename)
     
    start = perf_counter()
    main()
    print(f"time : {perf_counter() - start}")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time : 17.427481426002487
    EDIT: Petite précision, les requêtes se font sur le même serveur et je pense que le multiplexage selon ce que j'ai pu lire dépend des capacités du serveur à pouvoir gérer les connexions multiplexées.

    Du coup j'ai testé à nouveau aiohttp pour être sur la même plage horaire niveau débit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time : 5.9470249519981735
    J'attends tes remarques pour l'optimisation si possible

  12. #12
    Membre habitué
    Homme Profil pro
    Directeur technique
    Inscrit en
    Octobre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 12
    Par défaut
    Re:

    EDIT: Petite précision, les requêtes se font sur le même serveur et je pense que le multiplexage selon ce que j'ai pu lire dépend des capacités du serveur à pouvoir gérer les connexions multiplexées.
    Oui, je confirme.

    Ensuite quelque précisions:

    • Très important d'émettre (autant que possible) les requêtes avant d'y accéder en mode multiplex.
    • HTTP/2 consomme plus d'unité temps CPU que HTTP/1.1 car plus d'opérations à faire, mettez disable_http2=True et/ou disable_http3 dans le constructeur Session pour voir.
    • A défaut d'avoir vos URL j'effectue des tests sur des fichiers dummy de 5MB.
    • Niquests émet au moins une requête OCSP.
    • Qq exemple ou multiplex est pertinent https://replit.com/@ahmedtahri4/Python#main.py probablement moins en téléchargement de statique/fichier.
    • On retrouve une équivalence de temps avec aiohttp (hors multiplex, http2+) tout en sachant que niquests dispose de plus de fonctionnalités.


    merci pour vos retours constructifs.

  13. #13
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Salut,

    Oui, je confirme
    Merci

    A défaut d'avoir vos URL j'effectue des tests sur des fichiers dummy de 5MB.
    Je peux te donner mon code de base pour récupérer les URLs, ça te permettra de faire des tests de ton côté,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    from urllib.parse import unquote
    import requests
    from lxml import html
     
    base_url = "https://amigamuseum.emu-france.info/Fichiers/mp3/"
    response = requests.get(base_url)
    html_content = response.content
     
    tree = html.fromstring(html_content)
    links = tree.xpath('//a/@href')
     
    mp3_links = [(base_url + link, unquote(link)) for link in links if link.endswith('.mp3')][:50]
    HTTP/2 consomme plus d'unité temps CPU que HTTP/1.1 car plus d'opérations à faire, mettez disable_http2=True et/ou disable_http3 dans le constructeur Session pour voir.
    Avec disable_http2=True j'ai moins bien

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time : 27.635297717002686
    Avec disable_http3=True, j'ai des erreurs de timeout

    Test avec aiohttp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    time : 7.619676052010618
    Si le serveur web n'est pas configuré pour le HTTP/2, je pense que les efforts sont vains

    J'ai regardé la version du serveur c'est un Apache 2.4.56 donc qui peut gérer le HTTP/2 mais je suis pas certain qu'il ai été configuré...

  14. #14
    Membre habitué
    Homme Profil pro
    Directeur technique
    Inscrit en
    Octobre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 12
    Par défaut
    Re:

    En effet le serveur n'est pas capable de gérer HTTP/2 et supérieur.
    Une màj viens d'apporter plus de flexibilité sur les streams en async.

Discussions similaires

  1. problème http.client et urllib.parse avec python3.3
    Par python-learn dans le forum Réseau/Web
    Réponses: 0
    Dernier message: 24/09/2013, 22h09
  2. client http avec socket
    Par ben83510 dans le forum Réseau
    Réponses: 5
    Dernier message: 25/04/2011, 23h20
  3. [Xfire]Client avec connection SSL (not-yet-commons-ssl)
    Par rastalien dans le forum Services Web
    Réponses: 1
    Dernier message: 17/04/2008, 04h37
  4. souci gestion client avec connection bd access
    Par angelz dans le forum Windows Forms
    Réponses: 6
    Dernier message: 03/12/2007, 18h36
  5. Réponses: 1
    Dernier message: 11/05/2006, 11h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo