Co się stanie, jeśli rozpocznę zbyt wiele zadań w tle?

13

Muszę trochę popracować na 700 urządzeniach sieciowych przy użyciu skryptu expect. Mogę to zrobić sekwencyjnie, ale do tej pory czas działania wynosi około 24 godzin. Wynika to głównie z czasu potrzebnego na nawiązanie połączenia i opóźnienia w wyjściach z tych urządzeń (starych). Jestem w stanie ustanowić dwa połączenia i sprawić, by działały równolegle, ale jak daleko mogę to przesunąć?

Nie sądzę, żebym mógł zrobić wszystkie 700 z nich naraz, na pewno jest limit na nie. połączeń telnet, którymi moja maszyna wirtualna może zarządzać.

Gdybym spróbował uruchomić 700 z nich w takiej pętli:

for node in `ls ~/sagLogs/`; do  
    foo &  
done

Z

  • Procesor 12 procesorów x Procesor Intel (R) Xeon (E) E5649 @ 2,53 GHz

  • Pamięć 47,94 GB

Moje pytanie brzmi:

  1. Czy wszystkie 700 instancji może działać jednocześnie?
  2. Jak daleko mogę dotrzeć, dopóki mój serwer nie osiągnie limitu?
  3. Czy po osiągnięciu tego limitu zaczeka on tylko na następną iterację, fooczy też nastąpi awaria skrzynki?

Niestety działam w korporacyjnym środowisku produkcyjnym, więc nie mogę po prostu spróbować zobaczyć, co się stanie.

KuboMD
źródło
3
Miałem szczęście parallel, korzystając z około 50 równoczesnych zadań. Jest to świetne medium między równoległością 1 i 700. Inną miłą rzeczą jest to, że nie ma partii. Pojedyncze zablokowane połączenie utknie tylko samo, a nie inne. Główną wadą jest zarządzanie błędami. Żadne z tych podejść opartych na powłoce z wdziękiem nie obsłuży błędów. Będziesz musiał samodzielnie sprawdzić sukces i wykonać własne próby.
Adam
1
Twoja kolejka zadań może dziś mieć 700, ale czy rozmiar może się zwiększyć? Obserwuj, czy przestrzeń wymiany rośnie, co oznacza, że ​​osiągnąłeś limit pamięci. A% procesorów nie jest dobrą miarą (dla Linuksa / Uniksa), lepiej wziąć pod uwagę średnią ładowanie (długość kolejki uruchamiania).
ChuckCottrill
1
Ostatnim sposobem, w jaki przerwałem produkcję w mojej wciąż nowej pracy, było przypadkowe uruchomienie ponad miliona krótkotrwałych prac w tle. Obejmowały one maszyny JVM (poczekaj, czekaj, odłóż widły), więc konsekwencje były „ograniczone” do setek tysięcy plików raportów o błędach, których wątków nie można było uruchomić.
michaelb958 - GoFundMonica
4
Nitpick: Nie analizuj lsdanych wyjściowych
l0b0 30.04.19
1
@KuboMD I tak długo, jak nikt inny nie chce używać twojego kodu.
l0b0

Odpowiedzi:

17

Czy wszystkie 700 instancji może działać jednocześnie?

To zależy od tego, co masz na myśli jednocześnie. Jeśli jesteśmy wybredni, to nie, nie mogą, chyba że masz 700 wątków wykonania w swoim systemie, z których możesz skorzystać (więc prawdopodobnie nie). Realistycznie jednak tak, prawdopodobnie mogą, pod warunkiem, że masz wystarczającą ilość pamięci RAM i / lub miejsca wymiany w systemie. UNIX i jego różnorodne dzieci są wyjątkowo dobre w zarządzaniu ogromnymi poziomami współbieżności, dlatego właśnie są tak popularne w przypadku HPC na dużą skalę.

Jak daleko mogę dotrzeć, dopóki mój serwer nie osiągnie limitu?

Niemożliwe jest udzielenie konkretnej odpowiedzi bez wielu dodatkowych informacji. Prawie musisz mieć wystarczającą ilość pamięci, aby sprostać:

  • Wymagania dotyczące pamięci całego zadania dla jednego zadania, razy 700.
  • Wymagania pamięci bash do zarządzania tak wieloma zadaniami (bash nie jest w tym okropny, ale kontrola zadań nie jest dokładnie wydajna pod względem pamięci).
  • Wszelkie inne wymagania dotyczące pamięci w systemie.

Zakładając, że się z tym spotkałeś (ponownie, mając tylko 50 GB pamięci RAM, nadal masz do czynienia z innymi problemami:

  • Ile czasu procesora zmarnuje bash podczas kontroli zadań? Prawdopodobnie niewiele, ale przy setkach miejsc pracy może to być znaczące.
  • Jaka będzie potrzebna przepustowość sieci? Samo otwarcie wszystkich tych połączeń może zalać sieć na kilka minut, w zależności od przepustowości i opóźnień.
  • Wiele innych rzeczy, o których prawdopodobnie nie myślałem.

Czy po osiągnięciu tego limitu zaczeka tylko na następną iterację od foo, czy też nastąpi awaria skrzynki?

To zależy od tego, jaki limit zostanie osiągnięty. Jeśli jest to pamięć, coś umrze w systemie (a dokładniej, zostanie zabity przez jądro w celu zwolnienia pamięci) lub sam system może ulec awarii (nie jest niczym niezwykłym konfigurowanie systemów do celowego awarii, gdy kończy się pamięć). Jeśli jest czas na procesor, po prostu będzie działał bez problemu, po prostu nie będzie można zrobić wiele więcej w systemie. Jeśli jest to sieć, możesz zawiesić inne systemy lub usługi.


To, czego naprawdę potrzebujesz, to nie jednoczesne uruchamianie wszystkich zadań. Zamiast tego podziel je na partie i uruchom jednocześnie wszystkie zadania w ramach partii, pozwól im zakończyć, a następnie rozpocznij kolejną. Można do tego wykorzystać GNU Parallel ( https://www.gnu.org/software/parallel/ ), ale w środowisku produkcyjnym jest mniej niż idealne na taką skalę (jeśli pójdziesz z tym, nie bądź zbyt agresywny, jak powiedziałem, możesz zalać sieć i wpłynąć na systemy, których inaczej byś nie dotknął). Naprawdę poleciłbym zajrzeć do odpowiedniego narzędzia do aranżacji sieci, takiego jak Ansible ( https://www.ansible.com/), ponieważ nie tylko rozwiąże to problemy z współbieżnością (Ansible wykonuje wsadowanie, jak wspomniano powyżej automatycznie), ale także zapewni wiele innych przydatnych funkcji do pracy (takich jak idempotentne wykonywanie zadań, ładne raporty o stanie i natywna integracja z bardzo duża liczba innych narzędzi).

Austin Hemmelgarn
źródło
Istnieją sposoby uruchamiania ograniczonej liczby zadań w tle (przy użyciu bash, perl, python i in.), Monitorowania realizacji zadań i uruchamiania większej liczby zadań po zakończeniu wcześniejszych zadań. Prostym podejściem byłoby zebranie partii zadań reprezentowanych przez pliki w podkatalogach i przetwarzanie partii naraz. Istnieją inne sposoby ...
ChuckCottrill
Czy obejmuje to również systemy uniksopodobne? Co to jest „GUN równoległy”?
Biswapriyo
2
@ChuckCottrill Tak, są rzeczywiście inne sposoby, aby to zrobić. Biorąc pod uwagę moje własne doświadczenie związane z tego typu rzeczami, prawie zawsze lepiej jest po prostu zdobyć prawdziwe narzędzie do aranżacji, niż wypróbować własne rozwiązanie, zwłaszcza gdy minie kilkadziesiąt systemów pod względem skali.
Austin Hemmelgarn
3
@forest Tak, możesz użyć limitów, aby zapobiec awarii systemu, ale poprawienie ich w takim przypadku nie jest łatwe (musisz wiedzieć, jakie są wymagania dotyczące zasobów dla zadań wcześniej) i nie chroni reszta sieci od wpływu, jaki te zadania mogą spowodować (co jest prawdopodobnie potencjalnie znacznie większym problemem niż awaria systemu lokalnego).
Austin Hemmelgarn
12

Trudno powiedzieć konkretnie, ile instancji można uruchomić jako zadania w tle w opisany sposób. Ale normalny serwer z pewnością może utrzymywać 700 równoczesnych połączeń, o ile wykonujesz to poprawnie. Serwery WWW robią to cały czas.

Czy mogę zasugerować użycie GNU równoległego ( https://www.gnu.org/software/parallel/ ) lub czegoś podobnego do osiągnięcia tego? Dałoby to szereg korzyści w podejściu do pracy w tle:

  • Możesz łatwo zmienić liczbę równoczesnych sesji.
  • I zaczeka na zakończenie sesji, zanim zacznie nowe.
  • Łatwiej jest przerwać.

Zajrzyj tutaj, aby szybko rozpocząć: https://www.gnu.org/software/parallel/parallel_tutorial.html#A-single-input-source

Laenkeio
źródło
1
Ciekawy! Rzucę na to okiem. Czy wiesz, że próba wykonania tego rodzaju operacji (bez pomocy Parallel) groziłaby awarią hiperwizora?
KuboMD,
2
@KuboMD, jeśli możesz rozbić hiperwizora na coś tak przyziemnego, to jest błąd w hiperwizorze :)
hobbs
na bok, serwery sieciowe często używają wątków lub przetwarzania opartego na zdarzeniach (przykład: gunicorn.org )
ChuckCottrill 30.04.2019
10

Używanie &do przetwarzania równoległego jest dobre, gdy wykonujesz kilka czynności i monitorujesz postępy. Ale jeśli pracujesz w korporacyjnym środowisku produkcyjnym, potrzebujesz czegoś, co da ci lepszą kontrolę.

ls ~/sagLogs/ | parallel --delay 0.5 --memfree 1G -j0 --joblog my.log --retries 10 foo {}

To będzie działać foodla każdego pliku w ~/sagLogs. Uruchamia zadanie co 0,5 sekundy, będzie wykonywać tyle zadań równolegle, jak to możliwe, o ile 1 GB pamięci RAM jest wolne, ale będzie przestrzegać limitów w systemie (np. Liczby plików i procesów). Zazwyczaj oznacza to, że będziesz wykonywać równolegle 250 zadań, jeśli nie zmieniłeś dozwolonej liczby otwartych plików. Jeśli dostosujesz liczbę otwartych plików, nie powinno być problemu z równoległym uruchomieniem 32000 - o ile masz wystarczającą ilość pamięci.

Jeśli zadanie zakończy się niepowodzeniem (tzn. Zwróci kod błędu), zostanie ono powtórzone 10 razy.

my.log poinformuje cię, czy zadanie się powiedzie (po ewentualnych próbach), czy nie.

Ole Tange
źródło
To wygląda bardzo obiecująco, dziękuję.
KuboMD,
Przeprowadziłem prosty test cat ~/sagLogs/* >> ~/woah | paralleli cholera, która była szybka. 1 054 552 linii w mgnieniu oka.
KuboMD,
3
Polecenie, które wydałeś, ma podwójne przekierowanie, więc nie sądzę, że robi to, co zamierzasz. GNU Parallel ma narzut 10 ms na zadanie, więc zadania 1M powinny zająć 3 godziny.
Ole Tange
1
W ogóle nie ma zastosowania, jeśli wszystko, co chcesz zrobić, to po prostu połączyć pliki.
Ole Tange
1
@ KuboMD trywialna pętla zajętości procesora, awk 'BEGIN{for(i=rand()*10000000; i<100000000;i++){}}' która działałaby do zabawy. Możesz też wypróbować takie zadanie, jak sleep 10obserwowanie nzadań w locie bez zajmowania dużo czasu procesora. np. time parallel sleep ::: {100..1}biegać śpi od 100 do 1 sekundy.
Peter Cordes,
1

Co się stanie, jeśli rozpocznę zbyt wiele zadań w tle?

system stanie się powolny i nie będzie reagował, najgorszy przypadek jest tak niereagujący, że najlepiej byłoby po prostu nacisnąć przycisk zasilania i dokonać twardego restartu ... byłoby to uruchamianie czegoś takiego jak root, gdzie miałby zaszczyt to robić. Jeśli skrypt bash działa w ramach regularnych uprawnień użytkownika, to pierwszą rzeczą, która przychodzi do głowy, to /etc/security/limits.confi /etc/systemd/system.confi wszystkie zmienne do niej [idealnie mówiąc] zapobiec użytkownika (ów) z przeciążenia systemu.

  • cpu = xeon E5649, czyli 12- rdzeniowy procesor; więc masz 12 rdzeni dla 12 procesów do jednoczesnego działania, każdy z wykorzystaniem jednego z dwunastu rdzeni na 100%. Jeśli uruchomisz 24 procesy, każdy z nich będzie działał przy 50% wykorzystaniu każdego z dwunastu rdzeni, 700 procesów = 1,7%, ale jest to komputer, o ile wszystko zakończy się poprawnie w odpowiednim czasie, to = sukces; efektywność nie zawsze jest istotna.

    1. Czy wszystkie 700 instancji może działać jednocześnie? Z pewnością 700 nie jest dużą liczbą; maxprocNa przykład domyślnym plikiem my /etc/security/limits.conf jest 4,135,275

    2. Jak daleko mogę się dostać, dopóki mój serwer nie osiągnie limitu? Jestem pewien, że znacznie dalej niż 700.

    3. Granice ... co się stanie, jeśli skrypt zostanie uruchomiony na koncie użytkownika [i ogólnie root również limits.confdotyczy prawie wszystkich] jest to, że skrypt zakończy działanie po próbie zrobienia foo &700 razy; spodziewalibyście się wtedy 700 procesów foo , każdy z innym pid, ale może zobaczyć tylko 456 (wybór liczb losowych), a pozostałe 244 nigdy się nie uruchomiły, ponieważ zostały zablokowane przez pewne zabezpieczenia lub limit systemowy.

Pytanie Million $: ilu powinieneś uruchomić jednocześnie?

brałeś udział w sieci i powiedziałeś, że każdy wykona połączenie telnet, zgadnij, że wpadasz na limity sieci i koszty ogólne, zanim zrobisz to dla limitów procesora i pamięci RAM. Ale nie wiem, co konkretnie robisz, to, co najprawdopodobniej się wydarzy, to możesz uruchomić wszystkie 700 naraz, ale wszystko będzie się automatycznie blokować, dopóki poprzednie procesy i połączenia sieciowe nie zakończą się i nie zamkną w oparciu o różne ograniczenia systemowe lub coś w rodzaju pierwsze 500 rozpocznie się, a pozostałe 200 nie, ponieważ ograniczenia systemu lub jądra temu zapobiegają. Ale jakkolwiek wielu biegnie jednocześnie, będzie trochę słodyczyszybko i sprawnie, aby wszystko było zrobione ... minimalizując koszty ogólne i zwiększając wydajność. Mając 12 rdzeni (lub 24, jeśli masz 2 jednostki centralne), zacznij od 12 (lub 24) na raz, a następnie zwiększ liczbę równoczesnych partii o 12 lub 24, aż nie zauważysz poprawy czasu działania.

wskazówka: połączenia telnet google max i zobacz, jak to odnosi się do twojego systemu (systemów). Nie zapomnij także o zaporach ogniowych. Dokonaj również szybkiego obliczenia potrzebnej pamięci na proces x 700; upewnij się, że <dostępna pamięć RAM (w twoim przypadku około 50 GB), w przeciwnym razie system zacznie używać SWAP i po prostu przestanie odpowiadać. Więc uruchom 12, 24, N procesów naraz i monitoruj wolną pamięć RAM, a następnie zwiększ N już wiedząc, co się dzieje.

Domyślnie RHEL ogranicza liczbę połączeń telnet z jednego hosta do 10 równoczesnych sesji. Jest to funkcja bezpieczeństwa ... ustawiona na 10, /etc/xinetd.conf, zmień wartość „per_source”.

Ron
źródło