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

Shell et commandes GNU Discussion :

Perte de messages dans un serveur socket


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Perte de messages dans un serveur socket
    Salut les experts,

    Voila mon problème, j'espère que l'un d'entre vous pourra me donner une direction...

    Je fais des tests de performance de disques (pour tenter de faire acheter des SSD, hé hé hé!). Un serveur de fichiers, 4 machine-clientes contenant 4 tâche-clientes. Tout ça pour simuler les machines virtuelles.

    Quelques détails: Chaque tâche-cliente transfère 10000 fichiers de 1KB. Ce qui donne 10000x4x4=160000 fichiers à transférer en même temps. Les clients sont en ramdisk pour ne pas fausser les résultats du serveur de fichiers. À chaque test, tous les fichiers sont recréés pour éviter les caches. Je dois donc écrire un script pour automatiser tout ça.

    Là où est le problème: Chaque tâche-cliente fait les transferts, mesure le temps, calcule le taux de transfert et le transmet à la machine qui supervise. J'ai d'abord transmis par fichier sur le serveur, mais le malheureux est tellement surchargé que les données apparaissent parfois beaucoup plus tard (10 ou 20s!). J'ai donc décidé que chaque tâche-cliente enverrait ses résultats par socket TCP. Malheureusement, la tâche de supervision qui attend en boucle et affiche les résultats ne les reçoit pas tous. Je suppose que le temps d'afficher et hop, un message de loupé: une tâche-cliente tente la connexion lorsque le serveur est en train d'afficher, un résultat de perdu.

    Un peu de code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    # supervisor loop
    for ((i=1; i <= $totalOfGuests; i++))
    do
      /usr/bin/nc -l $scriptHost $scriptPort
    done
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # guest task (read test)
    ssh root@$h "{ time cp $srvPath/$h/guest-$g/* $ramdiskPath/guest-${g} 2>&1 } \
      | awk -v s=$transferSize '
      /^real/ \
      {
        split(\$2, t, \"[ms]\")
        time=t[1]*60+t[2]
        printf \"  READ rate for $h, guest-${g}: %6.3f MB/s\n\", s/time/1000000
      }' | /usr/bin/nc $scriptHost $scriptPort" &
    Bon, le code est un peu difficile à lire. Ce n'est pas le plus important:

    Auriez-vous une idée pour ne pas perdre des messages? La solution des sockets est-elle la bonne, selon vous? Merci pour vos lumières.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Par défaut
    Pourquoi n'écris-tu pas le résultat de chaque script client vers un fichier plutôt que de le capturer avec ton script superviseur?

  3. #3
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bonjour Ripat,

    Écrire les résultats dans un fichier, c'est l'idée qui m'est venue en premier. Il faut placer les fichiers dans un endroit commun pour que le script superviseur puisse les lire, les formater et les afficher; j'ai choisi le serveur de fichiers. Le problème est que ce serveur est tellement à la ramasse que les fichiers de résultats apparaissent 10 à 20s plus tard donc le script superviseur doit attendre que le serveur se calme un peu pour continuer son traitement.

    Avec les sockets j'obtiens les résultats immédiatement à la fin du test, mais pas tous!

    Une idée m'est venue à la lecture de ton post: Il est possible d'envoyer les fichiers résultat par scp (SecureCoPy) directement vers la machine qui supervise les tests. Autrement dit, dans une commande exécutée par ssh sur chaque client, il y a un scp en retour vers la machine de supervision. Ça marche... à peu près, lorsqu'il y a 4 tâche-clientes sur chacune des 4 machine-clientes, je n'obtiens pas les 2 ou 3 derniers résultats en écriture... Et puis il y a une attente active (boucle de lecture sur un type de fichier).

    Mais bon, ça commence a marcher...

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Par défaut
    Une commande utile en multi processus: wait

    Tu boucles sur les process lancés en background et tu attends qu'ils se terminent tous pour afficher les résultats.

    Exemple avec simulation d'un sleep aléatoire.

    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
    declare -a PID
    >/tmp/resultats
     
    for p in 0 1 2 3 4 5 6 7 8 9;do
    	# lancement d'un process en background
    	# avec simulation d'un wait aléatoire (1 à 5 secondes)
    	random=$(shuf -i 1-5 -n1)
    	(sleep $random; echo "Process $p attend $random sec."  >> /tmp/resultats) &
     
    	# récupération du PID du process qui vient d'être lancé
    	PID[$p]=$!
    done
     
    echo "Tous les process sont lancés. Attente de la fin de chacun d'entre-eux..."
     
    # pour l'affichage des résultats on attend que tout soit terminé
    for p in ${PID[@]};do
    	wait $p
    done
     
    # quand tout est fini, affichage.
    cat /tmp/resultats

  5. #5
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Merci Ripat,

    Je ne connaissais pas la commande wait. En lisant la man-page, je vois qu'il est possible de ne pas mettre de PID et dans ce cas tous les enfants sont attendus, et c'est bien ce que je veux.

    Un autre point qui me vient en lisant ton script, c'est d'utiliser STDOUT dans la machine cliente pour retourner le résultat (pas besoin de scp en retour), et de le faire sans attendre que tous les résultats sont bien arrivés:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for ((i=1; i <= $n; i++))
    do
      ssh machine "faire les tests; afficher les résultats" & # résultats affichés sur la machine de supervision dès que tests terminés
    done
    Ton exemple devient alors:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for p in {1..10}
    do
      # lancement d'un process en background
      # avec simulation d'un wait aléatoire (1 à 5 secondes)
      random=$(shuf -i 1-5 -n1)
      (sleep $random; echo "Process $p attend $random s.") &
    done
    Merci pour les idées, ça m'aide beaucoup. J'ai aussi découvert quelques trucs intéressants que je vais ajouter dans ce fil demain.

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Par défaut
    Citation Envoyé par jmelyn Voir le message
    En lisant la man-page, je vois qu'il est possible de ne pas mettre de PID et dans ce cas tous les enfants sont attendus, et c'est bien ce que je veux.
    Ah, tiens oui. Bien vu.

  7. #7
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par jmelyn Voir le message
    Un autre point qui me vient en lisant ton script, c'est d'utiliser STDOUT dans la machine cliente pour retourner le résultat (pas besoin de scp en retour), et de le faire sans attendre que tous les résultats sont bien arrivés:
    Si tu as des problèmes de flush sur la stdout, il existe une astuce qui marche dans certains cas: c'est d'utiliser plutôt la stderr.

    Je ne sais pas bien l'expliquer et je ne le maîtrise pas, mais j'ai déjà entendu dire et observé par moi-même une certaine désynchronisation entre la stdout et la stderr, celle-ci étant "prioritaire" sur celle-là! (je crois que la stdout est bufferisée et pas la stderr)

    En bref, là où tu génères tes résultats, si tu le fais avec un '1>&2', tu vas les envoyer sur la stderr et les récupérer plus vite que par la stdout... à essayer...

Discussions similaires

  1. Réponses: 1
    Dernier message: 17/05/2010, 10h21
  2. Client/Serveur Socket, envoyer un message précis
    Par Chyokyka dans le forum Débuter
    Réponses: 4
    Dernier message: 24/03/2009, 17h59
  3. Réponses: 1
    Dernier message: 19/09/2008, 09h29
  4. Réception des messages dans le Socket
    Par rzayani dans le forum C++
    Réponses: 3
    Dernier message: 16/04/2008, 10h33
  5. Réponses: 2
    Dernier message: 18/05/2007, 11h51

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