Walking in my shoes стоп, а яны маркіраваныя?

З 2019 года ў Расіі дзейнічае закон аб абавязковай маркіроўцы. Закон распаўсюджваецца не на ўсе групы тавараў, і тэрміны ўступлення ў сілу абавязковай маркіроўкі для таварных груп розныя. Першымі пад абавязковую маркіроўку трапляюць тытунь, абутак, лекі, пазней дададуцца і іншыя тавары, напрыклад, духі, тэкстыль, малако. Гэта заканадаўчае новаўвядзенне заахвоціла да распрацоўкі новых ІТ-рашэнняў, якія дазволяць адсачыць увесь ланцужок жыцця тавара з моманту вытворчасці да куплі канчатковым спажыўцом, усім удзельнікам працэсу: як сама дзяржава, так і ўсе арганізацыі, якія рэалізуюць тавары з абавязковай маркіроўкай.

У Х5 сістэма, якая будзе адсочваць тавары з маркіроўкай і абменьвацца дадзенымі з дзяржавай і пастаўшчыкамі, атрымала назву "Маркус". Раскажам па парадку як і хто яе распрацоўваў, які ў яе стэк тэхналогій, і чаму нам ёсць чым ганарыцца.

Walking in my shoes стоп, а яны маркіраваныя?

Сапраўдны HighLoad

"Маркус" вырашае мноства задач, галоўная з іх - інтэграцыйнае ўзаемадзеянне паміж інфармацыйнымі сістэмамі Х5 і дзяржаўнай інфармацыйнай сістэмай маркіраванай прадукцыі (ГІС МП) для прасочвання руху маркіраванай прадукцыі. Таксама платформа захоўвае ўсе коды маркіроўкі, якія паступілі да нас, і ўсю гісторыю руху гэтых кодаў па аб'ектах, дапамагае ліквідаваць перасорт маркіраванай прадукцыі. На прыкладзе тытунёвай прадукцыі, якая ўвайшла ў першыя групы маркіраваных тавараў, толькі адна фура цыгарэт змяшчае каля 600 000 пачкаў, кожная з якіх мае свой унікальны код. І задача нашай сістэмы адсачыць і праверыць легальнасць перасоўванняў кожнага такога пачка паміж складамі і крамамі, і ў канчатковым рахунку праверыць дапушчальнасць іх рэалізацыі канчатковаму пакупніку. А касавых аперацый мы фіксуем каля 125 000 у гадзіну, і яшчэ трэба зафіксаваць як кожны такі пачак трапіў у краму. Такім чынам з улікам усіх перасоўванняў паміж аб'ектамі мы чакаем дзясяткі мільярдаў запісаў у год.

Каманда М

Нягледзячы на ​​тое, што "Маркус" лічыцца ў рамках Х5 праектам, рэалізуецца ён па прадуктовым падыходзе. Каманда працуе па Scrum. Старт праекта быў летам мінулага года, але першыя вынікі прыйшлі толькі ў кастрычніку - была цалкам сабрана ўласная каманда, распрацавана архітэктура сістэмы і набыта абсталяванне. Цяпер у камандзе 16 чалавек, шэсць з якіх займаюцца распрацоўкай backend і frontend, трое сістэмным аналізам. Ручным, нагрузачным, аўтаматызаваным тэсціраваннем, і суправаджэннем прадукта займаюцца яшчэ шэсць чалавек. Апроч гэтага ў нас ёсць SRE-спецыяліст.

Код у нашай камандзе пішуць не толькі распрацоўшчыкі, практычна ўсе хлопцы ўмеюць праграмаваць і пішуць аўтатэсты, нагрузачныя скрыпты і скрыпты аўтаматызацыі. Мы надаем гэтаму адмысловую ўвагу, бо нават падтрымка прадукта патрабуе высокага ўзроўня аўтаматызацыі. Калегам, якія раней не праграміравалі, заўсёды стараемся падказаць і дапамагчы, даць у работу нейкія невялікія задачы.

У сувязі з пандэміяй каранавіруснай інфекцыі мы перавялі ўсю каманду на выдаленую працу, наяўнасць усіх інструментаў для кіравання распрацоўкай, пабудаваны workflow у Jira і GitLab дазволілі лёгка прайсці гэты этап. Праведзеныя на выдаленні месяцы паказалі, што прадукцыйнасць каманды ад гэтага не пацярпела, для многіх павысіўся камфорт у рабоце, адзінае, не хапае жывых зносін.

Сустрэча каманды да аддалення

Walking in my shoes стоп, а яны маркіраваныя?

Сустрэчы падчас выдалення

Walking in my shoes стоп, а яны маркіраваныя?

Тэхналагічны стэк рашэння

Стандартным рэпазітаром і прыладай CI/CD для Х5 з'яўляецца GitLab. Мы выкарыстоўваем яго для захоўвання кода, бесперапыннага тэсціравання, разгортвання на тэставых і прадуктыўных серверах. Таксама мы выкарыстоўваем практыку code review, калі як мінімум 2 калегамі трэба ўхваліць якія ўносяцца распрацоўнікам змены ў код. Статычныя аналізатары кода SonarQube і JaCoCo дапамагаюць нам трымаць код чыстым і забяспечыць патрабаваны ўзровень пакрыцця unit-тэстамі. Усе змены ў кодзе абавязкова павінны прайсці праз гэтыя праверкі. Усе тэставыя сцэнары, якія праганяюцца ўручную, пасля аўтаматызуюцца.

Для паспяховага выканання бізнес-працэсаў "Маркусам" нам прыйшлося вырашыць шэраг тэхналагічных задач, аб кожнай па парадку.

Задача 1. Неабходнасць гарызантальнай маштабаванасці сістэмы

Для рашэння гэтай задачы мы абралі мікрасэрвісны падыход да архітэктуры. Пры гэтым было вельмі важна зразумець галіны адказнасці сэрвісаў. Мы пастараліся падзяліць іх па бізнес-аперацыях з улікам спецыфікі працэсаў. Напрыклад, прыёмка на складзе - гэта не вельмі частая, але вельмі аб'ёмная аперацыя, у ходзе якой трэба максімальна хутка атрымаць у дзяржрэгулятара інфармацыю аб адзінках тавару, колькасць якіх у адной пастаўцы даходзіць да 600000, праверыць дапушчальнасць прыёму гэтага тавару на склад і аддаць усю неабходную інфармацыю сістэме аўтаматызацыі склада. А вось адгрузка са складоў мае значна большую інтэнсіўнасць, але пры гэтым аперуе невялікімі аб'ёмамі дадзеных.

Усе сэрвісы мы рэалізуем па прынцыпе stateless і нават унутраныя аперацыі імкнемся падзяляць на крокі, выкарыстаючы, як мы іх завём, self-топікі Kafka. Гэта калі мікрасэрвіс адпраўляе паведамленне сам сабе, што дазваляе збалансаваць нагрузку па больш рэсурсаёмістых аперацыях і спрашчае суправаджэнне прадукта, але пра гэта пазней.

Мы вырашылі вылучыць у асобныя сэрвісы модулі ўзаемадзеяння са знешнімі сістэмамі. Гэта дазволіла вырашыць праблему часта змяняюцца API вонкавых сістэм, практычна без уплыву на сэрвісы з бізнэс-функцыяналам.

Walking in my shoes стоп, а яны маркіраваныя?

Усе мікрасэрвісы разгортваюцца ў кластары OpenShift, які вырашае як праблему маштабавання кожнага мікрасэрвісу, так і дазваляе нам не выкарыстоўваць іншыя прылады Service Discovery.

Задача 2. Неабходнасць падтрымання высокай нагрузкі і вельмі інтэнсіўнага абмену данымі паміж сэрвісамі платформы: толькі на фазе запуску праекта выконваецца каля 600 аперацый у секунду. Мы чакаем павелічэнне гэтага значэння да 5000 оп/сек па меры падключэння гандлёвых аб'ектаў да нашай платформы.

Гэтую задачу вырашалі разгортваннем кластара Kafka і практычна поўнай адмовай ад сінхроннага ўзаемадзеяння паміж мікрасэрвісамі платформы. Гэта патрабуе вельмі ўважлівага аналізу патрабаванняў да сістэмы, бо не ўсе аперацыі могуць быць асінхроннымі. Пры гэтым, мы не проста перадаем падзеі праз брокер, але і перадаем у паведамленні ўсю патрабаваную бізнес-інфармацыю. Такім чынам, памер паведамлення можа даходзіць да некалькіх сотняў кілабайт. Абмежаванне на аб'ём паведамленняў у Kafka патрабуе ад нас дакладнага прагназавання памеру паведамленняў, і, пры неабходнасці, мы іх дзелім, але дзяленне гэта лагічнае, звязанае з бізнес-аперацыямі.
Напрыклад, тавар які прыехаў у аўтамабілі, мы дзелім па корабах. Для сінхронных аперацый вылучаюцца асобныя мікрасэрвісы і праводзіцца стараннае нагрузачнае тэсціраванне. Выкарыстанне Kafka паставіла перад намі іншы выклік - праверка працы нашага сэрвісу з улікам інтэграцыі Kafka робіць усё нашы unit-тэсты асінхроннымі. Гэтую задачу мы вырашалі напісаннем уласных утыльных метадаў з выкарыстаннем Embedded Kafka Broker. Гэта не адмяняе неабходнасці напісання unit-тэстаў на асобныя метады, але складаныя кейсы мы аддаем перавагу тэсціраваць з выкарыстаннем Kafka.

Вельмі шмат увагі надалі трасіроўцы логаў, каб іх TraceId не губляліся пры ўзнікненні выключэнняў падчас працы сэрвісаў ці пры працы з Kafka batch. І калі з першым адмысловых пытанняў не ўзнікла, то ў другім выпадку мы змушаныя запісаць у лог усё TraceId, з якімі прыйшоў batch, і абраць адзін для працягу трасіроўкі. Тады пры пошуку па першапачатковым TraceId карыстач лёгка выявіць з якім працягнулася трасіроўка.

Задача 3. Неабходнасць захоўвання вялікай колькасці даных: больш за 1 мільярд маркіровак у год толькі па тытуню паступае ў X5. Да іх патрабуецца пастаянны і хуткі доступ. Усяго сістэма павінна апрацоўваць каля 10 мільярдаў запісаў па гісторыі руху дадзеных маркіраваных тавараў.

Для рашэння трэцяй задачы была абрана NoSQL база MongoDB. У нас пабудаваны шард з 5 нод і ў кожнай нодзе Replica Set з 3 сервераў. Гэта дазваляе маштабаваць сістэму гарызантальна, дадаючы новыя серверы ў кластар, і забяспечыць яе адмоваўстойлівасць. Тут мы сутыкнуліся з іншай праблемай - забеспячэнне транзакцыйнасці ў кластары mongo з улікам выкарыстання гарызантальна якія маштабуюцца мікрасэрвісаў. Напрыклад, адна з задач нашай сістэмы - выяўляць спробы паўторнага продажу тавараў з аднолькавымі кодамі маркіроўкі. Тут з'яўляюцца накладкі з памылковымі сканаваннямі або з памылковымі аперацыямі касіраў. Мы выявілі, што такія дублі могуць узнікаць як усярэдзіне аднаго апрацоўванага batch Kafka, так і ўсярэдзіне двух раўналежна апрацоўваных batch. Такім чынам, праверка на з'яўленне дубляў шляхам запыту да базы нічога не давала. Для кожнага з мікрасэрвісаў мы вырашалі праблему асобна зыходзячы з бізнэс-логікі гэтага сэрвісу. Напрыклад, для чэкаў дадалі праверку ўсярэдзіне batch і асобную апрацоўку на з'яўленне дублікатаў пры ўстаўцы.

Каб праца карыстачоў з гісторыяй аперацый ніяк не ўплывала на самае галоўнае - функцыянаванне нашых бізнэс-працэсаў, усе гістарычныя дадзеныя мы вылучылі ў асобны сэрвіс з асобнай базай дадзеных, які таксама атрымлівае інфармацыю праз Kafka. Такім чынам карыстачы працуюць з ізаляваным сэрвісам, не ўплываючы на ​​сэрвісы, якія апрацоўваюць дадзеныя па бягучых аперацыях.

Задача 4. Паўторная апрацоўка чэргаў і маніторынг:

У размеркаваных сістэмах непазбежна ўзнікаюць праблемы і памылкі даступнасці баз дадзеных, чэргаў, вонкавых крыніц дадзеных. У выпадку "Маркуса" крыніцай такіх памылак з'яўляецца інтэграцыя з вонкавымі сістэмамі. Неабходна было знайсці рашэнне, якое дазваляе праводзіць паўторныя запыты па памылковых адказах з нейкім зададзеным таймаўтам, але пры гэтым не спыняць апрацоўку паспяховых запытаў у асноўнай чарзе. Для гэтага была абрана так званая канцэпцыя "topic based retry". Для кожнага асноўнага топіка ствараецца адзін або некалькі retry топікаў, у якія накіроўваюцца памылковыя паведамленні і пры гэтым выключаецца затрымка на апрацоўку паведамленняў з асноўнага топіка. Схема ўзаемадзеяння -

Walking in my shoes стоп, а яны маркіраваныя?

Для рэалізацыі такой схемы нам патрабавалася наступнае – інтэграваць гэтае рашэнне са Spring і пазбегнуць дубліраванні кода. На абшарах сеткі мы натыкнуліся на падобнае рашэнне, заснаванае на Spring BeanPostProccessor, але яно падалося нам залішне грувасткім. Нашай камандай было зроблена прасцейшае рашэнне, якое дазваляе ўбудавацца ў цыкл Spring па стварэнні consumer і дадаткова дадаваць Retry Consumer-ы. Прататып нашага рашэння мы прапанавалі камандзе Spring, паглядзець яго можна тут. Колькасць Retry Consumer-ов і колькасць спроб кожнага consumer-a наладжваецца праз параметры, у залежнасці ад запатрабаванняў бізнэс-працэсу, і, каб усё зарабіла, застаецца толькі паставіць знаёмую ўсім Spring-распрацоўнікам анатацыю org.springframework.kafka.annotation.KafkaListener.

У выпадку, калі паведамленне не магло быць апрацавана пасля ўсіх retry спроб, яно пападае ў DLT (dead letter topic) з дапамогай Spring DeadLetterPublishingRecoverer. Па просьбе падтрымкі, мы пашырылі дадзены функцыянал і зрабілі асобны сэрвіс, які дазваляе праглядаць якія трапілі ў DLT паведамленні, stackTrace, traceId і іншую карысную інфармацыю па іх. Акрамя таго, былі дададзеныя маніторынгі і алерты на ўсе DLT топікі, і цяпер, па сутнасці, з'яўленне паведамлення ў DLT топіцы з'яўляецца падставай для разбору і ўстановы дэфекту. Гэта вельмі зручна - па назве топіка мы адразу разумеем, на якім кроку працэсу ўзнікла праблема, што значна паскарае пошук яе каранёвай прычыны.

Walking in my shoes стоп, а яны маркіраваныя?

Зусім нядаўна мы рэалізавалі інтэрфейс, які дазваляе паўторна адправіць паведамленні сіламі нашай падтрымкі, пасля ўхілення іх чыннікаў (напрыклад, узнаўленне працаздольнасці вонкавай сістэмы) і, вядома, установы які адпавядае дэфекту для аналізу. Тут і спатрэбіліся нашы self-топікі, каб не перазапускаць доўгі ланцужок апрацоўкі, можна перазапусціць яе з патрэбнага кроку.

Walking in my shoes стоп, а яны маркіраваныя?

Эксплуатацыя платформы

Платформа ўжо знаходзіцца ў прадуктыўнай эксплуатацыі, кожны дзень мы праводзім пастаўкі і адгрузкі, падлучаем новыя размеркавальныя цэнтры і крамы. У рамках пілота сістэма працуе з групамі тавараў "Тытунь" і "Абутак".

Уся наша каманда ўдзельнічае ў правядзенні пілотаў, аналізуе ўзнікаючыя праблемы і ўносіць прапановы па ўдасканаленні нашага прадукта ад паляпшэння логаў да змены ў працэсах.

Каб не паўтараць сваіх памылак, усе кейсы знойдзеныя падчас пілота знаходзяць сваё адлюстраванне ў аўтаматызаваных тэстах. Наяўнасць вялікай колькасці аўтатэстаў і unit-тэстаў дазваляюць праводзіць рэгрэсійнае тэсціраванне і ставіць хотфікс літаральна на працягу некалькіх гадзін.

Цяпер мы працягваем развіваць і ўдасканальваць нашу платформу, і ўвесь час сутыкаемся з новымі выклікамі. Калі вам будзе цікава, то мы раскажам аб нашых рашэннях у наступных артыкулах.

Крыніца: habr.com

Дадаць каментар