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

Entrée/Sortie Java Discussion :

Requête HTTP via httpClient bien trop longue


Sujet :

Entrée/Sortie Java

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut Requête HTTP via httpClient bien trop longue
    Bonjour,

    Je viens de fignoler un bout de code permettant d'envoyer des requêtes HTTP à des cameras IP et de récupérer le résultat associé.

    J'utilise la librairie httpClient-4.3.1

    voici le code que j'utilise pour effectuer mes requêtes :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
     
    try {
    	SSLContext contexteSSL   = getConfigurationSSL(ipDestinataire);
    	CredentialsProvider auth = getConfigurationAuthentification(ipDestinataire);
     
    	CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(new SSLConnectionSocketFactory(contexteSSL)).setDefaultCredentialsProvider(auth).build();
     
    	httpget = new HttpGet(urlString);
     
    	if (ipSource != null)	httpget.setConfig(getRequestConfig(ipSource));
    	else				httpget.setConfig(getRequestConfig());
     
    	response = httpclient.execute(httpget);
     
    	entity = response.getEntity();
    	InputStream is = entity.getContent();
     
    	BufferedReader buffer = new BufferedReader(new InputStreamReader(is));
     
        	String str  = "";
     
        	// lecture du contenu du flux et stockage sous forme de chaine	
    	while (null != ((str = buffer.readLine()))){
    		if (str.length() > 0){
    			str = str.trim();
    			if(!str.equals(""))		retour += str;
    		}
    	}
    	// fermeture du flux		
    	buffer.close();
     
    	EntityUtils.consume(entity);
    	response.close();
    	httpclient.close();
     
    } catch (Exception e) {
    	Logger.getLoggerParDefaut().debug("Exception lros de l'appel HTTP");
    	e.printStackTrace();
    }
    la methode getConfigurationSSL() precise que l'on accepte tous les certificats
    la methode getConfigurationAuthentification() definit le bon login/mdp
    la methode getRequestConfig() créé la configuration avec une adresse locale :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    private static RequestConfig getRequestConfig(String ipEcoute) {
    	try {
    		return RequestConfig.custom().setSocketTimeout(TIMEOUT_CONNEXION).setConnectionRequestTimeout(TIMEOUT_CONNEXION).setConnectTimeout(TIMEOUT_CONNEXION)
    					.setLocalAddress(InetAddress.getByName(ipEcoute)).setAuthenticationEnabled(true).build();
    	} catch (UnknownHostException e) {
    		return null;
    	}
    }
    Ce code fonctionne et me permet de récuperer les resultats que je veux, mais j'ai tout de même un énorme soucis..

    la méthode execute() de la classe CloseableHttpClient est extrêmement longue.. elle met 11 secondes pour renvoyer le résultat sous forme d'une CloseableHttpResponse (dans le cas ou l'URL est atteignable, sinon, retour au bout de TIMEOUT_CONNEXION secondes)

    Est-ce normal ? je suppose que non mais je ne vois pas ce qui peut causer ce problème..

    Merci de votre aide

  2. #2
    Membre éclairé Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Points : 803
    Points
    803
    Par défaut
    Si tu récupères une image, 11 secondes ça peut être normal non ? Combien de mégaoctets récupère-tu ?
    Sans danger si utilisé conformément au mode d'emploi.

    (anciennement BenWillard, enfin moins anciennement que ... enfin bon c'est une longue histoire... Un genre de voyage dans le temps...)

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut
    je récupère quelques caractères seulement la plupart du temps.

    j'interroge une caméra, donc je demande des infos comme le modèle, le port RTSP.... la réponse fait une petite ligne de texte du genre :

    Brand.ProdNbr=M3005

    si je fais un wget ou directement dans le navigateur c'est instantané. J'avais également fait ce code via d'autres methodes, c'etait très rapide, mais httpClient est la seule librairie ou je peux préciser l'IP source depuis laquelle je veux faire ma requête...

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Si tu retire l'ip source, tu as les même temps?

  5. #5
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut
    oui, exactement pareil...

    la camera que je veux joindre est sur un réseau :
    10.16.106.0/24

    la machine qui essaie de faire la requête est sur un autre :
    10.16.192.0/24
    (j'ai une route depuis la machine qui fait la requête jusqu'à ma camera)

    pour simplifier les TESTS :
    je met la machine qui fait la requete sur le même réseau que la camera.

    J'ai toujours le même temps de réponse.
    De plus, si comme tu le propose j'enlève l'IP source, cela ne change rien..

  6. #6
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut
    est ce que l'URL que l'on définit peut poser un problème si elle est composée de différents paramètres GET ?

    une URL classique que j'utilise :
    https://10.16.106.32/axis-cgi/param....=Brand.ProdNbr

    si je lance dans un navigateur, le code source renvoie juste :
    Brand.ProdNbr=M3005

    mon prog récupere la même chose, mais en 10secondes..

    si je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     wget --no-check-certificate  --bind-address 10.16.197.253 "https://root:mdp@10.16.106.33/axis-cgi/param.cgi?action=list&group=Brand.ProdNbr"
    je récupere bien
    Brand.ProdNbr=M3005
    mais dans un fichier créé nommé :
    param.cgi?action=list&group=Brand.ProdNbr

    si jamais je ne met pas les cotes, la connexion dure 10 sec et je récupere la liste completes de tous les parametres de la camera (qques Mo)

    peut être que mon prog renvoie bien mon résultat mais qu'il récupere aussi autre chose que je ne vois pas et qui prend du temps..

  7. #7
    Membre éclairé Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Points : 803
    Points
    803
    Par défaut
    a connexion dure 10 sec et je récupere la liste completes de tous les parametres de la camera (qques Mo)
    Quelques Mo en 10 sec, ça fait quelques centaines de k/sec, ça semble normal non ? Donc apparemment il lit les Mo mais tu ne récupère que la première info.
    Sans danger si utilisé conformément au mode d'emploi.

    (anciennement BenWillard, enfin moins anciennement que ... enfin bon c'est une longue histoire... Un genre de voyage dans le temps...)

  8. #8
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut
    oui, ça semble normal pour le wget, mais pour mon prog, c'est vraiment bizarre, j'essaie de lire les entêtes, je parcours le flux InputStream, il ne contient que l'info que j'ai demandé..

    je pense aussi que le probleme vient de la, maintenant reste à savoir si c'est bien ça et si oui, pourquoi la camera renvoie autant d'infos et que je ne les vois pas..

  9. #9
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Tu peux activer le logging de ton httpclient, comme indiqué ici

    https://hc.apache.org/httpcomponents...x/logging.html


    Ca te permettra de savoir ce qui passe sur le cable.

  10. #10
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut
    re, je vais essayer de voir les logs, ca m'en dira peut etre plus..

    en utilisant wireshark aussi je me disais, je pourrais facilement voir la quantité de données.

  11. #11
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    oui mais en https, wireshark est beaucoup moins utile

  12. #12
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Tu es sûr que les lenteurs viennent bien de la méthode httpclient.execute() ?

    Parce que tu parles de récupérer "quelques Mo" de donnée, et en dessous je vois un code bien affreux qui peut bien malmener le GC :
    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
    	InputStream is = entity.getContent();
     
    	BufferedReader buffer = new BufferedReader(new InputStreamReader(is));
     
        	String str  = "";
     
        	// lecture du contenu du flux et stockage sous forme de chaine	
    	while (null != ((str = buffer.readLine()))){
    		if (str.length() > 0){
    			str = str.trim();
    			if(!str.equals(""))		retour += str;
    		}
    	}
    	// fermeture du flux		
    	buffer.close();
    Non seulement ca fait mal aux yeux car le close() n'est pas dans un bloc finally (ou via le try-with-ressource de Java 7), mais tu utilises des concaténations de String dans une boucle, ce qui conduit à générer un très grand nombre d'objets temporaires...
    Il faut utiliser un StringBuilder !!!

    Avec ton code je met environ 5 minutes pour lire un fichier de 6Mo en local... alors que c'est quasi-instantané avec un code comme celui là :
    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
    		final String result;
    		// Note : il serait préférable de spécifier l'encodage
    		Reader reader = new InputStreamReader(is);
    		try {
    			// On peut initialiser la taille du StringBuilder
    			// si on la connait à l'avance :
    			StringBuilder sb = new StringBuilder();
    			char[] cbuf = new char[8192];
    			int len;
     
    			while ( (len=reader.read(cbuf)) > 0 ) {
    				sb.append(cbuf, 0, len);
    			}
    			result = sb.toString();
    		} finally {
    			reader.close();
    		}
    a++

  13. #13
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut
    salut,
    le code la n'est pas définitif, je voulait juste afficher le flux complet opur voir s'il y avait plus d'informations que ce que je demandais, mais effectivement je vais utiliser ta solution.

    J'ai avancé, j'ai fait pas mal de test et oui, c'est la méthode execute(), mais j'ai compris que la phase qui est lente, c'est lorsque j'ajoute la notion de certificat.

    je veux juste accepter les certificats sans verif, et c'est cette étape qui prend un temps fou.

  14. #14
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut
    Je teste différentes méthodes, du genre :

    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
    19
    20
    21
    22
    23
     
    SSLContext sslContext = null;
    try {
    	sslContext = SSLContext.getInstance("SSL");
     
    	// set up a TrustManager that trusts everything
    	sslContext.init(null, new TrustManager[] { new X509TrustManager() {
    	            public X509Certificate[] getAcceptedIssuers() {
    	                   Logger.getLoggerParDefaut().debug("getAcceptedIssuers =============");
    	                    return null;
    	            }
    	            public void checkClientTrusted(X509Certificate[] certs,  String authType) {
    	                   Logger.getLoggerParDefaut().debug("checkClientTrusted =============");
    	            }
     
    	            public void checkServerTrusted(X509Certificate[] certs, String authType) {
    	                   Logger.getLoggerParDefaut().debug("checkServerTrusted =============");
    	            }
    	} }, new SecureRandom());
     
    } catch (Exception e) {
    	e.printStackTrace();
    }
    mais j'obtiens toujours un temps énorme, du genre 4-5 secondes avant de voir les logs :
    checkServerTrusted =============
    getAcceptedIssuers =============

    et encore 4-5 secondes pour obtenir le resultat.

    Y a t-il une méthode spéciale ? j'ai déjà utilisé ce genre de code avec des URLConnection et je n'avais pas ce soucis de temps...

  15. #15
    Membre éclairé Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Points : 803
    Points
    803
    Par défaut
    Envoyer directement l'URL ?
    Sans danger si utilisé conformément au mode d'emploi.

    (anciennement BenWillard, enfin moins anciennement que ... enfin bon c'est une longue histoire... Un genre de voyage dans le temps...)

  16. #16
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut
    heu.. envoyer directement l'URL ? peux tu préciser, car je suis dans le flou !

    peut être veux tu dire en utilisant des classes comme URLConnection plutot que Httpclient ?

  17. #17
    Membre éclairé Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Points : 803
    Points
    803
    Par défaut
    Puisque depuis le navigateur ça va vite, pourquoi ne pas simplement utiliser quelque chose du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new URL(url).openStream();
    Pas possible avec https peut-être ?
    Sans danger si utilisé conformément au mode d'emploi.

    (anciennement BenWillard, enfin moins anciennement que ... enfin bon c'est une longue histoire... Un genre de voyage dans le temps...)

  18. #18
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Transports

    Informations forums :
    Inscription : Février 2011
    Messages : 192
    Points : 107
    Points
    107
    Par défaut
    si c'est possible,

    mais la machine que j'utilise pour envoyer mes requêtes possède plusieurs interfaces, chacune sur un VLAN différents. Chaque VLAN a des routes qui lui sont propres, donc si je veux faire ma requête http ou https, je dois préciser l'adresse IP source, sinon je n'ai pas l’accès.

    j'ai la même chose avec des sockets et du SNMP, mais pour HTTP c'est catastrophique, je n'ai trouvé que HttpClient qui le permet avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     RequestConfig.custom().setLocalAddress(InetAddress.getByName(ipEcoute))
    malheureusement, la requête prend désormais 10sec au lieu de quelques millisecondes lorsque j'utilisais URL

  19. #19
    Membre éclairé Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Points : 803
    Points
    803
    Par défaut
    Pour que ça fonctionne (rapidement, donc) avec ton navigateur, tu envoyes juste un URL non ? pourquoi ne pas envoyer le même depuis tes sources ?
    Sans danger si utilisé conformément au mode d'emploi.

    (anciennement BenWillard, enfin moins anciennement que ... enfin bon c'est une longue histoire... Un genre de voyage dans le temps...)

  20. #20
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par JoeChip Voir le message
    Pour que ça fonctionne (rapidement, donc) avec ton navigateur, tu envoyes juste un URL non ? pourquoi ne pas envoyer le même depuis tes sources ?
    Vraisemblablement que les sources ne tournent pas sur le même serveur que son navigateur.

    Tu parle de plusieurs VLAN différents, mais le VLAN que tu utilise pour accéder à la webcam, il a bien aussi un accès internet? SSLFactory a besoin de ça pour vérifier les certificats!

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Problème Requête HTTP Via URL HTTPS
    Par newsdas dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 8
    Dernier message: 13/01/2011, 17h55
  2. Exécuter requête HTTP via PHP
    Par calitom dans le forum Langage
    Réponses: 0
    Dernier message: 15/07/2010, 16h11
  3. requêtes http via openssl
    Par gaelle40 dans le forum Réseau
    Réponses: 2
    Dernier message: 10/07/2009, 18h33
  4. [MySQL] Requête trop longue ?
    Par Thomas1434 dans le forum PHP & Base de données
    Réponses: 14
    Dernier message: 24/03/2006, 22h55
  5. Comment envoyer une requête POST via HTTP ?
    Par pdtor dans le forum C++
    Réponses: 2
    Dernier message: 13/09/2005, 06h54

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