"Gå i mina skor" - vänta, är de märkta?

Sedan 2019 har Ryssland haft en lag om obligatorisk märkning. Lagen gäller inte alla varugrupper och datumen för ikraftträdandet av obligatorisk märkning för produktgrupper är olika. Tobak, skor och mediciner blir de första som märks obligatoriskt, andra produkter kommer att läggas till senare, till exempel parfym, textilier och mjölk. Denna lagstiftningsinnovation föranledde utvecklingen av nya IT-lösningar som gör det möjligt att spåra hela livskedjan för en produkt från produktion till köp av slutkonsumenten, till alla deltagare i processen: både staten själv och alla organisationer som säljer varor med obligatorisk märkning.

I X5 heter systemet som kommer att spåra märkta varor och utbyta data med staten och leverantörer "Marcus". Låt oss berätta i ordning hur och vem som har utvecklat den, vad dess teknologistapel är och varför vi har något att vara stolta över.

"Gå i mina skor" - vänta, är de märkta?

Riktig högbelastning

"Marcus" löser många problem, det viktigaste är integrationsinteraktionen mellan X5 informationssystem och det statliga informationssystemet för märkta produkter (GIS MP) för att spåra rörelsen av märkta produkter. Plattformen lagrar också alla märkningskoder som vi fått och hela historiken för dessa koders förflyttning över objekt, och hjälper till att eliminera omgradering av märkta produkter. Med exemplet med tobaksprodukter, som ingick i de första grupperna av märkta varor, innehåller bara en lastbil cigaretter cirka 600 000 förpackningar, som var och en har sin egen unika kod. Och uppgiften för vårt system är att spåra och verifiera lagligheten av rörelserna för varje sådan förpackning mellan lager och butiker, och slutligen verifiera tillåtligheten av deras försäljning till slutköparen. Och vi registrerar cirka 125 000 kontanttransaktioner per timme, och vi behöver också registrera hur varje sådant paket kom in i butiken. Med hänsyn till alla rörelser mellan objekt förväntar vi oss alltså tiotals miljarder rekord per år.

Team M

Trots att Marcus betraktas som ett projekt inom X5, genomförs det med hjälp av en produktansats. Teamet arbetar enligt Scrum. Projektet startade förra sommaren, men de första resultaten kom först i oktober – vårt eget team var färdigmonterat, systemarkitekturen utvecklades och utrustning köptes in. Nu har teamet 16 personer, varav sex är involverade i backend- och frontend-utveckling, varav tre är involverade i systemanalys. Ytterligare sex personer är involverade i manuell, lastning, automatiserad testning och produktunderhåll. Dessutom har vi en SRE-specialist.

Inte bara utvecklare skriver kod i vårt team, nästan alla killar vet hur man programmerar och skriver autotester, laddar skript och automatiseringsskript. Vi lägger särskild vikt vid detta, eftersom även produktsupport kräver en hög grad av automatisering. Vi försöker alltid ge råd och hjälpa kollegor som inte har programmerat tidigare, och ge dem några små uppgifter att jobba med.

På grund av coronavirus-pandemin överförde vi hela teamet till distansarbete; tillgången på alla verktyg för utvecklingshantering, det inbyggda arbetsflödet i Jira och GitLab gjorde det möjligt att enkelt klara detta stadium. De månader som tillbringades på distans visade att teamets produktivitet inte blev lidande som ett resultat; för många ökade komforten på jobbet, det enda som saknades var direktkommunikation.

Fjärrgruppsmöte

"Gå i mina skor" - vänta, är de märkta?

Möten under distansarbete

"Gå i mina skor" - vänta, är de märkta?

Teknikstapel av lösningen

Standardförrådet och CI/CD-verktyget för X5 är GitLab. Vi använder den för kodlagring, kontinuerlig testning och distribution till test- och produktionsservrar. Vi använder också praxis för kodgranskning, när minst 2 kollegor behöver godkänna ändringar som görs av utvecklaren i koden. Statiska kodanalysatorer SonarQube och JaCoCo hjälper oss att hålla vår kod ren och säkerställa den erforderliga nivån av enhetstesttäckning. Alla ändringar av koden måste gå igenom dessa kontroller. Alla testskript som körs manuellt automatiseras därefter.

För en framgångsrik implementering av affärsprocesser av "Marcus" var vi tvungna att lösa ett antal tekniska problem, ungefär var och en i ordning.

Uppgift 1. Behovet av horisontell skalbarhet av systemet

För att lösa detta problem valde vi en mikrotjänstmetod för arkitektur. Samtidigt var det mycket viktigt att förstå tjänsternas ansvarsområden. Vi försökte dela upp dem i affärsverksamheter, med hänsyn till processernas särdrag. Till exempel är acceptans på ett lager inte en mycket frekvent, men mycket storskalig operation, under vilken det är nödvändigt att snabbt få information från den statliga regulatorn om varuenheterna som accepteras, vars antal i en leverans når 600000 XNUMX , kontrollera tillåtligheten av att acceptera denna produkt i lagret och returnera all nödvändig information för lagerautomatiseringssystemet. Men leveranser från lager har en mycket större intensitet, men arbetar samtidigt med små datamängder.

Vi implementerar alla tjänster på statslös basis och försöker till och med dela upp den interna verksamheten i steg, med hjälp av vad vi kallar Kafka självämnen. Det är då en mikrotjänst skickar ett meddelande till sig själv, vilket gör att du kan balansera belastningen på mer resurskrävande verksamhet och förenklar produktunderhållet, men mer om det senare.

Vi beslutade att separera moduler för interaktion med externa system i separata tjänster. Detta gjorde det möjligt att lösa problemet med ofta ändrade API:er för externa system, med praktiskt taget ingen inverkan på tjänster med affärsfunktionalitet.

"Gå i mina skor" - vänta, är de märkta?

Alla mikrotjänster är utplacerade i ett OpenShift-kluster, vilket löser både problemet med att skala varje mikrotjänst och tillåter oss att inte använda tredjepartsverktyg för att upptäcka tjänster.

Uppgift 2. Behovet av att upprätthålla en hög belastning och mycket intensivt datautbyte mellan plattformstjänster: Bara under projektstartfasen utförs cirka 600 operationer per sekund. Vi förväntar oss att detta värde kommer att öka till 5000 XNUMX ops/sek när butiker ansluter till vår plattform.

Detta problem löstes genom att distribuera ett Kafka-kluster och nästan helt överge synkron interaktion mellan plattformens mikrotjänster. Detta kräver en mycket noggrann analys av systemkraven, eftersom inte alla operationer kan vara asynkrona. Samtidigt överför vi inte bara händelser genom mäklaren, utan överför också all nödvändig affärsinformation i meddelandet. Således kan meddelandestorleken nå flera hundra kilobyte. Gränsen för meddelandestorlek i Kafka kräver att vi exakt förutsäger meddelandestorleken, och vid behov delar vi upp dem, men uppdelningen är logisk, relaterad till affärsverksamheten.
Till exempel delar vi upp varor som kommer i en bil i lådor. För synkrona operationer tilldelas separata mikrotjänster och grundlig lasttestning utförs. Att använda Kafka gav oss en annan utmaning - att testa driften av vår tjänst med hänsyn till Kafka-integrationen gör alla våra enhetstester asynkrona. Vi löste detta problem genom att skriva våra egna verktygsmetoder med Embedded Kafka Broker. Detta eliminerar inte behovet av att skriva enhetstester för enskilda metoder, men vi föredrar att testa komplexa fall med Kafka.

Mycket uppmärksamhet ägnades åt att spåra loggar så att deras TraceId inte skulle gå förlorad när undantag inträffar under driften av tjänster eller när man arbetar med Kafka batch. Och om det inte fanns några speciella problem med det första, så tvingas vi i det andra fallet logga alla TraceIds som partiet kom med och välja ett för att fortsätta spåra. Sedan, när du söker med det ursprungliga TraceId, kommer användaren enkelt att ta reda på med vilken spårningen fortsatte.

Uppgift 3. Behovet av att lagra en stor mängd data: Mer än 1 miljard etiketter per år för enbart tobak kommer till X5. De kräver konstant och snabb åtkomst. Totalt måste systemet bearbeta cirka 10 miljarder register över rörelsehistoriken för dessa märkta varor.

För att lösa det tredje problemet valdes NoSQL-databasen MongoDB. Vi har byggt en skärva med 5 noder och varje nod har en replikuppsättning med 3 servrar. Detta gör att du kan skala systemet horisontellt, lägga till nya servrar till klustret och säkerställa dess feltolerans. Här stötte vi på ett annat problem - att säkerställa transaktionalitet i mongo-klustret, med hänsyn till användningen av horisontellt skalbara mikrotjänster. Till exempel är en av uppgifterna i vårt system att identifiera försök att återförsälja produkter med samma märkningskoder. Här visas överlägg med felaktiga skanningar eller felaktiga operationer av kassapersonal. Vi fann att sådana dubbletter kan förekomma både inom en Kafka-sats som bearbetas och inom två satser som bearbetas parallellt. Att leta efter dubbletter genom att fråga databasen gav alltså ingenting. För varje mikrotjänst löste vi problemet separat baserat på den här tjänstens affärslogik. Till exempel, för kontroller, lade vi till en kontroll i batch och separat bearbetning för utseendet av dubbletter vid insättning.

För att säkerställa att användarnas arbete med verksamhetshistoriken inte på något sätt påverkar det viktigaste - hur våra affärsprocesser fungerar, har vi separerat all historisk data i en separat tjänst med en separat databas, som även tar emot information genom Kafka . På så sätt arbetar användarna med en isolerad tjänst utan att det påverkar tjänsterna som behandlar data för pågående verksamhet.

Uppgift 4: Köupparbetning och övervakning:

I distribuerade system uppstår oundvikligen problem och fel i tillgängligheten av databaser, köer och externa datakällor. I Marcus fall är källan till sådana fel integration med externa system. Det var nödvändigt att hitta en lösning som skulle tillåta upprepade förfrågningar om felaktiga svar med viss specificerad timeout, men samtidigt inte sluta behandla lyckade förfrågningar i huvudkön. För detta ändamål valdes det så kallade "topic based retry"-konceptet. För varje huvudämne skapas ett eller flera återförsöksämnen till vilka felaktiga meddelanden skickas och samtidigt elimineras förseningen i behandlingen av meddelanden från huvudämnet. Interaktionsschema -

"Gå i mina skor" - vänta, är de märkta?

För att implementera ett sådant schema behövde vi följande: att integrera denna lösning med Spring och undvika kodduplicering. När vi surfade på nätet stötte vi på en liknande lösning baserad på Spring BeanPostProccessor, men den verkade onödigt krånglig för oss. Vårt team har skapat en enklare lösning som gör att vi kan integreras i vårcykeln för att skapa konsumenter och dessutom lägga till Retry Consumers. Vi erbjöd en prototyp av vår lösning till Spring-teamet, du kan se den här. Antalet Försök igen konsumenter och antalet försök för varje konsument konfigureras genom parametrar, beroende på behoven i affärsprocessen, och för att allt ska fungera återstår bara att lägga till anteckningen org.springframework.kafka.annotation.KafkaListener , som är bekant för alla Spring-utvecklare.

Om meddelandet inte kunde bearbetas efter alla återförsök, går det till DLT (dead letter topic) med Spring DeadLetterPublishingRecoverer. På begäran av support utökade vi denna funktionalitet och skapade en separat tjänst som låter dig se meddelanden som ingår i DLT, stackTrace, traceId och annan användbar information om dem. Dessutom lades övervakning och varningar till alla DLT-ämnen, och nu är faktiskt förekomsten av ett meddelande i ett DLT-ämne en anledning att analysera och åtgärda en defekt. Detta är mycket bekvämt - med namnet på ämnet förstår vi omedelbart i vilket steg i processen problemet uppstod, vilket avsevärt påskyndar sökningen efter dess grundorsak.

"Gå i mina skor" - vänta, är de märkta?

Senast har vi implementerat ett gränssnitt som gör att vi kan skicka meddelanden igen med hjälp av vårt stöd efter att ha eliminerat deras orsaker (till exempel återställt funktionaliteten hos det externa systemet) och, naturligtvis, etablerat motsvarande defekt för analys. Det är här våra självämnen kommer väl till pass: för att inte starta om en lång bearbetningskedja kan du starta om den från önskat steg.

"Gå i mina skor" - vänta, är de märkta?

Plattformsdrift

Plattformen är redan i produktiv drift, varje dag utför vi leveranser och försändelser, kopplar ihop nya distributionscenter och butiker. Som en del av pilotprojektet arbetar systemet med produktgrupperna "Tobak" och "Skor".

Hela vårt team deltar i att genomföra piloter, analyserar uppkommande problem och ger förslag på förbättringar av vår produkt, från förbättring av loggar till att förändra processer.

För att inte upprepa våra misstag återspeglas alla fall som hittas under piloten i automatiserade tester. Närvaron av ett stort antal autotester och enhetstester gör att du kan utföra regressionstestning och installera en snabbkorrigering bokstavligen inom några timmar.

Nu fortsätter vi att utveckla och förbättra vår plattform och står ständigt inför nya utmaningar. Om du är intresserad kommer vi att prata om våra lösningar i följande artiklar.

Källa: will.com

Lägg en kommentar