"Walking in my shoes" — vĂ€nta, Ă€r de mĂ€rkta?

Sedan 2019 har det funnits en lag i Ryssland om obligatorisk mÀrkning. Lagen gÀller inte alla varugrupper, och tidsramarna för införandet av obligatorisk mÀrkning för olika varugrupper Àr olika. De första produkterna som omfattas av obligatorisk mÀrkning Àr tobak, skor och lÀkemedel; senare kommer Àven andra produkter som parfymer, textilier och mjölk att lÀggas till. Denna lagstiftningsnyhet har lett till utvecklingen av nya IT-lösningar som gör det möjligt att spÄra hela livscykeln för en produkt frÄn produktion till köp av slutanvÀndaren, bÄde för staten och alla organisationer som sÀljer produkter med obligatorisk mÀrkning.

I X5 har systemet som ska spĂ„ra produkter med mĂ€rkning och utbyta data med staten och leverantörer fĂ„tt namnet “Markus”. Vi berĂ€ttar i tur och ordning hur och av vem det har utvecklats, vilken teknologistack det har och varför vi har anledning att vara stolta.

"Walking in my shoes" — vĂ€nta, Ă€r de mĂ€rkta?

Verklig HighLoad

“Markus” löser mĂ„nga uppgifter, den viktigaste av dem Ă€r integrationsinteraktionen mellan informationssystemen hos X5 och statens informationssystem för mĂ€rkta produkter (GIS MP) för att spĂ„ra rörelsen av mĂ€rkta produkter. Plattformen lagrar ocksĂ„ alla mottagna mĂ€rkningkoder och hela historien om dessa koders rörelse mellan objekt, och hjĂ€lper till att eliminera förvĂ€xlingar med mĂ€rkta produkter. Till exempel, med tobaksprodukter som ingĂ„r i de första grupperna av mĂ€rkta varor, innehĂ„ller endast en bil med cigaretter cirka 600 000 paket, som vart och ett har sin egen unika kod. VĂ„r uppgift Ă€r att spĂ„ra och verifiera lagligheten av flytten av varje sĂ„dant paket mellan lager och butiker, och i slutĂ€ndan verifiera möjligheten att sĂ€lja dem till slutkonsumenten. Vi registrerar cirka 125 000 kassatransaktioner i timmen, och vi mĂ„ste Ă€ven registrera hur varje paket kom in i butiken. Med tanke pĂ„ alla flyttningar mellan objekt förvĂ€ntar vi oss tiotals miljarder poster per Ă„r.

Team M

Trots att "Markus" betraktas som ett projekt inom X5, genomförs det utifrÄn en produktansats. Teamet arbetar enligt Scrum. Projektet startade sommaren förra Äret, men de första resultaten kom först i oktober - teamet sattes samman, systemarkitekturen utvecklades och utrustning köptes in. Idag bestÄr teamet av 16 personer, varav sex arbetar med backend- och frontendutveckling, tre med systemanalys. Ytterligare sex personer ansvarar för manuell, belastning, automatiserad testning och produktunderhÄll. Dessutom har vi en SRE-specialist.

I vÄrt team skriver inte bara utvecklare kod, nÀstan alla i gruppen kan programmera och skriver automatiserade tester, belastningsskript och automatiseringsskript. Vi lÀgger stor vikt vid detta, eftersom Àven produktunderhÄll krÀver en hög nivÄ av automatisering. Vi försöker alltid hjÀlpa kollegor som tidigare inte programmerat genom att ge dem smÄ uppgifter.

Med anledning av coronaviruspandemin har vi övergÄtt till distansarbete. Tillsammans med vÄr tillgÄng till alla verktyg för att hantera utvecklingen och den uppbyggda arbetsflödet i Jira och GitLab, lyckades vi enkelt klara denna fas. De mÄnader som spenderades pÄ distans visade att teamets produktivitet inte pÄverkades, för mÄnga ökade komforten i arbetet, det enda som saknas Àr det personliga mötet.

Teamets möte före distansarbetet

"Walking in my shoes" — vĂ€nta, Ă€r de mĂ€rkta?

Möten under distansarbetet

"Walking in my shoes" — vĂ€nta, Ă€r de mĂ€rkta?

Den tekniska stacken för lösningen

Den standardrepository och CI/CD-verktyget för X5 Àr GitLab. Vi anvÀnder det för att lagra koden, kontinuerlig testning, och distribution pÄ test- och produktionsservrar. Vi tillÀmpar Àven en code review-praxis, dÀr minst tvÄ kollegor mÄste godkÀnna de förÀndringar som utvecklaren gjort i koden. De statiska kodanalysatorerna SonarQube och JaCoCo hjÀlper oss att hÄlla koden ren och sÀkerstÀlla att den nödvÀndiga nivÄn av enhetstestning upprÀtthÄlls. Alla kodÀndringar mÄste först genomgÄ dessa kontroller. Alla testscenarier som körs manuellt automatiseras senare.

För att framgÄngsrikt genomföra affÀrsprocesserna med "Markus" var vi tvungna att lösa ett antal tekniska utmaningar, en i taget.

Uppgift 1. Behov av horisontell skalbarhet i systemet

För att lösa denna uppgift valde vi en mikrotjĂ€nstarkitektur. Det var mycket viktigt att förstĂ„ ansvarsomrĂ„dena för tjĂ€nsterna. Vi försökte dela upp dem utifrĂ„n affĂ€rsoperationer med hĂ€nsyn till processernas specifik. Till exempel, mottagningen pĂ„ lagret Ă€r en ovanlig, men mycket omfattande operation, dĂ€r man snabbt mĂ„ste fĂ„ information frĂ„n myndigheterna om de mottagna varorna, dĂ€r antalet i en leverans kan nĂ„ upp till 600000, kontrollera om det Ă€r tillĂ„tet att ta emot dessa varor pĂ„ lagret och ge all nödvĂ€ndig information till lagrets automatiseringssystem. Å andra sidan har utfoutskick frĂ„n lagren en mycket högre intensitet, men arbetar med mindre datavolymer.

Vi implementerar alla tjÀnster enligt stateless-principen och försöker Àven dela upp interna operationer i steg, genom att anvÀnda det vi kallar self-Àmnen i Kafka. Detta innebÀr att mikrotjÀnsten skickar meddelanden till sig sjÀlv, vilket gör att belastningen pÄ mer resurskrÀvande operationer kan fördelas och förenklar produktunderhÄll, men mer om detta senare.

Vi beslutade att separera modulerna för interaktion med externa system i egna tjÀnster. Detta löste problemet med snabbt förÀnderliga API:er i externa system, nÀstan utan pÄverkan pÄ tjÀnster med affÀrsfunktionalitet.

"Walking in my shoes" — vĂ€nta, Ă€r de mĂ€rkta?

Alla mikrotjÀnster distribueras i en OpenShift-kluster, vilket bÄde hanterar problem med skalning av varje mikrotjÀnst och gör att vi kan undvika att anvÀnda externa verktyg för Service Discovery.

Uppgift 2. Behov av att stödja hög belastning och mycket intensiv datakommunikation mellan plattformens tjÀnster: bara i projektets startfas genomförs cirka 600 operationer per sekund. Vi förvÀntar oss att detta vÀrde ökar till 5000 op/s i takt med att handelsobjekten kopplas till vÄr plattform.

Denna uppgift löstes genom att implementera en Kafka-kluster och praktiskt taget helt överge synkron interaktion mellan plattformens mikrotjÀnster. Detta krÀver en mycket noggrann analys av systemets krav, eftersom inte alla operationer kan vara asynkrona. Vi skickar inte bara hÀndelser via en broker, utan överför ocksÄ all nödvÀndig affÀrsinformation i meddelandet. DÀrför kan storleken pÄ meddelandet uppgÄ till flera hundra kilobyte. BegrÀnsningen av meddelandestorlek i Kafka krÀver att vi exakt kan förutsÀga meddelandestorlekar, och vid behov delar vi upp dem, men uppdelningen Àr logisk och relaterad till affÀrsoperationer.
Till exempel, för varor som anlĂ€nder med bil delar vi upp dem i lĂ„dor. För synkrona operationer avsĂ€tts separata mikrotjĂ€nster, och noggranna prestandatester utförs. AnvĂ€ndningen av Kafka stĂ€llde en annan utmaning för oss — att kontrollera hur vĂ„r tjĂ€nst fungerar med tanke pĂ„ integrationen av Kafka gör alla vĂ„ra enhetstester asynkrona. Denna uppgift löste vi genom att skriva egna tillgĂ€ngliga metoder med Embedded Kafka Broker. Detta avskaffar inte behovet av att skriva enhetstester för separata metoder, men för komplexa fall föredrar vi att testa med Kafka.

Vi har lagt mycket fokus pÄ loggtracing sÄ att deras TraceId inte gÄr förlorade vid undantag i tjÀnsternas drift eller vid hantering av Kafka-batchar. Om det första inte orsakade nÄgra sÀrskilda frÄgor, var vi i det andra fallet tvungna att logga alla TraceId som batchen kom med och vÀlja ett för att fortsÀtta spÄrningen. DÄ kan anvÀndaren enkelt hitta det ursprungliga TraceId och se vilket spÄrning som fortsatte.

Uppgift 3. Behovet av att lagra stora mÀngder data: mer Àn 1 miljard mÀrkningar per Är, bara för tobak, kommer in i X5. Dessa krÀver stÀndig och snabb Ätkomst. Totalt ska systemet hantera cirka 10 miljarder poster av datarörelser för mÀrkta varor.

För att lösa den tredje uppgiften valdes NoSQL-databasen MongoDB. Vi har byggt ett sharded kluster med 5 noder, och i varje nod finns en Replica Set med 3 servrar. Detta möjliggör horisontell skalning av systemet genom att lÀgga till nya servrar i klustret och sÀkerstÀlla dess fel-tolerans. HÀr stötte vi pÄ ett annat problem - att sÀkerstÀlla transaktionalitet i ett mongo-kluster med tanke pÄ anvÀndningen av horisontellt skalbara mikrotjÀnster. Till exempel Àr en av vÄra systems uppgifter att upptÀcka försök till ÄterförsÀljning av varor med samma mÀrkning. HÀr uppstÄr problem med felaktiga skanningar eller felaktiga kasörer. Vi har upptÀckt att sÄdana dubbletter kan uppkomma bÄde inom en behandlad Kafka-batch och inom tvÄ parallellt behandlade batches. DÀrför gav kontrollen av dubbletter genom en databasfrÄga ingenting. För varje mikrotjÀnst hanterade vi problemet separat baserat pÄ affÀrslogiken för den tjÀnsten. Till exempel har vi för kvitton lagt till en kontroll inom batchen och en separat hantering för att upptÀcka dubbletter vid insÀttning.

För att anvÀndarnas arbete med transaktionshistorik inte skulle pÄverka det mest centrala - funktionen av vÄra affÀrsprocesser, har vi separerat all historisk data i en sÀrskild tjÀnst med en sÀrskild databas, som ocksÄ fÄr information genom Kafka. PÄ sÄ sÀtt arbetar anvÀndarna med en isolerad tjÀnst utan att pÄverka de tjÀnster som hanterar data om aktuella transaktioner.

Uppgift 4. Ombehandling av köer och övervakning:

I distribuerade system uppstÄr oundvikligen problem och fel med tillgÄng till databaser, köer och externa datakÀllor. I fallet med "Markus" Àr kÀllan till sÄdana fel integrationen med externa system. Det var nödvÀndigt att hitta en lösning som skulle möjliggöra omförfrÄgningar vid felaktiga svar med en viss timeout, men utan att avbryta behandlingen av framgÄngsrika förfrÄgningar i den primÀra kön. För detta valdes den sÄ kallade konceptet "topic based retry". För varje huvudtopic skapas en eller flera retry-topics dit felaktiga meddelanden dirigeras, vilket samtidigt utesluter fördröjning i behandlingen av meddelanden frÄn huvudtoppen. Kommunikationsschemat -

"Walking in my shoes" — vĂ€nta, Ă€r de mĂ€rkta?

För att genomföra denna lösning behövde vi integrera den med Spring och undvika kodduplicering. Vi stötte pÄ en liknande lösning online, baserad pÄ Spring BeanPostProcessor, men den verkade onödigt tungrodd. VÄrt team skapade en enklare lösning som gör det möjligt att integrera med Spring-cykeln för att skapa konsumenter och dessutom lÀgga till Retry-konsumenter. Prototypen av vÄr lösning presenterade vi för Spring-teamet, den kan ses ). Ett typiskt exempel pÄ anvÀndning:. Antalet Retry-konsumenter och antalet försök för varje konsument kan konfigureras via parametrar, beroende pÄ behov inom affÀrsprocessen, och för att allt ska fungera krÀvs bara den vÀlkÀnda annoteringen org.springframework.kafka.annotation.KafkaListener som alla Spring-utvecklare kÀnner till.

Om ett meddelande inte kunde bearbetas efter alla retry-försök gÄr det till DLT (dead letter topic) med hjÀlp av Spring DeadLetterPublishingRecoverer. PÄ begÀran av supporten utvidgade vi denna funktion och skapade en separat tjÀnst som gör det möjligt att se meddelanden som hamnat i DLT, stackTrace, traceId och annan nyttig information om dem. Dessutom har övervakning och larm pÄ alla DLT-topiker lagts till, och i dagslÀget Àr ett meddelande i DLT-topiken i stort sett en anledning till att göra en felanmÀlan. Detta Àr mycket praktiskt - genom topikens namn förstÄr vi direkt vilket steg i processen problemet uppstod, vilket avsevÀrt pÄskyndar sökandet efter dess rotorsak.

"Walking in my shoes" — vĂ€nta, Ă€r de mĂ€rkta?

Nyligen implementerade vi ett grÀnssnitt som gör det möjligt att Äterigen skicka meddelanden med hjÀlp av vÄr support, efter att orsaken till problemen ÄtgÀrdats (till exempel ÄterstÀllande av den externa systemets funktionalitet) och givetvis gör en motsvarande felanmÀlan för analys. HÀr kom vÄra self-topiker till nytta, för att inte behöva starta om hela kedjan av bearbetning kan den startas om frÄn det önskade steget.

"Walking in my shoes" — vĂ€nta, Ă€r de mĂ€rkta?

Drift av plattformen

Plattformen Àr redan i produktiv drift, varje dag genomför vi leveranser och frakt, samt kopplar nya distributionscentra och butiker. Inom ramen för piloten fungerar systemet med produktgrupperna "Tobak" och "Skor".

Hela vÄrt team deltar i piloterna, analyserar de problem som uppstÄr och kommer med förslag pÄ förbÀttringar av vÄr produkt, frÄn att förbÀttra loggar till förÀndringar i processerna.

För att undvika att upprepa sina misstag Äterspeglas alla fall som upptÀckts under piloten i automatiserade tester. NÀrvaron av ett stort antal automatiserade tester och enhetstester möjliggör regressionsprovning och att tillÀmpa en hotfix bokstavligt talat inom nÄgra timmar.

Just nu fortsÀtter vi att utveckla och förbÀttra vÄr plattform och stöter stÀndigt pÄ nya utmaningar. Om du Àr intresserad kan vi berÀtta om vÄra lösningar i kommande artiklar.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster