J'ai un script de ligne de commande qui effectue un appel d'API et met à jour une base de données avec les résultats.
J'ai une limite de 5 appels d'API par seconde avec le fournisseur d'API. L'exécution du script prend plus de 0,2 seconde.
- Si j'exécute la commande séquentiellement, elle ne s'exécutera pas assez rapidement et je ne ferai que 1 ou 2 appels d'API par seconde.
- Si j'exécute la commande séquentiellement, mais simultanément à partir de plusieurs terminaux, je peux dépasser la limite de 5 appels / seconde.
S'il existe un moyen d'orchestrer les threads afin que mon script de ligne de commande soit exécuté presque exactement 5 fois par seconde?
Par exemple, quelque chose qui s'exécuterait avec 5 ou 10 threads, et aucun thread n'exécuterait le script si un thread précédent l'avait exécuté il y a moins de 200 ms.
command-line
multithreading
Benjoin
la source
la source
Réponses:
Sur un système GNU et si vous l'avez fait
pv
, vous pouvez faire:Le
-P20
est d'exécuter au plus 20$cmd
en même temps.-L10
limite le débit à 10 octets par seconde, donc 5 lignes par seconde.Si votre
$cmd
s devient lent et fait atteindre la limite de 20, alors laxargs
lecture s'arrêtera jusqu'à ce qu'une$cmd
instance au moins revienne.pv
continuera à écrire sur le canal au même rythme, jusqu'à ce que le canal soit plein (ce qui sous Linux avec une taille de canal par défaut de 64 Ko prendra près de 2 heures).À ce stade,
pv
arrêtera d'écrire. Mais même alors, lorsque laxargs
lecture reprendra,pv
il tentera de rattraper son retard et d'envoyer toutes les lignes qu'il aurait dû envoyer le plus rapidement possible afin de maintenir une moyenne globale de 5 lignes par seconde.Ce que cela signifie, c'est que tant qu'il est possible avec 20 processus de répondre à 5 besoins par seconde en moyenne, il le fera. Cependant, lorsque la limite est atteinte, la vitesse à laquelle les nouveaux processus sont démarrés ne sera pas pilotée par le temporisateur de pv mais par la vitesse à laquelle les instances cmd précédentes reviennent. Par exemple, si 20 sont en cours d'exécution et durent 10 secondes, et que 10 d'entre eux décident de tout terminer en même temps, 10 nouveaux seront démarrés en même temps.
Exemple:
En moyenne, il sera de 5 fois par seconde même si le délai entre deux runs ne sera pas toujours exactement de 0,2 seconde.
Avec
ksh93
(ou aveczsh
si votresleep
commande prend en charge les fractions de seconde):Cela ne met cependant aucune limite sur le nombre de
your-command
s simultanés .la source
pv
commande semble être exactement ce que je cherchais, je ne pouvais pas espérer mieux! Juste sur cette ligne:,yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
n'est-ce pas le derniersh
redondant?sh
est pour le$0
dans votre$cmd
script. Il est également utilisé dans les messages d'erreur par le shell. Sans elle,$0
seraity
deyes
, donc vous auriez des messages d'erreur commey: cannot execute cmd
... Vous pourriez aussi faireyes sh | pv -qL15 | xargs -n1 -P20 sh -c "$cmd"
sh
; et dans mes tests, quand je l'enlève, je ne vois aucune différence!$cmd
utilisez$0
(pourquoi le ferait-il?) Et pour les messages d'erreur. Essayez par exemple aveccmd=/
; sans le secondsh
, vous verriez quelque chose commey: 1: y: /: Permission denied
au lieu desh: 1: sh: /: Permission denied
Simplement, si votre commande dure moins de 1 seconde, vous pouvez simplement démarrer 5 commandes par seconde. De toute évidence, c'est très éclatant.
Si votre commande peut prendre plus d'une seconde et que vous souhaitez étaler les commandes, vous pouvez essayer
Alternativement, vous pouvez avoir 5 boucles distinctes qui s'exécutent indépendamment, avec un minimum de 1 seconde.
la source
Avec un programme C,
Vous pouvez par exemple utiliser un thread qui dort pendant 0,2 seconde dans un certain temps
l'utiliser pour savoir comment créer un fil: créer un fil (c'est le lien que j'ai utilisé pour coller ce code)
la source
cc
est un outil Unix existant, et ce n'est pas beaucoup de code!À l'aide de node.js, vous pouvez démarrer un seul thread qui exécute le script bash toutes les 200 millisecondes quel que soit le temps nécessaire à la réponse pour revenir car la réponse passe par une fonction de rappel .
Ce javascript s'exécute toutes les 200 millisecondes et la réponse est obtenue via la fonction de rappel
function (error, stdout, stderr)
.De cette façon, vous pouvez contrôler qu'il ne dépasse jamais les 5 appels par seconde, indépendamment de la lenteur ou de la rapidité de l'exécution de la commande ou de la durée d'attente d'une réponse.
la source
J'ai utilisé la
pv
solution basée sur Stéphane Chazelas pendant un certain temps, mais j'ai découvert qu'elle s'est arrêtée de manière aléatoire (et silencieuse) après un certain temps, de quelques minutes à quelques heures. - Edit: La raison en est que mon script PHP est parfois mort à cause d'un temps d'exécution maximum dépassé, se terminant avec le statut 255.J'ai donc décidé d'écrire un outil de ligne de commande simple qui fait exactement ce dont j'ai besoin.
Atteindre mon objectif initial est aussi simple que:
Il démarre presque exactement 5 commandes par seconde, sauf s'il existe déjà 20 processus simultanés, auquel cas il ignore la ou les prochaines exécutions jusqu'à ce qu'un emplacement devienne disponible.
Cet outil n'est pas sensible à une sortie d'état 255.
la source