Entry
Hälsningar!
I den här artikeln kommer jag att dela med mig av min erfarenhet av att bygga en mikrotjänstarkitektur för ett projekt med hjälp av neurala nätverk.
Låt oss prata om arkitekturkraven, titta på olika strukturdiagram, analysera var och en av komponenterna i den färdiga arkitekturen och även utvärdera de tekniska måtten för lösningen.
Njut av att läsa!
Några ord om problemet och dess lösning
Huvudidén är att utvärdera en persons attraktivitet på en tiogradig skala baserat på ett foto.
I den här artikeln kommer vi att gå bort från att beskriva både de neurala nätverk som används och processen för databeredning och träning. Men i en av följande publikationer kommer vi definitivt att återkomma till att analysera bedömningspipelinen på en djupgående nivå.
Nu kommer vi att gå igenom utvärderingspipelinen på toppnivå, och kommer att fokusera på interaktionen mellan mikrotjänster i samband med den övergripande projektarkitekturen.
När man arbetade med pipeline för attraktionsbedömning delades uppgiften upp i följande komponenter:
- Välja ansikten i foton
- Betyg av varje person
- Återge resultatet
Den första löses av förtränade krafter
Funktionsdiagram över utvärderingspipeline
Analys av krav på projektarkitektur
I livscykeln
Livscykeln för ett ML-projekt
Det här projektet är inget undantag - beslutet togs att omsluta bedömningspipelinen till en onlinetjänst, vilket krävde att vi fördjupade oss i arkitekturen. Följande grundläggande krav identifierades:
- Enhetlig logglagring – alla tjänster ska skriva loggar på ett ställe, de ska vara bekväma att analysera
- Möjlighet till horisontell skalning av bedömningstjänsten - som den mest troliga flaskhalsen
- Samma mängd processorresurser bör tilldelas för att utvärdera varje bild för att undvika extremvärden i fördelningen av tid för slutledning
- Snabb (om)distribution av både specifika tjänster och stacken som helhet
- Möjligheten att vid behov använda vanliga objekt i olika tjänster
Arkitektur
Efter att ha analyserat kraven blev det uppenbart att mikrotjänstarkitekturen passar nästan perfekt.
För att bli av med onödig huvudvärk valdes Telegram API som frontend.
Låt oss först titta på strukturdiagrammet för den färdiga arkitekturen, gå sedan vidare till en beskrivning av var och en av komponenterna och även formalisera processen för framgångsrik bildbehandling.
Strukturdiagram över den färdiga arkitekturen
Låt oss prata mer i detalj om var och en av komponenterna i diagrammet och betecknar dem som ett enda ansvar i processen för bildutvärdering.
Microservice "attrai-telegram-bot"
Denna mikrotjänst kapslar in all interaktion med Telegram API. Det finns två huvudscenarier: att arbeta med en anpassad bild och att arbeta med resultatet av en bedömningspipeline. Låt oss titta på båda scenarierna i allmänna termer.
När du får ett anpassat meddelande med en bild:
- Filtrering utförs, bestående av följande kontroller:
- Tillgänglighet för optimal bildstorlek
- Antal användarbilder som redan finns i kö
- När den initiala filtreringen passerar sparas bilden i dockningsvolymen
- En uppgift produceras i "att_uppskatta"-kön, som bland annat inkluderar sökvägen till bilden som finns i vår volym
- Om ovanstående steg slutförs framgångsrikt kommer användaren att få ett meddelande med den ungefärliga bildbehandlingstiden, som beräknas baserat på antalet uppgifter i kön. Om ett fel uppstår kommer användaren uttryckligen att meddelas genom att skicka ett meddelande med information om vad som kan ha gått fel.
Dessutom lyssnar denna mikrotjänst, som en selleriarbetare, på "efter_estimate"-kön, som är avsedd för uppgifter som har passerat utvärderingspipelinen.
När du får en ny uppgift från "after_estimate":
- Om bilden bearbetas framgångsrikt skickar vi resultatet till användaren, om inte meddelar vi om ett fel.
- Tar bort bilden som är resultatet av utvärderingspipelinen
Utvärdering mikrotjänst "attrai-estimator"
Den här mikrotjänsten är en selleriarbetare och kapslar in allt relaterat till bildutvärderingspipelinen. Det finns bara en fungerande algoritm här – låt oss analysera den.
När du får en ny uppgift från "to_estimate":
- Låt oss köra bilden genom utvärderingspipelinen:
- Laddar bilden i minnet
- Vi tar bilden till önskad storlek
- Hitta alla ansikten (MTCNN)
- Vi utvärderar alla ansikten (vi slår in ansiktena som hittades i det sista steget i en batch och sluter ResNet34)
- Gör den slutliga bilden
- Låt oss rita avgränsningsrutorna
- Rita betygen
- Ta bort en anpassad (original) bild
- Sparar utdata från utvärderingspipeline
- Vi lägger uppgiften i "after_estimate"-kön, som lyssnas på av mikrotjänsten "attrai-telegram-bot" som diskuteras ovan.
Graylog (+ mongoDB + Elasticsearch)
Valet föll på honom, och inte på det vanliga
Som någon som tidigare bara arbetat med ELK-stacken hade jag en övergripande positiv upplevelse när jag arbetade med Graylog. Det enda som är deprimerande är överlägsenheten i Kibanas funktioner över Graylog webbgränssnitt.
RabbitMQ
I detta projekt användes det som
Redis
Ibland finns det ett behov av att använda vanliga objekt som implementerar vissa datastrukturer i olika Python-mikrotjänster.
Till exempel lagrar Redis en hashmap av formen "telegram_user_id => antal aktiva uppgifter i kön", som låter dig begränsa antalet förfrågningar från en användare till ett visst värde och därmed förhindra DoS-attacker.
Låt oss formalisera processen för framgångsrik bildbehandling
- Användaren skickar en bild till Telegram-boten
- "attrai-telegram-bot" tar emot ett meddelande från Telegram API och analyserar det
- Uppgiften med bilden läggs till i den asynkrona kön "to_estimate"
- Användaren får ett meddelande med den planerade bedömningstiden
- "attrai-estimator" tar en uppgift från "to_estimate"-kön, kör uppskattningarna genom pipelinen och producerar uppgiften i "after_estimate"-kön
- "attrai-telegram-bot" lyssnar på "after_estimate"-kön och skickar resultatet till användaren
DevOps
Slutligen, efter att ha granskat arkitekturen, kan du gå vidare till den lika intressanta delen - DevOps
Docker svärm
Med hjälp av en "svärm" kan alla noder i vårt kluster delas in i 2 typer - arbetare och chef. På maskiner av den första typen är grupper av containrar (stackar) utplacerade, maskiner av den andra typen ansvarar för skalning, balansering och
Kluster med en ledare och tre arbetare
Minsta möjliga klusterstorlek är 1 nod; en enda maskin kommer samtidigt att fungera som en ledare och en arbetare. Baserat på projektets storlek och minimikraven för feltolerans beslutades att använda detta tillvägagångssätt.
Framöver kommer jag att säga att sedan den första produktionsleveransen, som var i mitten av juni, har det inte funnits några problem förknippade med denna klusterorganisation (men detta betyder inte att en sådan organisation på något sätt är acceptabel i någon medium-stor projekt som omfattas av feltoleranskrav).
Docker Stack
I svärmläge är han ansvarig för att distribuera stackar (uppsättningar av dockningstjänster)
Den stöder docker-compose-konfigurationer, så att du kan använda distributionsalternativ.
Till exempel, med dessa parametrar, var resurserna för var och en av utvärderingsmikrotjänstinstanserna begränsade (vi allokerar N kärnor för N instanser, i själva mikrotjänsten begränsar vi antalet kärnor som används av PyTorch till en)
attrai_estimator:
image: 'erqups/attrai_estimator:1.2'
deploy:
replicas: 4
resources:
limits:
cpus: '4'
restart_policy:
condition: on-failure
…
Det är viktigt att notera att Redis, RabbitMQ och Graylog är statliga tjänster och de kan inte skalas lika lätt som "attrai-estimator"
Förespelar frågan - varför inte Kubernetes?
Det verkar som att användningen av Kubernetes i små och medelstora projekt är en overhead; all nödvändig funktionalitet kan erhållas från Docker Swarm, som är ganska användarvänlig för en containerorkesterare och dessutom har en låg inträdesbarriär.
Infrastruktur
Allt detta distribuerades på VDS med följande egenskaper:
- CPU: 4-kärnig Intel® Xeon® Gold 5120 CPU @ 2.20 GHz
- RAM: 8 GB
- SSD: 160GB
Efter lokal belastningstestning verkade det som om den här maskinen skulle räcka med ett seriöst tillflöde av användare.
Men direkt efter implementeringen lade jag upp en länk till en av de mest populära imageboards i CIS (yup, samma), varefter folk blev intresserade och på några timmar bearbetade tjänsten tiotusentals bilder framgångsrikt. Samtidigt, vid toppögonblick, användes inte ens CPU- och RAM-resurser till hälften.
Lite mer grafik
Antal unika användare och utvärderingsförfrågningar sedan implementeringen, beroende på dag
Utvärdering pipeline slutledning tidsfördelning
Resultat
För att sammanfatta kan jag säga att arkitekturen och tillvägagångssättet för orkestrering av containrar helt rättfärdigade sig själva - även vid toppögonblick fanns det inga droppar eller sjunkande bearbetningstider.
Jag tror att små och medelstora projekt som använder realtidsinferens av neurala nätverk på processorn i sin process framgångsrikt kan anta de metoder som beskrivs i den här artikeln.
Jag ska tillägga att artikeln från början var längre, men för att inte lägga upp en longread bestämde jag mig för att utelämna några punkter i den här artikeln - vi återkommer till dem i framtida publikationer.
Du kan peta boten på Telegram - @AttraiBot, den kommer att fungera åtminstone till slutet av hösten 2020. Låt mig påminna dig om att ingen användardata lagras - varken originalbilderna eller resultatet av utvärderingspipelinen - allt rivs efter bearbetning.
Källa: will.com