Mam skrypt wiersza polecenia, który wykonuje wywołanie interfejsu API i aktualizuje bazę danych o wyniki.
Mam limit 5 wywołań API na sekundę u dostawcy API. Wykonanie skryptu trwa dłużej niż 0,2 sekundy.
- Jeśli uruchomię polecenie sekwencyjnie, nie będzie ono działać wystarczająco szybko i będę wykonywać tylko 1 lub 2 wywołania API na sekundę.
- Jeśli uruchomię polecenie sekwencyjnie, ale jednocześnie z kilku terminali, mogę przekroczyć limit 5 połączeń / sekundę.
Czy istnieje sposób na uporządkowanie wątków, aby mój skrypt wiersza polecenia był wykonywany prawie dokładnie 5 razy na sekundę?
Na przykład coś, co działałoby z 5 lub 10 wątkami i żaden wątek nie wykonałby skryptu, jeśli poprzedni wątek wykonał go mniej niż 200 ms temu.
command-line
multithreading
Benzoes
źródło
źródło
Odpowiedzi:
W systemie GNU, a jeśli tak
pv
, możesz:Należy
-P20
wykonać najwyżej 20$cmd
jednocześnie.-L10
ogranicza szybkość do 10 bajtów na sekundę, więc 5 linii na sekundę.Jeśli twoje
$cmd
s stają się dwa wolne i powodują osiągnięcie limitu 20, wtedyxargs
przestaną czytać, aż$cmd
przynajmniej jedna instancja powróci.pv
nadal będzie zapisywać do potoku z tą samą szybkością, aż potok się zapełni (co w systemie Linux z domyślnym rozmiarem potoku 64KiB zajmie prawie 2 godziny).W tym momencie
pv
przestanie pisać. Ale nawet wtedy, gdyxargs
wznowi czytanie,pv
spróbuje nadrobić zaległości i wyśle wszystkie wiersze, które powinien był wysłać wcześniej, tak szybko, jak to możliwe, aby utrzymać ogólną średnią 5 linii na sekundę.Oznacza to, że tak długo, jak to możliwe, przy 20 procesach, aby spełnić te wymagania średnio 5 uruchomień na sekundę, będzie to robić. Jednak gdy limit zostanie osiągnięty, szybkość, z jaką uruchamiane są nowe procesy, nie będzie sterowana przez timer pv, ale przez szybkość, z jaką wracają wcześniejsze instancje cmd. Na przykład, jeśli 20 jest aktualnie uruchomionych i działało przez 10 sekund, a 10 z nich decyduje się zakończyć wszystkie w tym samym czasie, wtedy 10 nowych zostanie uruchomionych jednocześnie.
Przykład:
Średnio będzie to 5 razy na sekundę, nawet jeśli opóźnienie między dwoma cyklami nie zawsze będzie wynosić dokładnie 0,2 sekundy.
Za pomocą
ksh93
(lub za pomocą,zsh
jeśli twojesleep
polecenie obsługuje ułamkowe sekundy):Nie ogranicza to jednak liczby współbieżnych
your-command
.źródło
pv
polecenie wydaje się być dokładnie tym, czego szukałem, nie mogłem mieć lepszej nadziei! Tylko na tej linii:yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
czy nie jest to ostatniash
zbędna?sh
dotyczy$0
twojego$cmd
skryptu. Jest również używany w komunikatach o błędach przez powłokę. Bez tego$0
byłbyy
zyes
, więcy: cannot execute cmd
yes sh | pv -qL15 | xargs -n1 -P20 sh -c "$cmd"
sh
; a w moich testach, kiedy go usuwam, nie widzę żadnej różnicy!$cmd
gdy użyjesz$0
(dlaczego miałbyś to zrobić?) I wyświetli komunikat o błędzie. Spróbuj na przykład zcmd=/
; bez drugiegosh
zobaczyłbyś coś takiegoy: 1: y: /: Permission denied
zamiastsh: 1: sh: /: Permission denied
Upraszczając, jeśli twoje polecenie trwa krócej niż 1 sekundę, możesz po prostu uruchomić 5 poleceń na sekundę. Oczywiście jest to bardzo brutalne.
Jeśli twoje polecenie może potrwać dłużej niż 1 sekundę i chcesz rozłożyć polecenia, możesz spróbować
Alternatywnie możesz mieć 5 oddzielnych pętli, które działają niezależnie, z minimum 1 sekundą.
źródło
Dzięki programowi C
Możesz na przykład użyć wątku, który śpi przez 0,2 sekundy
użyj go, aby wiedzieć, jak utworzyć wątek: utwórz wątek (to jest link, którego użyłem do wklejenia tego kodu)
źródło
cc
jest istniejące narzędzie uniksowe, a to nie jest dużo kodu!Za pomocą node.js możesz uruchomić pojedynczy wątek, który wykonuje skrypt bash co 200 milisekund, bez względu na to, jak długo odpowiedź wraca, ponieważ odpowiedź pochodzi z funkcji wywołania zwrotnego .
Ten skrypt javascript jest uruchamiany co 200 milisekund, a odpowiedź jest uzyskiwana przez funkcję wywołania zwrotnego
function (error, stdout, stderr)
.W ten sposób możesz kontrolować, że nigdy nie przekracza 5 wywołań na sekundę niezależnie od tego, jak powolne lub szybkie jest wykonanie polecenia lub ile musi czekać na odpowiedź.
źródło
Od
pv
jakiegoś czasu korzystam z rozwiązania opartego na Stéphane Chazelas , ale odkryłem, że po jakimś czasie, gdziekolwiek od kilku minut do kilku godzin, wyszedł losowo (i cicho). - Edycja: Powodem było to, że mój skrypt PHP czasami umarł z powodu przekroczenia maksymalnego czasu wykonania, wychodząc ze statusem 255.Postanowiłem więc napisać proste narzędzie wiersza polecenia, które robi dokładnie to, czego potrzebuję.
Osiągnięcie mojego pierwotnego celu jest tak proste, jak:
Uruchamia prawie dokładnie 5 poleceń na sekundę, chyba że jest już 20 współbieżnych procesów, w którym to przypadku pomija kolejne wykonanie, dopóki nie zostanie udostępnione miejsce.
To narzędzie nie jest wrażliwe na wyjście o statusie 255.
źródło