Intrare
Hi!
În acest articol, voi împărtăși experiența mea de construire a unei arhitecturi de microservicii pentru un proiect care utilizează rețele neuronale.
Să vorbim despre cerințele arhitecturii, să analizăm diferite diagrame structurale, să analizăm fiecare dintre componentele arhitecturii finite și, de asemenea, să evaluăm metricile tehnice ale soluției.
Bucură-te!
Câteva cuvinte despre problemă și soluția ei
Ideea principală este de a evalua atractivitatea unei persoane pe o scară de zece puncte pe baza unei fotografii.
În acest articol ne vom îndepărta de la descrierea atât a rețelelor neuronale utilizate, cât și a procesului de pregătire și antrenament a datelor. Cu toate acestea, într-una dintre următoarele publicații, vom reveni cu siguranță la analizarea conductei de evaluare la un nivel aprofundat.
Acum vom trece prin conducta de evaluare la nivel superior și ne vom concentra pe interacțiunea microserviciilor în contextul arhitecturii generale a proiectului.
Când lucrați la conducta de evaluare a atractivității, sarcina a fost descompusă în următoarele componente:
- Selectarea fețelor din fotografii
- Evaluarea fiecărei persoane
- Redați rezultatul
Primul este rezolvat de forțele de pre-antrenat
Schema funcțională a conductei de evaluare
Analiza cerințelor arhitecturii proiectului
În ciclul vieții
Ciclul de viață al unui proiect ML
Acest proiect nu face excepție - a fost luată decizia de a îngloba conducta de evaluare într-un serviciu online, care a necesitat să ne cufundam în arhitectură. Au fost identificate următoarele cerințe de bază:
- Stocare unificată a jurnalelor - toate serviciile ar trebui să scrie jurnalele într-un singur loc, ar trebui să fie convenabil de analizat
- Posibilitatea de scalare orizontală a serviciului de evaluare - ca fiind cel mai probabil Blocaj
- Aceeași cantitate de resurse procesor ar trebui să fie alocată pentru a evalua fiecare imagine pentru a evita valorile aberante în distribuția timpului pentru inferență.
- (re)implementare rapidă atât a serviciilor specifice, cât și a stivei în ansamblu
- Abilitatea, dacă este necesar, de a utiliza obiecte comune în diferite servicii
Arhitectură
După analizarea cerințelor, a devenit evident că arhitectura de microservicii se potrivește aproape perfect.
Pentru a scăpa de durerile de cap inutile, API-ul Telegram a fost ales ca interfață.
Mai întâi, să ne uităm la diagrama structurală a arhitecturii finite, apoi să trecem la o descriere a fiecăreia dintre componente și, de asemenea, să formalizăm procesul de procesare a imaginii cu succes.
Diagrama structurală a arhitecturii finite
Să vorbim mai detaliat despre fiecare dintre componentele diagramei, notându-le Responsabilitate unică în procesul de evaluare a imaginii.
Microserviciu „attrai-telegram-bot”
Acest microserviciu încapsulează toate interacțiunile cu API-ul Telegram. Există 2 scenarii principale: lucrul cu o imagine personalizată și lucrul cu rezultatul unei conducte de evaluare. Să ne uităm la ambele scenarii în termeni generali.
Când primiți un mesaj personalizat cu o imagine:
- Se efectuează filtrarea, constând din următoarele verificări:
- Disponibilitatea dimensiunii optime a imaginii
- Numărul de imagini de utilizator aflate deja în coadă
- Când treceți filtrarea inițială, imaginea este salvată în volumul docker
- O sarcină este produsă în coada „to_estimate”, care include, printre altele, calea către imaginea aflată în volumul nostru
- Dacă pașii de mai sus sunt finalizați cu succes, utilizatorul va primi un mesaj cu timpul aproximativ de procesare a imaginii, care este calculat pe baza numărului de sarcini din coadă. Dacă apare o eroare, utilizatorul va fi înștiințat în mod explicit prin trimiterea unui mesaj cu informații despre ceea ce ar fi putut merge prost.
De asemenea, acest microserviciu, ca un lucrător de țelină, ascultă coada „after_estimate”, care este destinată sarcinilor care au trecut prin conducta de evaluare.
Când primiți o nouă sarcină de la „after_estimate”:
- Dacă imaginea este procesată cu succes, trimitem rezultatul utilizatorului; dacă nu, anunțăm o eroare.
- Eliminarea imaginii care este rezultatul conductei de evaluare
Microserviciu de evaluare „attrai-estimator”
Acest microserviciu este un lucrător de țelină și încapsulează tot ceea ce are legătură cu conducta de evaluare a imaginii. Există un singur algoritm de lucru aici - să-l analizăm.
Când primiți o nouă sarcină de la „to_estimate”:
- Să rulăm imaginea prin conducta de evaluare:
- Încărcarea imaginii în memorie
- Aducem imaginea la dimensiunea cerută
- Găsirea tuturor fețelor (MTCNN)
- Evaluăm toate fețele (înfășurăm fețele găsite în ultimul pas într-un lot și deducem ResNet34)
- Redați imaginea finală
- Să desenăm casetele de delimitare
- Desenarea evaluărilor
- Ștergerea unei imagini personalizată (originală).
- Salvarea rezultatului din conducta de evaluare
- Am pus sarcina în coada „after_estimate”, care este ascultată de microserviciul „attrai-telegram-bot” discutat mai sus.
Graylog (+ mongoDB + Elasticsearch)
Alegerea a căzut asupra lui, și nu asupra celui obișnuit
Fiind cineva care a lucrat anterior doar cu stiva ELK, am avut o experiență generală pozitivă în timp ce lucram cu Graylog. Singurul lucru care este deprimant este superioritatea caracteristicilor Kibana față de interfața web Graylog.
Iepure MQ
În acest proiect a fost folosit ca
Redis
Uneori este nevoie de a utiliza obiecte comune care implementează anumite structuri de date în diferite microservicii Python.
De exemplu, Redis stochează un hashmap de forma „telegram_user_id => numărul de sarcini active în coadă”, care vă permite să limitați numărul de solicitări de la un utilizator la o anumită valoare și, prin urmare, să preveniți atacurile DoS.
Să oficializăm procesul de procesare de succes a imaginii
- Utilizatorul trimite o imagine botului Telegram
- „attrai-telegram-bot” primește un mesaj de la API-ul Telegram și îl parsează
- Sarcina cu imaginea este adăugată la coada asincronă „to_estimate”
- Utilizatorul primește un mesaj cu timpul planificat de evaluare
- „attrai-estimator” preia o sarcină din coada „to_estimate”, rulează estimările prin conductă și produce sarcina în coada „after_estimate”
- „attrai-telegram-bot” ascultând coada „after_estimate”, trimite rezultatul utilizatorului
DevOps
În cele din urmă, după ce ați revizuit arhitectura, puteți trece la partea la fel de interesantă - DevOps
Docker roi
Folosind un „roi”, toate nodurile din clusterul nostru pot fi împărțite în 2 tipuri – lucrător și manager. Pe mașinile de primul tip sunt desfășurate grupuri de containere (stive), mașinile de al doilea tip sunt responsabile de scalare, echilibrare și
Cluster cu un manager lider și trei lucrători
Dimensiunea minimă posibilă a clusterului este de 1 nod; o singură mașină va acționa simultan ca manager lider și lucrător. Pe baza dimensiunii proiectului și a cerințelor minime de toleranță la erori, s-a decis să se utilizeze această abordare.
Privind în perspectivă, voi spune că de la prima livrare de producție, care a avut loc la mijlocul lunii iunie, nu au existat probleme asociate cu această organizație de cluster (dar asta nu înseamnă că o astfel de organizație este în vreun fel acceptabilă în orice mediu-mari). proiecte, care sunt supuse cerințelor de toleranță la erori).
Docker Stack
În modul roi, el este responsabil pentru implementarea stivelor (seturi de servicii docker)
Acceptă configurațiile docker-compose, permițându-vă să utilizați suplimentar opțiunile de implementare.
De exemplu, folosind acești parametri, resursele pentru fiecare dintre instanțe de microserviciu de evaluare au fost limitate (alocam N nuclee pentru N instanțe, în microserviciu în sine limităm numărul de nuclee utilizate de PyTorch la unul)
attrai_estimator:
image: 'erqups/attrai_estimator:1.2'
deploy:
replicas: 4
resources:
limits:
cpus: '4'
restart_policy:
condition: on-failure
…
Este important de reținut că Redis, RabbitMQ și Graylog sunt servicii cu state și nu pot fi scalate la fel de ușor ca „atrai-estimator”
Prefigurand întrebarea - de ce nu Kubernetes?
Se pare că utilizarea Kubernetes în proiecte mici și mijlocii este o suprasolicitare; toate funcționalitățile necesare pot fi obținute de la Docker Swarm, care este destul de ușor de utilizat pentru un orchestrator de containere și are, de asemenea, o barieră scăzută la intrare.
Infrastructură
Toate acestea au fost implementate pe VDS cu următoarele caracteristici:
- CPU: CPU Intel® Xeon® Gold 4 cu 5120 nuclee la 2.20 GHz
- RAM: 8 GB
- SSD: 160 GB
După testarea de încărcare locală, se părea că, cu un aflux serios de utilizatori, această mașină ar fi suficientă.
Dar, imediat după implementare, am postat un link către una dintre cele mai populare plăci de imagini din CSI (da, aceeași), după care oamenii s-au interesat și în câteva ore serviciul a procesat cu succes zeci de mii de imagini. În același timp, în momentele de vârf, resursele CPU și RAM nu erau nici măcar folosite pe jumătate.
Mai multe grafice
Numărul de utilizatori unici și solicitări de evaluare de la implementare, în funcție de zi
Distribuția timpului de inferență a conductei de evaluare
Constatări
Pentru a rezuma, pot spune că arhitectura și abordarea orchestrarii containerelor s-au justificat pe deplin - chiar și în momentele de vârf nu au existat scăderi sau scăderi în timpul de procesare.
Cred că proiectele mici și mijlocii care folosesc inferența în timp real a rețelelor neuronale pe CPU în procesul lor pot adopta cu succes practicile descrise în acest articol.
Voi adăuga că inițial articolul a fost mai lung, dar pentru a nu posta o lectură lungă, am decis să omit câteva puncte din acest articol - vom reveni la ele în publicațiile viitoare.
Puteți pune bot-ul pe Telegram - @AttraiBot, va funcționa cel puțin până la sfârșitul toamnei 2020. Permiteți-mi să vă reamintesc că nu sunt stocate date de utilizator - nici imaginile originale, nici rezultatele conductei de evaluare - totul este demolat după procesare.
Sursa: www.habr.com