2016-07-03 2 views
2

Je cours un système d'acquisition de données sur une machine Ubuntu 16.04. Il est déployé sur un site distant, ma capacité à modifier la configuration physique est donc limitée. Nous avons quelqu'un sur le site qui a pu effectuer des tests simples avec la configuration.Les connexions de socket Python ont un retard d'une seconde toutes les 9 connexions sur Ubuntu 16.04

Nous exécutons un script python pour l'acquisition de données. Cependant, nous avons remarqué qu'à des débits de données élevés, nous faisions l'expérience de sauvegardes bizarres dans notre mémoire tampon de données. Après plusieurs heures de débogage, nous avons pu réduire la question jusqu'à le cas de test suivant:

for i in xrange(500): 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.connect(('1.2.3.4', 5678)) 
    sock.close() 

Lorsque le code ci-dessus exécute la plupart des échantillons exécutent presque instantanément, mais chaque échantillon 9 prend exactement une seconde pour exécuter. Bizarrement, lors de la prise de données, la période est beaucoup plus courte - 650ms environ en un test - et plus de connexions réussissent avant l'échantillon de pépin (dans ce cas, l'échantillon de pépins ne prend que ~ 400ms de cet intervalle de 650ms). Ci-dessous un graphique de la latence de la connexion en fonction du temps pour les deux instances. Sont en quelques secondes axes.)

Latency between connections. connect-and-close in blue, system under load in red.

est ici un sous-ensemble de la mise au point, nous avons essayé, et si le problème persiste ou non dans chaque cas. Toutes mes excuses pour la brièveté; Si une étape n'est pas claire, je suis heureux de fournir des informations de suivi.

  • acquisition de données avec netcat: Travaux
  • Run script python entre deux machines Ubuntu 14.04 (contre auditeur nc, pas en mesure de tester avec une source de données): Travaux
  • connecter à un autre ordinateur exécutant un écouteur de netcat, au lieu de la source de données, à partir de l'ordinateur d'acquisition: problème persiste
  • Appel shutdown() avant close(): problème persiste
  • essayé d'utiliser asyncore pour exécuter le serveur: problème persiste
  • essayé d'ouvrir les prises dans les discussions: le problème persiste
  • basculée divers paramètres du noyau net.ipv4.tcp_*: problème persiste

De ce qui précède, la seule cohérence, je suis en mesure de discerner que python en cours d'exécution sur cette machine particulière rencontre ce problème. Je n'ai pas encore eu l'occasion de tester ceci sur un autre Ubuntu 16.04 (ou n'importe quel autre noyau 4.x, d'ailleurs), donc je ne sais pas si c'est lié à un changement dans la pile réseau ou pas. Je vais continuer à tester divers tests pour essayer de diagnostiquer ce problème, mais toutes les idées sont appréciées!

Mise à jour:

Le résultat de ulimit -a (rien me saute aux yeux comme inhabituel).

core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
scheduling priority    (-e) 40 
file size    (blocks, -f) unlimited 
pending signals     (-i) 32053 
max locked memory  (kbytes, -l) 64 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 1024 
pipe size   (512 bytes, -p) 8 
POSIX message queues  (bytes, -q) 819200 
real-time priority    (-r) 0 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 32053 
virtual memory   (kbytes, -v) unlimited 
file locks      (-x) unlimited 

Je vais bientôt lancer le test TIME_WAIT et afficher les résultats. Un autre test que j'espère exécuter est l'exécution des appels netcat et python avec strace pour voir si/comment les arguments de socket et de connexion diffèrent.

+0

Veuillez vérifier 'ulimit'. Je suppose qu'il doit y avoir un certain facteur limitant au nombre de connexions que vous pouvez avoir en supposant que le serveur distant a la capacité de gérer toutes les connexions entrantes à ce rythme. En outre, utilisez netcat pour surveiller les sockets TIME_WAIT, peut-être que les connexions ne sont pas fermées correctement. Si c'est le cas, essayez: 'sock.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)'. S'il vous plaît laissez-moi savoir sur la progression :) – purrogrammer

+0

Quelle est la valeur de la file d'écoute? Du côté serveur? Quand il se remplit, le message envoyé par le client sera supprimé et la retransmission de tcp aura lieu. Cette valeur par défaut est de 3 secondes (vos systèmes peuvent être réglés sur 1 seconde), pour confirmer, vous devez capturer tcpdump et vérifier – VenkatC

Répondre

1

Merci pour vos suggestions. Rétrospectivement, tcpdump est la première chose que j'aurais dû vérifier, alors merci Venkat de me substituer à mon propre jugement.

Cela semble être un bug avec le logiciel du fournisseur. Tcpdump a montré que lors de l'exécution du test python, le périphérique anticipait l'établissement de la liaison et renvoyait une réponse à la dernière requête de données émise. En effet, le SYN a été retransmis 1 seconde après la chute du paquet, et le cycle s'est poursuivi.

Les 9 paquets semblent être une coïncidence de la latence (ce qui a été suggéré par la dérive dans le tracé affiché) - la réponse est déclenchée immédiatement, et vient justement de préempter le 9ème paquet; une seule requête avec netcat (par exemple printf "" | nc 1.2.3.4 5678) déclencherait la retransmission de données.

Nous allons essayer de travailler avec le fournisseur pour résoudre ce problème. En attendant, nous pouvons essayer d'utiliser settimeout et gérer l'exception de timeout en rétablissant la connexion.

Encore merci!