"Wandelen in mijn schoenen" - wacht, zijn ze gemarkeerd?

Sinds 2019 kent Rusland een wet inzake verplichte etikettering. De wet is niet van toepassing op alle productgroepen en de data voor de inwerkingtreding van de verplichte etikettering voor productgroepen zijn verschillend. Tabak, schoenen en medicijnen zullen als eerste onderworpen zijn aan verplichte etikettering; later zullen andere producten worden toegevoegd, bijvoorbeeld parfum, textiel en melk. Deze wetgevende innovatie heeft geleid tot de ontwikkeling van nieuwe IT-oplossingen die het mogelijk zullen maken om de gehele levensketen van een product te volgen, van productie tot aankoop door de eindgebruiker, tot aan alle deelnemers aan het proces: zowel de staat zelf als alle organisaties die goederen verkopen met verplichte etikettering.

In X5 heet het systeem dat gelabelde goederen volgt en gegevens uitwisselt met de staat en leveranciers “Marcus”. Laten we u op volgorde vertellen hoe en wie het heeft ontwikkeld, wat de technologiestapel is en waarom we iets hebben om trots op te zijn.

"Wandelen in mijn schoenen" - wacht, zijn ze gemarkeerd?

Echte HighLoad

“Marcus” lost veel problemen op, de belangrijkste is de integratie-interactie tussen X5-informatiesystemen en het staatsinformatiesysteem voor gelabelde producten (GIS MP) om de beweging van gelabelde producten te volgen. Het platform slaat ook alle door ons ontvangen etiketteringscodes op, evenals de volledige geschiedenis van de verplaatsing van deze codes tussen objecten, en helpt bij het elimineren van de herclassificatie van gelabelde producten. Als we het voorbeeld van de tabaksproducten gebruiken, die deel uitmaakten van de eerste groepen gelabelde goederen, bevat slechts één vrachtwagen vol sigaretten ongeveer 600 pakjes, die elk hun eigen unieke code hebben. En de taak van ons systeem is het volgen en verifiëren van de wettigheid van de bewegingen van elk dergelijk pakket tussen magazijnen en winkels, en uiteindelijk het verifiëren van de toelaatbaarheid van de verkoop ervan aan de eindkoper. En we registreren ongeveer 000 contante transacties per uur, en we moeten ook vastleggen hoe elk pakketje in de winkel terecht is gekomen. Als we alle bewegingen tussen objecten in aanmerking nemen, verwachten we dus tientallen miljarden records per jaar.

Team M

Ondanks dat Marcus binnen X5 als een project wordt beschouwd, wordt het vanuit een productaanpak uitgevoerd. Het team werkt volgens Scrum. Het project ging afgelopen zomer van start, maar de eerste resultaten kwamen pas in oktober: ons eigen team was volledig samengesteld, de systeemarchitectuur werd ontwikkeld en apparatuur werd aangeschaft. Nu bestaat het team uit 16 mensen, waarvan er zes betrokken zijn bij de ontwikkeling van de backend en de frontend, en drie bij de systeemanalyse. Er zijn nog zes mensen betrokken bij handmatig testen, laden, geautomatiseerd testen en productonderhoud. Daarnaast beschikken wij over een SRE-specialist.

In ons team schrijven niet alleen de ontwikkelaars code; bijna alle jongens weten hoe ze autotests, load- en automatiseringsscripts moeten programmeren en schrijven. Wij besteden hier speciale aandacht aan, omdat zelfs productondersteuning een hoge mate van automatisering vereist. We proberen altijd collega's die nog niet eerder hebben geprogrammeerd te adviseren en te helpen, en hen wat kleine taakjes te geven om aan te werken.

Vanwege de coronaviruspandemie hebben we het hele team overgezet naar werken op afstand; de beschikbaarheid van alle tools voor ontwikkelingsbeheer, de ingebouwde workflow in Jira en GitLab maakten het mogelijk om deze fase gemakkelijk te passeren. De maanden op afstand lieten zien dat de productiviteit van het team er niet onder leed; voor velen nam het comfort op het werk toe, het enige wat ontbrak was live communicatie.

Teamvergadering op afstand

"Wandelen in mijn schoenen" - wacht, zijn ze gemarkeerd?

Vergaderingen tijdens werken op afstand

"Wandelen in mijn schoenen" - wacht, zijn ze gemarkeerd?

Technologiestapel van de oplossing

De standaard repository en CI/CD-tool voor X5 is GitLab. We gebruiken het voor codeopslag, continu testen en implementatie op test- en productieservers. We gebruiken ook de praktijk van codebeoordeling, waarbij ten minste twee collega's wijzigingen moeten goedkeuren die door de ontwikkelaar in de code zijn aangebracht. Statische code-analysatoren SonarQube en JaCoCo helpen ons onze code schoon te houden en het vereiste niveau van unit-testdekking te garanderen. Alle wijzigingen aan de code moeten deze controles doorlopen. Alle testscripts die handmatig worden uitgevoerd, worden vervolgens geautomatiseerd.

Voor de succesvolle implementatie van bedrijfsprocessen door “Marcus” moesten we een aantal technologische problemen oplossen, ongeveer elk in volgorde.

Taak 1. De behoefte aan horizontale schaalbaarheid van het systeem

Om dit probleem op te lossen, hebben we gekozen voor een microservice-benadering van de architectuur. Tegelijkertijd was het erg belangrijk om de verantwoordelijkheidsgebieden van de diensten te begrijpen. We hebben geprobeerd ze in te delen in bedrijfsactiviteiten, rekening houdend met de specifieke kenmerken van de processen. Acceptatie in een magazijn is bijvoorbeeld geen zeer frequente, maar zeer grootschalige operatie, waarbij het nodig is om snel van de staatstoezichthouder informatie te verkrijgen over de eenheden goederen die worden geaccepteerd, waarvan het aantal in één levering 600000 bedraagt. , controleer de toelaatbaarheid van het accepteren van dit product in het magazijn en stuur alle benodigde informatie voor het magazijnautomatiseringssysteem terug. Maar verzending vanuit magazijnen heeft een veel grotere intensiteit, maar werkt tegelijkertijd met kleine hoeveelheden gegevens.

We implementeren alle diensten op staatloze basis en proberen zelfs de interne bedrijfsvoering in stappen te verdelen, met behulp van wat we Kafka-zelfonderwerpen noemen. Dit is wanneer een microservice een bericht naar zichzelf stuurt, waardoor u de belasting van meer resource-intensieve bewerkingen kunt verdelen en het productonderhoud kunt vereenvoudigen, maar daarover later meer.

We hebben besloten om de modules voor interactie met externe systemen op te splitsen in afzonderlijke services. Dit maakte het mogelijk om het probleem van de vaak wisselende API’s van externe systemen op te lossen, vrijwel zonder impact op diensten met zakelijke functionaliteit.

"Wandelen in mijn schoenen" - wacht, zijn ze gemarkeerd?

Alle microservices worden geïmplementeerd in een OpenShift-cluster, wat zowel het probleem van het schalen van elke microservice oplost als ons in staat stelt om geen Service Discovery-tools van derden te gebruiken.

Taak 2. De noodzaak om een ​​hoge belasting en zeer intensieve gegevensuitwisseling tussen platformdiensten te handhaven: Alleen al tijdens de startfase van het project worden ongeveer 600 handelingen per seconde uitgevoerd. We verwachten dat deze waarde zal stijgen naar 5000 ops/sec naarmate winkels verbinding maken met ons platform.

Dit probleem werd opgelost door een Kafka-cluster in te zetten en de synchrone interactie tussen de microservices van het platform vrijwel volledig achterwege te laten. Dit vereist een zeer zorgvuldige analyse van de systeemvereisten, aangezien niet alle bewerkingen asynchroon kunnen zijn. Tegelijkertijd verzenden we niet alleen gebeurtenissen via de makelaar, maar verzenden we ook alle benodigde bedrijfsinformatie in het bericht. De berichtgrootte kan dus enkele honderden kilobytes bereiken. De limiet voor de berichtgrootte in Kafka vereist dat we de berichtgrootte nauwkeurig voorspellen en indien nodig verdelen we ze, maar de indeling is logisch en gerelateerd aan de bedrijfsvoering.
Goederen die in een auto binnenkomen verdelen wij bijvoorbeeld in dozen. Voor synchrone operaties worden afzonderlijke microservices toegewezen en worden grondige belastingtests uitgevoerd. Het gebruik van Kafka stelde ons voor een nieuwe uitdaging: het testen van de werking van onze service, rekening houdend met de Kafka-integratie, zorgt ervoor dat al onze unit-tests asynchroon zijn. We hebben dit probleem opgelost door onze eigen hulpprogrammamethoden te schrijven met behulp van Embedded Kafka Broker. Dit elimineert niet de noodzaak om unit-tests voor individuele methoden te schrijven, maar wij geven er de voorkeur aan om complexe cases te testen met Kafka.

Er is veel aandacht besteed aan het traceren van logs, zodat hun TraceId niet verloren zou gaan als er uitzonderingen optreden tijdens de werking van services of bij het werken met Kafka batch. En als er geen speciale problemen waren met de eerste, zijn we in het tweede geval gedwongen om alle TraceIds die bij de batch horen te loggen en er één te selecteren om door te gaan met traceren. Wanneer de gebruiker vervolgens zoekt op de oorspronkelijke TraceId, kan hij er gemakkelijk achter komen waarmee de tracering is voortgezet.

Taak 3. De noodzaak om een ​​grote hoeveelheid gegevens op te slaan: Alleen al voor tabak komen er jaarlijks ruim 1 miljard labels naar X5. Ze vereisen constante en snelle toegang. In totaal moet het systeem ongeveer 10 miljard records verwerken van de verplaatsingsgeschiedenis van deze gelabelde goederen.

Om het derde probleem op te lossen werd gekozen voor de NoSQL-database MongoDB. We hebben een scherf van 5 knooppunten gebouwd en elk knooppunt heeft een replicaset van 3 servers. Hierdoor kunt u het systeem horizontaal schalen, nieuwe servers aan het cluster toevoegen en de fouttolerantie garanderen. Hier kwamen we een ander probleem tegen: het garanderen van transactionaliteit in het mongocluster, rekening houdend met het gebruik van horizontaal schaalbare microservices. Een van de taken van ons systeem is bijvoorbeeld het identificeren van pogingen om producten met dezelfde etiketteringscodes door te verkopen. Hier verschijnen overlays met foutieve scans of foutieve handelingen door kassamedewerkers. We hebben vastgesteld dat dergelijke duplicaten kunnen voorkomen binnen één Kafka-batch die wordt verwerkt, maar ook binnen twee batches die parallel worden verwerkt. Het controleren op duplicaten door de database te bevragen leverde dus niets op. Voor elke microservice hebben we het probleem afzonderlijk opgelost op basis van de bedrijfslogica van deze service. Voor cheques hebben we bijvoorbeeld een cheque binnen batch en een afzonderlijke verwerking toegevoegd voor het verschijnen van duplicaten bij het invoegen.

Om ervoor te zorgen dat het werk van gebruikers met de geschiedenis van de operaties op geen enkele manier invloed heeft op het allerbelangrijkste: het functioneren van onze bedrijfsprocessen, hebben we alle historische gegevens gescheiden in een aparte dienst met een aparte database, die ook informatie ontvangt via Kafka . Op deze manier werken gebruikers met een geïsoleerde service zonder dat dit gevolgen heeft voor de services die gegevens verwerken voor lopende activiteiten.

Taak 4: Herverwerking en monitoring van wachtrijen:

In gedistribueerde systemen ontstaan ​​onvermijdelijk problemen en fouten in de beschikbaarheid van databases, wachtrijen en externe gegevensbronnen. In het geval van Marcus is de bron van dergelijke fouten de integratie met externe systemen. Het was noodzakelijk om een ​​oplossing te vinden die herhaalde verzoeken om foutieve antwoorden met een bepaalde time-out mogelijk zou maken, maar tegelijkertijd niet zou stoppen met het verwerken van succesvolle verzoeken in de hoofdwachtrij. Hiervoor werd gekozen voor het zogenaamde “topic based retry” concept. Voor elk hoofdonderwerp worden een of meer onderwerpen voor opnieuw proberen aangemaakt waarnaar foutieve berichten worden verzonden en tegelijkertijd wordt de vertraging bij het verwerken van berichten uit het hoofdonderwerp geëlimineerd. Interactieschema -

"Wandelen in mijn schoenen" - wacht, zijn ze gemarkeerd?

Om een ​​dergelijk schema te implementeren hadden we het volgende nodig: deze oplossing integreren met Spring en duplicatie van code voorkomen. Tijdens het surfen op internet kwamen we een soortgelijke oplossing tegen, gebaseerd op Spring BeanPostProccessor, maar het leek ons ​​onnodig omslachtig. Ons team heeft een eenvoudigere oplossing gemaakt waarmee we in de lentecyclus kunnen integreren voor het maken van consumenten en bovendien Retry Consumers kunnen toevoegen. We hebben een prototype van onze oplossing aangeboden aan het Spring-team, je kunt het zien hier. Het aantal Retry Consumers en het aantal pogingen voor elke consument worden geconfigureerd via parameters, afhankelijk van de behoeften van het bedrijfsproces. Om alles te laten werken, hoeft u alleen nog de annotatie org.springframework.kafka.annotation.KafkaListener toe te voegen. , die bekend is bij alle Spring-ontwikkelaars.

Als het bericht na alle nieuwe pogingen niet kon worden verwerkt, gaat het met Spring DeadLetterPublishingRecoverer naar DLT (dead letter topic). Op verzoek van ondersteuning hebben we deze functionaliteit uitgebreid en een aparte service gecreëerd waarmee u berichten kunt bekijken die zijn opgenomen in DLT, stackTrace, traceId en andere nuttige informatie daarover. Bovendien zijn er monitoring en waarschuwingen toegevoegd aan alle DLT-onderwerpen, en nu is het verschijnen van een bericht in een DLT-onderwerp in feite een reden om een ​​defect te analyseren en op te lossen. Dit is erg handig: door de naam van het onderwerp begrijpen we meteen in welke stap van het proces het probleem zich voordeed, wat de zoektocht naar de oorzaak ervan aanzienlijk versnelt.

"Wandelen in mijn schoenen" - wacht, zijn ze gemarkeerd?

Recentelijk hebben we een interface geïmplementeerd waarmee we berichten opnieuw kunnen verzenden met behulp van onze ondersteuning nadat we de oorzaken ervan hebben geëlimineerd (bijvoorbeeld door de functionaliteit van het externe systeem te herstellen) en uiteraard het overeenkomstige defect voor analyse hebben vastgesteld. Dit is waar onze zelfonderwerpen van pas komen: om een ​​lange verwerkingsketen niet opnieuw te starten, kunt u deze opnieuw starten vanaf de gewenste stap.

"Wandelen in mijn schoenen" - wacht, zijn ze gemarkeerd?

Platformbediening

Het platform is al productief in gebruik, dagelijks voeren wij leveringen en verzendingen uit, sluiten nieuwe distributiecentra en winkels aan. Als onderdeel van de pilot werkt het systeem met de productgroepen ‘Tabak’ en ‘Schoenen’.

Ons hele team neemt deel aan het uitvoeren van pilots, analyseert opkomende problemen en doet suggesties voor het verbeteren van ons product, van het verbeteren van logs tot het veranderen van processen.

Om onze fouten niet te herhalen, worden alle tijdens de pilot gevonden gevallen weergegeven in geautomatiseerde tests. Door de aanwezigheid van een groot aantal autotests en unit-tests kunt u letterlijk binnen een paar uur regressietesten uitvoeren en een hotfix installeren.

Nu blijven we ons platform ontwikkelen en verbeteren, en worden we voortdurend geconfronteerd met nieuwe uitdagingen. Als u geïnteresseerd bent, bespreken we onze oplossingen in de volgende artikelen.

Bron: www.habr.com

Voeg een reactie