Wejście
Hi!
W tym artykule podzielę się swoim doświadczeniem w budowaniu architektury mikroserwisowej dla projektu wykorzystującego sieci neuronowe.
Porozmawiajmy o wymaganiach architektury, przyjrzyjmy się różnym schematom strukturalnym, przeanalizujmy każdy z elementów gotowej architektury, a także oceńmy parametry techniczne rozwiązania.
Miłej lektury!
Kilka słów o problemie i jego rozwiązaniu
Główną ideą jest ocena atrakcyjności danej osoby w dziesięciopunktowej skali na podstawie zdjęcia.
W tym artykule odejdziemy od opisu zarówno wykorzystywanych sieci neuronowych, jak i procesu przygotowania i uczenia danych. Jednak w jednej z kolejnych publikacji na pewno powrócimy do pogłębionej analizy procesu oceny.
Teraz przejdziemy przez proces ewaluacji na najwyższym poziomie i skupimy się na interakcji mikroserwisów w kontekście ogólnej architektury projektu.
Podczas pracy nad rurociągiem oceny atrakcyjności zadanie zostało rozłożone na następujące komponenty:
- Zaznaczanie twarzy na zdjęciach
- Ocena każdej osoby
- Renderuj wynik
Pierwszy jest rozwiązywany przez siły wstępnie przeszkolone
Schemat funkcjonalny rurociągu ewaluacyjnego
Analiza wymagań architektury projektu
W cyklu życia
Cykl życia projektu ML
Ten projekt nie jest wyjątkiem – podjęto decyzję o przekształceniu procesu oceny w usługę online, co wymagało zanurzenia się w architekturze. Zidentyfikowano następujące podstawowe wymagania:
- Ujednolicone przechowywanie logów – wszystkie usługi powinny zapisywać logi w jednym miejscu, powinny być wygodne do analizy
- Możliwość poziomego skalowania usługi oceny – jako najbardziej prawdopodobne wąskie gardło
- Do oceny każdego obrazu należy przeznaczyć tę samą ilość zasobów procesora, aby uniknąć wartości odstających w rozkładzie czasu na wnioskowanie
- Szybkie (ponowne) wdrożenie zarówno konkretnych usług, jak i stosu jako całości
- Możliwość, w razie potrzeby, wykorzystania wspólnych obiektów w różnych usługach
Architektura
Po przeanalizowaniu wymagań stało się oczywiste, że architektura mikroserwisów pasuje niemal idealnie.
Aby pozbyć się niepotrzebnych problemów, jako frontend wybrano Telegram API.
Najpierw przyjrzyjmy się schematowi strukturalnemu gotowej architektury, następnie przejdźmy do opisu każdego z elementów, a także sformalizujmy proces udanego przetwarzania obrazu.
Schemat konstrukcyjny gotowej architektury
Porozmawiajmy bardziej szczegółowo o każdym z elementów diagramu, oznaczając je Pojedyncza odpowiedzialność w procesie oceny obrazu.
Mikroserwis „attrai-telegram-bot”
Ta mikrousługa obejmuje wszystkie interakcje z interfejsem API Telegramu. Istnieją 2 główne scenariusze: praca z niestandardowym obrazem i praca z wynikami potoku oceny. Przyjrzyjmy się ogólnie obu scenariuszom.
Po otrzymaniu niestandardowej wiadomości z obrazem:
- Przeprowadza się filtrację, składającą się z następujących kontroli:
- Dostępność optymalnego rozmiaru obrazu
- Liczba obrazów użytkowników znajdujących się już w kolejce
- Po przejściu wstępnego filtrowania obraz zostaje zapisany w woluminie okna dokowanego
- W kolejce „to_estimate” generowane jest zadanie, które zawiera m.in. ścieżkę do obrazu znajdującego się w naszym wolumenie
- Jeżeli powyższe kroki przebiegną pomyślnie, użytkownik otrzyma komunikat z przybliżonym czasem przetwarzania obrazu, który jest wyliczany na podstawie ilości zadań w kolejce. Jeżeli wystąpi błąd, użytkownik zostanie wyraźnie o tym poinformowany poprzez wysłanie wiadomości z informacją o tym, co mogło pójść nie tak.
Ponadto ta mikrousługa, podobnie jak proces roboczy selera, nasłuchuje kolejki „after_estimate”, która jest przeznaczona dla zadań, które przeszły przez potok oceny.
Po otrzymaniu nowego zadania od „after_estimate”:
- Jeśli obraz zostanie pomyślnie przetworzony, wynik wysyłamy do użytkownika, jeśli nie, powiadamiamy o błędzie.
- Usuwanie obrazu będącego wynikiem potoku oceny
„Attrai-estimator” mikroserwisu ewaluacyjnego
Ta mikrousługa jest procesem roboczym selera i zawiera wszystko, co jest związane z potokiem oceny obrazu. Działa tu tylko jeden algorytm – przeanalizujmy go.
Po otrzymaniu nowego zadania od „to_estimate”:
- Przepuśćmy obraz przez potok oceny:
- Ładowanie obrazu do pamięci
- Doprowadzamy obraz do wymaganego rozmiaru
- Znajdowanie wszystkich twarzy (MTCNN)
- Oceniamy wszystkie twarze (twarze znalezione w ostatnim kroku zawijamy w partię i wyciągamy wnioski ResNet34)
- Renderuj ostateczny obraz
- Narysujmy ramki ograniczające
- Rysowanie ocen
- Usuwanie niestandardowego (oryginalnego) obrazu
- Zapisywanie danych wyjściowych z potoku oceny
- Umieszczamy zadanie w kolejce „after_estimate”, której odsłuchuje omówiony powyżej mikroserwis „attrai-telegram-bot”.
Graylog (+ mongoDB + Elasticsearch)
Wybór padł na niego, a nie na zwykłego
Jako osoba, która wcześniej pracowała tylko ze stosem ELK, miałem ogólnie pozytywne doświadczenia podczas pracy z Graylog. Jedyną rzeczą, która jest przygnębiająca, jest wyższość funkcji Kibany nad interfejsem sieciowym Graylog.
RabbitMQ
W tym projekcie został użyty jako
Redis
Czasami istnieje potrzeba użycia wspólnych obiektów, które implementują określone struktury danych w różnych mikrousługach Pythona.
Przykładowo Redis przechowuje hashmapę w postaci „telegram_user_id => liczba aktywnych zadań w kolejce”, co pozwala ograniczyć liczbę żądań od jednego użytkownika do określonej wartości, a tym samym zapobiegać atakom DoS.
Sformalizujmy proces udanego przetwarzania obrazu
- Użytkownik wysyła obraz do bota Telegramu
- „attrai-telegram-bot” odbiera wiadomość z interfejsu API Telegramu i analizuje ją
- Zadanie z obrazem zostaje dodane do kolejki asynchronicznej „to_estimate”
- Użytkownik otrzymuje wiadomość z planowanym czasem oceny
- „attrai-estimator” pobiera zadanie z kolejki „to_estimate”, uruchamia oszacowania przez potok i tworzy zadanie w kolejce „after_estimate”
- „attrai-telegram-bot” nasłuchując kolejki „after_estimate”, wysyła wynik do użytkownika
DevOps
Wreszcie po zapoznaniu się z architekturą można przejść do równie interesującej części – DevOps
Rój dokerów
Używając „roju”, wszystkie węzły w naszym klastrze można podzielić na 2 typy – pracownika i menedżera. Na maszynach pierwszego typu rozmieszczane są grupy kontenerów (stosów), maszyny drugiego typu odpowiadają za skalowanie, równoważenie i
Klaster składający się z jednego menedżera-lidera i trzech pracowników
Minimalny możliwy rozmiar klastra to 1 węzeł; pojedyncza maszyna będzie jednocześnie pełnić funkcję lidera-menedżera i pracownika. W oparciu o wielkość projektu i minimalne wymagania dotyczące odporności na uszkodzenia zdecydowano się zastosować to podejście.
Patrząc w przyszłość powiem, że od pierwszej dostawy produkcyjnej, która miała miejsce w połowie czerwca, nie było żadnych problemów związanych z organizacją tego klastra (nie oznacza to jednak, że taka organizacja jest w jakikolwiek sposób akceptowalna w każdej średniej i dużej projektów, które podlegają wymogom odporności na awarie).
Stos Dockera
W trybie roju odpowiada za wdrażanie stosów (zestawów usług dokowanych)
Obsługuje konfiguracje tworzenia dokerów, umożliwiając dodatkowe użycie parametrów wdrażania.
Przykładowo stosując te parametry ograniczono zasoby dla każdej z instancji mikrousług ewaluacyjnych (przydzielamy N rdzeni dla N instancji, w samym mikroserwisie ograniczamy liczbę rdzeni wykorzystywanych przez PyTorch do jednego)
attrai_estimator:
image: 'erqups/attrai_estimator:1.2'
deploy:
replicas: 4
resources:
limits:
cpus: '4'
restart_policy:
condition: on-failure
…
Należy zauważyć, że Redis, RabbitMQ i Graylog są usługami stanowymi i nie można ich skalować tak łatwo, jak „estymator attrai”
Zapowiadając pytanie – dlaczego nie Kubernetes?
Wydaje się, że używanie Kubernetesa w małych i średnich projektach jest narzutem; całą niezbędną funkcjonalność można uzyskać z Docker Swarm, który jest dość przyjazny dla orkiestratora kontenerów, a także ma niski próg wejścia.
Infrastruktura
Wszystko to zostało wdrożone na VDS o następujących cechach:
- Procesor: 4-rdzeniowy procesor Intel® Xeon® Gold 5120 @ 2.20 GHz
- RAM: 8 GB
- Dysk SSD: 160 GB
Po testach obciążenia lokalnego wydawało się, że przy poważnym napływie użytkowników ta maszyna będzie wystarczająca.
Ale zaraz po wdrożeniu zamieściłem link do jednej z najpopularniejszych tablic graficznych w WNP (tak, tej samej), po czym ludzie się zainteresowali i w ciągu kilku godzin usługa pomyślnie przetworzyła dziesiątki tysięcy zdjęć. Jednocześnie w momentach szczytowych zasoby procesora i pamięci RAM nie były wykorzystywane nawet w połowie.
Jeszcze trochę grafiki
Liczba unikalnych użytkowników i żądań oceny od czasu wdrożenia, w zależności od dnia
Rozkład czasu wnioskowania potoku oceny
odkrycia
Podsumowując, mogę powiedzieć, że architektura i podejście do orkiestracji kontenerów w pełni się uzasadniły – nawet w momentach szczytowych nie było żadnych spadków ani spadków czasu przetwarzania.
Myślę, że małe i średnie projekty, które w swoim procesie wykorzystują wnioskowanie sieci neuronowych w czasie rzeczywistym na procesorze, mogą z powodzeniem zastosować praktyki opisane w tym artykule.
Dodam, że początkowo artykuł był dłuższy, jednak aby nie wpisywać się w długą lekturę, zdecydowałem się pominąć niektóre punkty w tym artykule – powrócimy do nich w przyszłych publikacjach.
Bota możesz zaczepić na Telegramie - @AttraiBot, będzie działać przynajmniej do końca jesieni 2020. Przypominam, że nie są przechowywane żadne dane użytkownika – ani oryginalne obrazy, ani wyniki procesu oceny – wszystko jest niszczone po przetworzeniu.
Źródło: www.habr.com