Që nga viti 2019, një ligj për etiketime të detyrueshme është në fuqi në Rusi. Ky ligj nuk zbatohet për të gjitha grupet e Produkteve, dhe afatet për fillimin e etiketimeve të detyrueshme për grupe të ndryshme produktesh janë të ndryshme. Të parët që do të përfshihen në etiketim janë duhani, këpucët, ilaçet, ndërsa më vonë do të shtohen edhe produkte të tjera si parfumi, tekstili dhe qumështi. Ky ndryshim ligjor ka nxitur zhvillimin e zgjidhjeve të reja IT që do të mundësojnë ndjekjen e gjithë zinxhirit të jetës së produktit nga prodhimi deri te blerësi përfundimtar, për të gjithë pjesëmarrësit e procesit: si vetë shteti, ashtu edhe të gjitha organizatat që shesin produkte me etiketim të detyrueshëm.
Në H5, sistemi që do të ndjekë produktet me etiketim dhe do të shkëmbejë të dhëna me shtetin dhe furnizuesit, u quajt "Markus". Do të flasim rreth saj për rendin se si dhe kush e zhvilloi, çfarë është stack-u i saj teknologjik dhe pse kemi për të qenë krenarë.

HighLoad i vërtetë
"Markus" zgjidh shumë probleme, më kryesorja është ndërveprimi integrues midis sistemeve informative të H5 dhe sistemit informativ shtetëror për produktet e etiketuar (GIS MP) për ndjekjen e lëvizjes së produkteve të etiketuar. Gjithashtu, platforma ruan të gjitha kodet e etiketimeve që na kanë mbërritur dhe gjithë historinë e lëvizjes së këtyre kodit për objekte, ndihmon në eliminimin e gabimeve në ndarjen e produkteve të etiketuar. Për shembull, për produktet e duhanit, të cilat ishin në grupet e para të produkteve të etiketuar, vetëm një kamion me cigare përmban rreth 600,000 pako, secila prej të cilave ka kodin e saj unik. Dhe detyra e sistemit tonë është të ndjekë dhe të verifikojë ligjshmërinë e lëvizjeve të secilës pako të tillë midis depo dhe dyqaneve, dhe përfundimisht të verifikojë lejueshmërinë e shitjes së tyre për blerësin përfundimtar. Ne regjistrojmë rreth 125,000 operacione në orë dhe gjithashtu duhet të regjistrojmë si çdo pako e tillë ka mbërritur në dyqan. Në këtë mënyrë, duke marrë parasysh të gjitha lëvizjet midis objekteve, ne presim dhjetëra miliarda regjistrimesh në vit.
Ekipa M
MegjithĂ«se "Markusi" konsiderohet njĂ« projekt i H5, ai realizohet sipas njĂ« qasje produkti. Ekipi punon sipas metodologjisĂ« Scrum. Projekti filloi verĂ«n e vitit tĂ« kaluar, por rezultatet e para erdhĂ«n vetĂ«m nĂ« tetor â u formua plotĂ«sisht ekipi ynĂ«, u zhvillua arkitektura e sistemit dhe u ble njĂ« pajisje. Tani ekipi pĂ«rbĂ«het nga 16 persona, gjashtĂ« prej tĂ« cilĂ«ve punojnĂ« nĂ« zhvillimin backend dhe frontend, tre nĂ« analizĂ«n sistematike. Testimin manual, ngarkesĂ«n, testimin automatizuar dhe mbĂ«shtetje produkti e kryejnĂ« edhe gjashtĂ« persona tĂ« tjerĂ«. PĂ«rveç kĂ«saj, kemi njĂ« specialist SRE.
Kodi në ekipin tonë nuk shkruhet vetëm nga zhvillues, pothuajse të gjithë djemtë dinë të programojnë dhe shkruajnë teste automatike, skenare ngarkese dhe skenare automatizimi. Ne i kushtojmë shumë rëndësi kësaj, pasi edhe mbështetje e produktit kërkon një nivel të lartë automatizimi. Kolegët, të cilët nuk kanë programuar më parë, gjithmonë përpiqemi t'u japim ndihmë dhe t'i mbështesim, duke u dhënë disa detyra të vogla.
Për shkak të pandemisë së infeksionit me koronavirus, ne e kemi kaluar të gjithë ekipin në punë të largët, disponimi i të gjitha mjeteve për menaxhimin e zhvillimit, struktura e punës e ndërtuar në Jira dhe GitLab na lejuan të kalojmë lehtësisht këtë fazë. Muaj të kaluar në punë të largët treguan se produktiviteti i ekipit nuk u prek, për shumë nga ta komoditeti në punë u rrit, e vetmja gjë, na mungon komunikimi i drejtpërdrejtë.
Takimi i ekipit para punës në distancë

Takimet gjatë punës në distancë

Stoku teknologjik i zgjidhjes
Repo standard dhe mjeti CI/CD për H5 është GitLab. Ne e përdorim për ruajtjen e kodit, testimin e vazhdueshëm, dhe shpërndarjen në serverët testues dhe në ata produktivë. Po ashtu, ne përdorim praktikën e review-it të kodit, ku të paktën dy kolegë duhet të miratojnë ndryshimet që zhvilluesi bën në kod. Analizuesit statikë të kodit SonarQube dhe JaCoCo na ndihmojnë të mbajmë kodin të pastër dhe të sigurojmë nivelin e kërkuar të mbulimit me teste unitare. Të gjitha ndryshimet në kodin duhet të kalojnë përmes këtyre kontrollimeve. Të gjitha skenarët e testeve, të cilët ekzekutohen manualisht, më vonë automatizohen.
Për të realizuar me sukses proceset e biznesit me "Markusin", na u desh të zgjidhnim një sërë problemesh teknologjike, për secilën nga të cilat do të flasim me radhë.
Detyra 1. Nevoja për zgjerimin horizontal të sistemit
Për të zgjidhur këtë detyrë, ne zgjodhëm qasjen mikrosherbimeve në arkitekturë. Në këtë kuadër, ishte shumë e rëndësishme të kuptohet fushat e përgjegjësisë së shërbimeve. Ne u përpoqëm t'i ndajmë ato sipas operacioneve të biznesit duke marrë parasysh karakteristikat e proceseve. Për shembull, pranimi në magazinë është një operacion jo shumë i shpeshtë, por shumë i voluminshëm, gjatë të cilit duhet të marrim sa më shpejt informacionin nga autoriteti shtetëror për njësi të pranuara të mallrave, numri i të cilave në një dërgesë arrin deri në 600,000, të kontrollojmë lejueshmërinë e pranimit të këtij malli në magazinë dhe të dërgojmë të gjitha informacionet e nevojshme në sistemin e automatizimit të magazinës. Ndërsa, dërgesa nga magazinat ka një intensitet shumë më të madh, por operon me të dhëna më të vogla.
Të gjithë shërbimet i realizojmë sipas parimit stateless dhe madje përpiqemi të ndajmë operacionet e brendshme në hapa, duke përdorur, siç i quajmë ne, self-temat Kafka. Kjo është kur mikrosherbimi dërgon një mesazh vetes, gjë që lejon balancimin e ngarkesës mbi operacionet më burimëvne dhe thjeshtëson mirëmbajtjen e produktit, por për këtë më vonë.
Ne vendosëm t'i ndajmë në shërbime të veçanta modulet e ndërveprimit me sistemet e jashtme. Kjo ndihmoi në zgjidhjen e problemit të API-ve të jashtme që shpesh ndryshojnë, pa ndonjë ndikim në shërbimet me funksionalitetin e biznesit.

Të gjithë mikrosherbimet zhvillohen në klasterin OpenShift, i cili zgjidh si problemin e zgjerimit të çdo mikrosherbimi, ashtu edhe na lejon të mos përdorim mjete të jashtme të Zbulimit të Shërbimeve.
Detyra 2. Nevoja për të mbajtur një ngarkesë të lartë dhe shkëmbim shumë intensiv të të dhënave midis shërbimeve të platformës: vetëm në fazën e nisjes së projektit, kryhen rreth 600 operacione në sekondë. Ne presim që kjo vlerë të rritet deri në 5000 op/sec ndërsa lidhim objektet tregtare me platformën tonë.
Kjo detyrë u zgjidh duke shpërndarë një klaster Kafka dhe duke u hequr praktikisht nga ndërveprimi sinkron mes mikroshërbimeve të platformës. Kjo kërkon një analizë shumë të kujdesshme të kërkesave për sistemin, sepse jo të gjitha operacionet mund të jenë asinkrone. Në të njëjtën kohë, ne jo vetëm që transferojmë ngjarje përmes brokerit, por gjithashtu transferojmë në mesazh të gjitha informacionet e nevojshme biznesore. Si rezultat, madhësia e mesazhit mund të arrijë deri në disa qindra kilobajt. Kufizimi i madhësisë së mesazheve në Kafka kërkon që ne të parashikojmë saktësisht madhësinë e mesazheve, dhe, nëse është e nevojshme, i ndajmë ato, por ndarja është logjike, e lidhur me operacionet e biznesit.
Për shembull, produktin që ka ardhur me makinë, ne e ndajmë sipas kutive. Për operacionet sinkrone janë rezervuar mikroshërbise të veçanta dhe bëhet testim i kujdesshëm i ngarkesës. Përdorimi i Kafka na vendosi përballë një sfide tjetër - verifikimi i funksionimit të shërbimit tonë me përfshirjen e Kafka bën që të gjitha testet tona unit të jenë asinkrone. Këtë detyrë e zgjidhëm duke shkruar metoda të përdorura vetë me përdorimin e Embedded Kafka Broker. Kjo nuk përjashton nevojën për të shkruar teste unit për metoda të veçanta, por ne preferojmë të testojmë rastet e komplikuara duke përdorur Kafka.
Kemi kushtuar shumë vëmendje gjurmimit të log-ve, në mënyrë që TraceId e tyre të mos humbasin gjatë shfaqjes së përjashtimeve gjatë punës së shërbimeve ose gjatë punës me Kafka batch. Dhe nëse me rastin e parë nuk kishte ndonjë pyetje të veçantë, për rastin e dytë na nevojitet të regjistrojmë në log të gjitha TraceId që kanë ardhur me batch-in dhe të zgjedhim një për të vazhduar gjurmimin. Atëherë, kur kërkon me TraceId fillestar, përdoruesi do të zbulojë lehtësisht me cilin ka vazhduar gjurmimi.
Detyra 3. Nevoja për të ruajtur një sasi të madhe të të dhënave: më shumë se 1 miliard etiketash në vit vetëm për duhanin arrijnë në X5. Këto kërkojnë akses të vazhdueshëm dhe të shpejtë. Përgjithësisht sistemi duhet të përpunojë rreth 10 miliardë regjistrime për historinë e lëvizjes së të dhënave të produkteve të etiketuar.
PĂ«r zgjidhjen e detyrĂ«s sĂ« tretĂ« u zgjodh databaza NoSQL MongoDB. Ne kemi ndĂ«rtuar njĂ« shard prej 5 nodash dhe nĂ« çdo nod ka njĂ« Replica Set prej 3 serverĂ«sh. Kjo lejon qĂ« sistemi tĂ« shkallzohet horizontalisht, duke shtuar servera tĂ« rinj nĂ« grupin, dhe tĂ« sigurojĂ« qĂ« ajo tĂ« jetĂ« e qĂ«ndrueshme. KĂ«tu u pĂ«rballĂ«m me njĂ« problem tjetĂ«r â sigurimin e transaksionit nĂ« grupin mongo, duke marrĂ« parasysh pĂ«rdorimin e mikrosĂ«rvices horizontalisht tĂ« shkallĂ«zuar. PĂ«r shembull, njĂ« nga detyrat e sistemit tonĂ« Ă«shtĂ« tĂ« identifikojĂ« pĂ«rpjekjet e ripĂ«rsĂ«ritjes sĂ« shitjes sĂ« artikujve me kode tĂ« njĂ«jta markimi. KĂ«tu shfaqen ngatĂ«rrime me skanime tĂ« gabuara ose me veprime tĂ« gabuara nga kasĂ«tarĂ«t. Zbuluam se kĂ«to dublika mund tĂ« lindin si brenda njĂ« batch tĂ« pĂ«rpunuar nga Kafka, ashtu edhe brenda dy batch-eve qĂ« pĂ«rpunohen paralelisht. KĂ«shtu qĂ« kontrolli pĂ«r shfaqjen e dublikeve pĂ«rmes kĂ«rkesĂ«s nĂ« bazĂ« nuk jepte asnjĂ« rezultat. PĂ«r secilin nga mikrosĂ«rvices, ne e zgjidhĂ«m problemin veçmas, duke u bazuar nĂ« logjikĂ«n e biznesit tĂ« kĂ«tij shĂ«rbimi. PĂ«r shembuj, pĂ«r çekĂ«t shtuam njĂ« kontroll brenda batch dhe njĂ« pĂ«rpunim tĂ« veçantĂ« pĂ«r shfaqjen e dublikeve gjatĂ« inserimit.
PĂ«r tĂ« siguruar qĂ« puna e pĂ«rdoruesve me historinĂ« e operacioneve tĂ« mos ndikonte nĂ« mĂ« tĂ« rĂ«ndĂ«sishmen â funksionimin e proceseve tona biznesore, tĂ« gjitha tĂ« dhĂ«nat historike i kemi dedikuar njĂ« shĂ«rbimi tĂ« veçantĂ« me njĂ« bazĂ« tĂ« dhĂ«nash tĂ« veçantĂ«, e cila gjithashtu merr informacion pĂ«rmes Kafka. KĂ«shtu, pĂ«rdoruesit punojnĂ« me njĂ« shĂ«rbim tĂ« izoluar, pa ndikuar nĂ« shĂ«rbimet qĂ« pĂ«rpunojnĂ« tĂ« dhĂ«nat pĂ«r operacionet aktuale.
Detyra 4. Riprocesimi i radhëve dhe monitorimi:
NĂ« sistemet e shpĂ«rndara, problemet dhe gabimet e disponueshmĂ«risĂ« sĂ« bazave tĂ« tĂ« dhĂ«nave, radhĂ«ve dhe burimeve tĂ« jashtme tĂ« tĂ« dhĂ«nave janĂ« tĂ« pashmangshme. NĂ« rastin e 'Markus', burimi i kĂ«tyre gabimeve Ă«shtĂ« integrimi me sistemet e jashtme. Duhej tĂ« gjenim njĂ« zgjidhje qĂ« tĂ« lejonte kryerjen e kĂ«rkesave tĂ« ripĂ«rsĂ«ritura pĂ«r pĂ«rgjigje tĂ« gabuar me njĂ« periudhĂ« tĂ« caktuar kohore, por pa ndalur pĂ«rpunimin e kĂ«rkesave tĂ« suksesshme nĂ« radhĂ«n kryesore. PĂ«r kĂ«tĂ«, u zgjodh koncepti i quajtur âriprocesimi i bazuar nĂ« temaâ. PĂ«r secilĂ«n temĂ« kryesore krijohet njĂ« ose disa tema rytrye, nĂ« tĂ« cilat dĂ«rgohen mesazhet e gabuar dhe pĂ«r kĂ«tĂ« arsye pĂ«rjashtohet vonesa nĂ« pĂ«rpunimin e mesazheve nga tema kryesore. Schemi i ndĂ«rveprimit â

Për realizimin e një skeme të tillë na duhej të integrojmë këtë zgjidhje me Spring dhe të shmangim riprodhimin e kodit. Në hapësirën e internetit ne u ndeshëm me një zgjidhje të ngjashme, të bazuar në Spring BeanPostProcessor, por na dukej tejet e ndërlikuar. Ekipi ynë zhvilloi një zgjidhje më të thjeshtë, që lejon të integrohet në ciklin Spring për krijimin e konsumatorëve dhe për të shtuar konsumatorë me Retry. Prototipi i zgjidhjes sonë u propozua ekipit të Spring, dhe mund të shihet . Numri i konsumatorëve me Retry dhe numri i përpjekjeve të çdo konsumatori konfigurohen përmes parametërve, në varësi të nevojave të procesit të biznesit, dhe, që gjithçka të funksionojë, mbetet vetëm të vendoset annotacioni i njohur për të gjithë zhvilluesit e Spring: org.springframework.kafka.annotation.KafkaListener.
Në rast se mesazhi nuk mund të përpunohet pas të gjitha përpjekjeve për riprovim, ai kalon në DLT (dead letter topic) me ndihmën e Spring DeadLetterPublishingRecoverer. Në kërkesën e mbështetjes, ne e zgjeruam këtë funksionalitet dhe zhvilluam një shërbim të veçantë që lejon të shikohen mesazhet që kanë përfunduar në DLT, stackTrace, traceId dhe informacione të tjera të dobishme për to. Përveç kësaj, u shtuan monitorime dhe alarme për të gjitha temat DLT, dhe tani, në thelb, shfaqja e një mesazhi në temën DLT është një shkak për hetim dhe krijimin e një defekti. Kjo është shumë e përshtatshme - nga emri i temës ne menjëherë kuptojmë se në cilin hap të procesit ka ndodhur problemi, që e përshpejton ndjeshëm gjetjen e shkakut të saj rrënjësor.

Pak kohë më parë ne realizuam një ndërfaqe që lejon të dërgohen përsëri mesazhet nga mbështetja jonë, pas zgjidhjes së shkakut të tyre (për shembull, rikthimi i funksionimit të sistemit të jashtëm) dhe, sigurisht, krijimin e një defekti për analizë. Këtu na erdhën në ndihmë self-temat tona, për të mos e rifilluar një varg të gjatë procesimi, mund të rifillojmë nga hapi i kërkuar.

Ekspluatimi i platformës
Plani tashmë është në përdorim produktiv, çdo ditë ne realizojmë dërgesa dhe shpërndarje, lidhim qendra të reja shpërndarjeje dhe dyqane. Në kuadër të pilotit, sistemi punon me grupe produktesh 'Tënd' dhe 'Këpucë'.
E gjithë ekipi ynë merr pjesë në realizimin e pilotëve, analizon problemet që lindin dhe propozon përmirësime për produktin tonë nga përmirësimi i logeve deri te ndryshimet në procese.
Për të shmangur përsëritjen e gabimeve të mia, të gjitha rastet e gjetura gjatë pilotit pasqyrohen në testet e automatizuara. Prania e një numri të madh të testeve automatike dhe testeve të njësi lejon kryerjen e testimeve regresive dhe vendosjen e hotfix-eve në vetëm disa orë.
Aktualisht ne po vazhdojmë të zhvillojmë dhe përmirësojmë platformën tonë dhe përballemi vazhdimisht me sfida të reja. Nëse jeni të interesuar, ne do të flasim për zgjidhjet tona në artikujt e ardhshëm.
Burimi: habr.com
