Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Sadələşdirilmiş prosesə və onlarla bir-biri ilə əlaqəli xidmətlərə malik Lamoda kimi böyük bir şirkəti öz yanaşmasını əhəmiyyətli dərəcədə dəyişməyə nə məcbur edə bilər? Motivasiya tamamilə fərqli ola bilər: qanunvericilikdən tutmuş bütün proqramçılara xas olan təcrübə istəyinə qədər.

Ancaq bu, əlavə üstünlüklərə arxalana bilməyəcəyiniz demək deyil. Sergey Zaika sizə Kafkada hadisələrə əsaslanan API tətbiq etsəniz, tam olaraq nə qazana biləcəyinizi söyləyəcək (az). Böyük kadrlar və maraqlı kəşflər haqqında da mütləq danışılacaq - eksperiment onlarsız keçə bilməz.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

İmtina: Bu məqalə Sergeyin 2018-ci ilin noyabrında HighLoad++-da keçirdiyi görüş materiallarına əsaslanır. Lamodanın Kafka ilə canlı işləmək təcrübəsi dinləyiciləri cədvəl üzrə digər hesabatlardan az olmayaraq cəlb etdi. Düşünürük ki, bu, həmişə həmfikir insanları tapa biləcəyiniz və tapmağınızın gözəl nümunəsidir və HighLoad++ təşkilatçıları buna əlverişli atmosfer yaratmağa çalışacaqlar.

Proses haqqında

Lamoda öz əlaqə mərkəzinə, çatdırılma xidmətinə (və bir çox filiallarına), fotostudiyaya, nəhəng anbara malik olan və bütün bunlar öz proqram təminatı ilə işləyən böyük bir elektron ticarət platformasıdır. Bu xidmətlərdən bəzilərini və ya hamısını istifadə edə bilən və məhsulları haqqında ən son məlumatları bilmək istəyən onlarla ödəniş üsulu, b2b tərəfdaşları var. Bundan əlavə, Lamoda Rusiya Federasiyasından başqa üç ölkədə fəaliyyət göstərir və orada hər şey bir az fərqlidir. Ümumilikdə, yəqin ki, öz qaydasında işlənməli olan yeni bir sifarişi konfiqurasiya etməyin yüzdən çox yolu var. Bütün bunlar bəzən qeyri-aşkar yollarla əlaqə saxlayan onlarla xidmətin köməyi ilə işləyir. Əsas məsuliyyəti sifariş statusları olan mərkəzi sistem də var. Biz ona BOB deyirik, mən onunla işləyirəm.

Hadisələrə əsaslanan API ilə Geri Ödəniş Aləti

Hadisələrə əsaslanan söz kifayət qədər səhvdir; bir az sonra bunun nə demək olduğunu daha ətraflı müəyyənləşdirəcəyik. Kafkada hadisələrə əsaslanan API yanaşmasını sınamağa qərar verdiyimiz kontekstdən başlayacağam.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

İstənilən mağazada müştərilərin ödədiyi sifarişlərdən əlavə, məhsul müştəriyə uyğun gəlmədiyi üçün mağazanın pulu qaytarması tələb olunduğu vaxtlar olur. Bu, nisbətən qısa bir prosesdir: lazım gələrsə, məlumatları dəqiqləşdiririk və pul köçürürük.

Amma qanunvericilikdəki dəyişikliklərlə əlaqədar geri qaytarma daha mürəkkəbləşdi və biz bunun üçün ayrıca mikroservis tətbiq etməli olduq.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Bizim motivasiyamız:

  1. Qanun FZ-54 - bir sözlə, qanun bir neçə dəqiqəlik kifayət qədər qısa SLA müddətində hər bir pul əməliyyatı, istər geri qaytarma, istərsə də qəbz barədə vergi idarəsinə məlumat verməyi tələb edir. Biz e-ticarət şirkəti olaraq kifayət qədər çox əməliyyatlar həyata keçiririk. Texniki cəhətdən bu, yeni məsuliyyət (və buna görə də yeni xidmət) və bütün cəlb edilmiş sistemlərdə təkmilləşdirmələr deməkdir.
  2. BOB bölündü BOB-ni çoxlu sayda əsas olmayan öhdəliklərdən azad etmək və onun ümumi mürəkkəbliyini azaltmaq üçün şirkətin daxili layihəsidir.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Bu diaqram əsas Lamoda sistemlərini göstərir. İndi onların əksəriyyəti daha çoxdur daralan monolit ətrafında 5-10 mikroservisdən ibarət bürc. Onlar yavaş-yavaş böyüyürlər, lakin biz onları kiçikləşdirməyə çalışırıq, çünki ortada seçilmiş fraqmentin yerləşdirilməsi qorxuludur - biz onun düşməsinə icazə verə bilmərik. Biz bütün mübadilələri (oxları) rezerv etməyə məcburuq və onlardan hər hansı birinin əlçatmaz ola biləcəyini nəzərə almalıyıq.

BOB-da kifayət qədər çox sayda mübadilə var: ödəniş sistemləri, çatdırılma sistemləri, bildiriş sistemləri və s.

Texniki olaraq BOB:

  • ~150k sətir kod + ~100k sətir test;
  • php7.2 + Zend 1 & Symfony Komponentləri 3;
  • >100 API və ~50 çıxış inteqrasiyası;
  • Öz biznes məntiqi ilə 4 ölkə.

BOB-u yerləşdirmək bahalı və ağrılıdır, onun həll etdiyi kod və problemlərin miqdarı elədir ki, heç kim hamısını öz başına qoya bilməz. Ümumiyyətlə, onu sadələşdirmək üçün çoxlu səbəblər var.

Qaytarma Prosesi

Əvvəlcə prosesdə iki sistem iştirak edir: BOB və Ödəniş. İndi daha ikisi görünür:

  • Fiskallaşdırma və xarici xidmətlərlə əlaqə ilə bağlı problemləri həll edəcək Fiskallaşdırma Xidməti.
  • BOB-u şişirtməmək üçün sadəcə olaraq yeni mübadilələri ehtiva edən Qaytarma Aləti.

İndi proses belə görünür:

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

  1. BOB pulun geri qaytarılması üçün sorğu alır.
  2. BOB bu Geri Ödəniş Aləti haqqında danışır.
  3. Geri qaytarma aləti Ödənişə deyir: "Pulu qaytarın."
  4. Ödəniş pulu qaytarır.
  5. Geri Ödəniş Aləti və BOB statusları bir-biri ilə sinxronlaşdırır, çünki hələlik hər ikisinin buna ehtiyacı var. BOB-da UI, mühasibat uçotu üçün hesabatlar və ümumiyyətlə, asanlıqla ötürülə bilməyən çoxlu məlumat olduğundan, biz hələ tam olaraq Geri Ödəniş Alətinə keçməyə hazır deyilik. İki stulda oturmalısan.
  6. Fiskalizasiya tələbi yox olur.

Nəticədə Kafkada bir növ hadisə avtobusu - hadisə-avtobus düzəltdik, hər şey onun üzərindən başladı. Hurray, indi bircə uğursuzluq nöqtəmiz var (sarkazm).

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Müsbət və mənfi cəhətləri olduqca açıqdır. Avtobus düzəltdik, bu o deməkdir ki, indi bütün xidmətlər ondan asılıdır. Bu, dizaynı asanlaşdırır, lakin sistemdə bir uğursuzluq nöqtəsi təqdim edir. Kafka çökəcək, proses dayanacaq.

Hadisələrə əsaslanan API nədir

Bu suala yaxşı cavab Martin Fowlerin hesabatındadır (GOTO 2017) "Hadisələrə əsaslanan arxitekturanın bir çox mənası".

Qısaca olaraq nə etdik:

  1. vasitəsilə bütün asinxron mübadiləsini tamamlayın hadisələrin saxlanması. Şəbəkə üzərindən hər bir maraqlı istehlakçıya status dəyişikliyi barədə məlumat vermək əvəzinə, biz mərkəzləşdirilmiş yaddaşa status dəyişikliyi haqqında hadisə yazırıq və mövzu ilə maraqlanan istehlakçılar oradan görünən hər şeyi oxuyurlar.
  2. Bu halda hadisə bildirişdir (notifications) haradasa nəyinsə dəyişdiyini. Məsələn, sifariş statusu dəyişdi. Bildirişdə olmayan status dəyişikliyini müşayiət edən bəzi məlumatlarla maraqlanan istehlakçı onun statusunu özü öyrənə bilər.
  3. Maksimum seçim tam hüquqlu hadisə mənbəyidir, dövlət transferi, hansı hadisə emal üçün lazım olan bütün məlumatları ehtiva edir: haradan gəldi və hansı statusa keçdi, məlumat dəqiq olaraq necə dəyişdi və s. Yeganə sual, saxlamağa imkanınız olan məlumatın mümkünlüyü və miqdarıdır.

Geri ödəmə alətinin işə salınmasının bir hissəsi kimi biz üçüncü variantdan istifadə etdik. Təfərrüatlı məlumat çıxarmağa ehtiyac olmadığı üçün bu hadisənin işlənməsini sadələşdirdi, üstəlik, hər bir yeni hadisənin istehlakçılardan aydınlaşdırıcı sorğular yaratdığı ssenarini aradan qaldırdı.

Geri qaytarma aləti xidməti yüklənməyib, deməli, Kafka zərurətdən daha çox qələm dadı var. Düşünmürəm ki, geri qaytarma xidməti yüksək yüklü bir layihəyə çevrilsə, biznes xoşbəxt olardı.

Async mübadiləsi OLDUĞU KİMİ

Asinxron mübadiləsi üçün PHP şöbəsi adətən RabbitMQ-dan istifadə edir. Sorğu üçün məlumatları topladıq, növbəyə qoyduq və eyni xidmətin istehlakçısı onu oxudu və göndərdi (ya da göndərmədi). API-nin özü üçün Lamoda Swagger-dən fəal şəkildə istifadə edir. Biz API dizayn edirik, onu Swagger-də təsvir edirik və müştəri və server kodu yaradırıq. Biz həmçinin bir qədər təkmilləşdirilmiş JSON RPC 2.0 istifadə edirik.

Bəzi yerlərdə ESB avtobuslarından istifadə olunur, bəziləri activeMQ-də yaşayır, lakin, ümumiyyətlə, RabbitMQ - standart.

Async mübadiləsi TO BE

Hadisələr avtobusu vasitəsilə mübadilə dizayn edərkən, bir bənzətmə izlənilə bilər. Biz eyni şəkildə hadisə strukturunun təsvirləri vasitəsilə gələcək məlumat mübadiləsini təsvir edirik. Yaml formatı, kodun yaradılmasını özümüz etməli olduq, generator spesifikasiyaya uyğun olaraq DTO-lar yaradır və müştərilərə və serverlərə onlarla işləməyi öyrədir. Nəsil iki dilə keçir - golang və php. Bu, kitabxanaları ardıcıl saxlamağa kömək edir. Generator qolanq dilində yazılmışdır, buna görə də qogi adını almışdır.

Kafka ilə bağlı hadisə qaynağı tipik bir şeydir. Kafka Confluent-in əsas müəssisə versiyasından bir həll var, var nakadi, domen qardaşlarımız Zalandodan bir həll. Bizim vanil Kafka ilə başlamaq üçün motivasiya - bu, biz onu hər yerdə istifadə edib-etməyəcəyimizə qərar verənə qədər həlli sərbəst buraxmaq, həmçinin manevr və təkmilləşdirmələr üçün özümüzə yer buraxmaq deməkdir: biz özümüz üçün dəstək istəyirik. JSON RPC 2.0, iki dil üçün generatorlar və başqa nə olduğunu görək.

Təəccüblüdür ki, belə bir xoşbəxt vəziyyətdə belə, təxminən oxşar bir iş olan Zalando, təxminən oxşar bir həll yolu tapsa, biz ondan səmərəli istifadə edə bilmirik.

Başlanğıcda memarlıq nümunəsi belədir: biz birbaşa Kafkadan oxuyuruq, ancaq hadisələr avtobusu vasitəsilə yazırıq. Kafkada oxumağa hazır çox şey var: maklerlər, balansçılar və o, üfüqi miqyaslamaya az-çox hazırdır, mən bunu saxlamaq istədim. Biz qeydi bir Gateway aka Events-bus vasitəsilə tamamlamaq istədik və bunun səbəbi budur.

Hadisələr - avtobus

Və ya hadisə avtobusu. Bu, sadəcə olaraq vətəndaşlığı olmayan http şlüzdür və bir neçə mühüm rolu öz üzərinə götürür:

  • Təsdiqləmə istehsalı — hadisələrin spesifikasiyalarımıza uyğun olduğunu yoxlayırıq.
  • Hadisə ustası sistemi, yəni bu, şirkətdə hansı hadisələrin hansı strukturlarla etibarlı hesab edildiyi sualına cavab verən əsas və yeganə sistemdir. Təsdiqləmə sadəcə məzmunu ciddi şəkildə müəyyən etmək üçün məlumat növləri və nömrələri əhatə edir.
  • Hash funksiyası sharding üçün - Kafka mesaj strukturu açar-dəyərdir və açarın heşindən istifadə etməklə onun hara qoyulacağı hesablanır.

Niyə

Biz rasional prosesə malik böyük bir şirkətdə işləyirik. Niyə bir şeyi dəyişdirin? Bu bir təcrübədir, və biz bir sıra faydalar əldə etməyi gözləyirik.

1:n+1 mübadiləsi (birdən çoxa)

Kafka yeni istehlakçıların API-yə qoşulmasını çox asanlaşdırır.

Tutaq ki, bir anda bir neçə sistemdə (və bəzi yeni sistemlərdə) yenilənməli olduğunuz bir kataloqunuz var. Əvvəllər biz set-API tətbiq edən paket icad etdik və master sistem istehlakçı ünvanları haqqında məlumatlandırıldı. İndi master sistem mövzu ilə bağlı yenilikləri göndərir və maraqlanan hər kəs onu oxuyur. Yeni bir sistem ortaya çıxdı - biz onu mövzu üçün qeyd etdik. Bəli, həmçinin paket, lakin daha sadə.

BOB parçası olan geri qaytarma aləti vəziyyətində, onları Kafka vasitəsilə sinxronlaşdırmaq bizim üçün əlverişlidir. Ödənişdə pulun geri qaytarıldığı deyilir: BOB, RT bundan xəbər tutdular, statuslarını dəyişdilər, Fiskalizasiya Xidməti bundan xəbər tutdu və çek verdi.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Müştərini sifariş/qaytarma ilə bağlı xəbərlər barədə xəbərdar edən vahid Bildirişlər Xidməti yaratmaq planlarımız var. İndi bu məsuliyyət sistemlər arasında yayılıb. Bildirişlər Xidmətinə Kafkadan müvafiq məlumatları tutmağı və ona cavab verməyi öyrətməyimiz (və digər sistemlərdə bu bildirişləri söndürmək) kifayət edər. Yeni birbaşa mübadilə tələb olunmayacaq.

Məlumat yönümlü

Sistemlər arasında məlumat şəffaf olur – hansı “qanlı müəssisə”niz olmasından və işinizin nə qədər dolğun olmasından asılı olmayaraq. Lamoda-da sistemlərdən məlumatları toplayan və həm biznes, həm də ağıllı sistemlər üçün təkrar istifadə edilə bilən formaya salan Məlumat Analitikası şöbəsi var. Kafka onlara tez bir zamanda çoxlu məlumat verməyə və bu məlumat axınını aktual saxlamağa imkan verir.

Replikasiya jurnalı

Mesajlar RabbitMQ-da olduğu kimi oxunduqdan sonra yox olmur. Hadisə emal üçün kifayət qədər məlumatı ehtiva etdikdə, bizdə obyektdə son dəyişikliklərin tarixçəsi və arzu olunarsa, bu dəyişiklikləri tətbiq etmək imkanı var.

Replikasiya jurnalının saxlanma müddəti bu mövzuya yazılma intensivliyindən asılıdır; Kafka sizə çevik şəkildə saxlama vaxtı və məlumat həcminə məhdudiyyətlər təyin etməyə imkan verir. İntensiv mövzular üçün, bütün istehlakçıların, hətta qısa müddətli işləməməsi halında belə, yoxa çıxmazdan əvvəl məlumatları oxumağa vaxtının olması vacibdir. üçün məlumat saxlamaq adətən mümkündür gün vahidləri, bu dəstək üçün kifayət qədərdir.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Sonra, Kafka ilə tanış olmayanlar üçün sənədlərin bir az təkrarlanması (şəkil də sənədlərdəndir)

AMQP-nin növbələri var: biz istehlakçı üçün növbəyə mesajlar yazırıq. Tipik olaraq, bir növbə eyni biznes məntiqi ilə bir sistem tərəfindən işlənir. Bir neçə sistemə xəbərdarlıq etmək lazımdırsa, siz proqrama bir neçə növbəyə yazmağı öyrədə və ya onların özünü klonlayan fanout mexanizmi ilə mübadiləni konfiqurasiya edə bilərsiniz.

Kafkanın da oxşar abstraksiyası var mövzu, mesaj yazdığınız, lakin oxuduqdan sonra yoxa çıxmır. Varsayılan olaraq, Kafkaya qoşulduqda bütün mesajları alırsınız və qaldığınız yerdə saxlamaq seçiminiz var. Yəni, siz ardıcıl oxuyursunuz, mesajı oxunmuş kimi qeyd edə bilməzsiniz, ancaq oxumağa davam edə biləcəyiniz id-ni yadda saxlayın. Yerləşdiyiniz İd ofset adlanır və mexanizm commit ofsetdir.

Buna uyğun olaraq fərqli məntiq həyata keçirilə bilər. Məsələn, bizdə müxtəlif ölkələr üçün 4 instansiyada BOB var - Lamoda Rusiya, Qazaxıstan, Ukrayna, Belarusiyadadır. Ayrı-ayrılıqda yerləşdirildiklərinə görə, onların bir qədər fərqli konfiqurasiyaları və öz biznes məntiqi var. Mesajda hansı ölkəyə aid olduğunu göstəririk. Hər bir ölkədə hər bir BOB istehlakçısı fərqli groupId ilə oxuyur və mesaj ona aid deyilsə, onu ötürər, yəni. dərhal ofset +1 edir. Eyni mövzu Ödəniş Xidmətimiz tərəfindən oxunursa, o, bunu ayrıca qrupla edir və buna görə də ofsetlər kəsişmir.

Tədbir tələbləri:

  • Məlumatların tamlığı. İstərdim ki, tədbirin işlənməsi üçün kifayət qədər məlumat olsun.

  • Dürüstlük Tədbirin ardıcıl olduğunu və onu emal edə biləcəyini yoxlamaq üçün Hadisələr avtobusuna həvalə edirik.
  • Sifariş vacibdir. Qayıdış vəziyyətində tarixlə işləmək məcburiyyətindəyik. Bildirişlərlə sifariş vacib deyil, əgər onlar bircins bildirişlərdirsə, hansı sifarişin birinci gəldiyindən asılı olmayaraq e-poçt eyni olacaq. Geri qaytarılma vəziyyətində aydın bir proses var; sifarişi dəyişdirsək, istisnalar yaranacaq, geri qaytarılmayacaq və ya işlənməyəcək - biz fərqli bir statusa sahib olacağıq.
  • Ardıcıllıq. Mağazamız var və indi API əvəzinə hadisələr yaradırıq. Yeni hadisələr və mövcud olanlara edilən dəyişikliklər haqqında məlumatları xidmətlərimizə tez və ucuz ötürmək üçün bir yola ehtiyacımız var. Bu, ayrıca git deposunda və kod generatorlarında ümumi spesifikasiya vasitəsilə əldə edilir. Beləliklə, müxtəlif xidmətlərdəki müştərilər və serverlər əlaqələndirilir.

Lamodada Kafka

Üç Kafka quraşdırmamız var:

  1. Qeydlər;
  2. R&D;
  3. Hadisələr - avtobus.

Bu gün biz yalnız son məqamdan danışırıq. Hadisə-avtobusda çox böyük qurğularımız yoxdur - 3 broker (server) və cəmi 27 mövzu. Bir qayda olaraq, bir mövzu bir prosesdir. Amma bu incə məqamdır və biz indi ona toxunacağıq.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Yuxarıda rps qrafiki var. Geri qaytarma prosesi firuzəyi xətt ilə işarələnir (bəli, X oxundakı), çəhrayı xətt isə məzmun yeniləmə prosesidir.

Lamoda kataloqu milyonlarla məhsulu ehtiva edir və məlumatlar hər zaman yenilənir. Bəzi kolleksiyalar dəbdən düşür, onların yerinə yeniləri buraxılır, kataloqda daim yeni modellər peyda olur. Biz sabah müştərilərimiz üçün nəyin maraqlı olacağını proqnozlaşdırmağa çalışırıq, ona görə də daim yeni şeylər alırıq, onların fotoşəkillərini çəkirik və vitrinini yeniləyirik.

Çəhrayı zirvələr məhsul yeniləmələri, yəni məhsullarda dəyişikliklərdir. Görmək olar ki, uşaqlar şəkil çəkdirdilər, şəkil çəkdirdilər, sonra yenə! - hadisələr paketini yüklədi.

Lamoda Events istifadə halları

Aşağıdakı əməliyyatlar üçün qurulmuş arxitekturadan istifadə edirik:

  • Qayıdış statusunun izlənməsi: bütün əlaqəli sistemlərdən fəaliyyətə çağırış və statusun izlənməsi. Ödəniş, statuslar, fiskallaşdırma, bildirişlər. Burada yanaşmanı sınaqdan keçirdik, alətlər hazırladıq, bütün səhvləri topladıq, sənədlər yazdıq və həmkarlarımıza ondan necə istifadə edəcəyimizi söylədik.
  • Məhsul kartları yenilənir: konfiqurasiya, metadata, xüsusiyyətlər. Bir sistem oxuyur (göstərir), bir neçəsi isə yazır.
  • E-poçt, push və sms: sifariş yığıldı, sifariş gəldi, qaytarılma qəbul edildi və s., çox var.
  • Anbar, anbarın yenilənməsi — əşyaların kəmiyyətcə yenilənməsi, sadəcə rəqəmlər: anbara gəliş, qayıdış. Malların rezervasiyası ilə əlaqəli bütün sistemlərin ən aktual məlumatlarla işləməsi lazımdır. Hazırda fond yeniləmə sistemi olduqca mürəkkəbdir; Kafka onu sadələşdirəcək.
  • Məlumat Təhlili (Ar-ge şöbəsi), ML alətləri, analitika, statistika. Biz informasiyanın şəffaf olmasını istəyirik - Kafka bunun üçün çox uyğundur.

İndi son altı ayda baş verən böyük zərbələr və maraqlı kəşflər haqqında daha maraqlı hissə.

Dizayn problemləri

Tutaq ki, biz yeni bir şey etmək istəyirik - məsələn, bütün çatdırılma prosesini Kafkaya köçürün. İndi prosesin bir hissəsi BOB-da Sifariş Emalı ilə həyata keçirilir. Sifarişin çatdırılma xidmətinə ötürülməsi, aralıq anbara daşınması və s. arxasında status modeli var. Bütün monolit, hətta iki, üstəgəl çatdırılma üçün ayrılmış bir dəstə API var. Onlar çatdırılma haqqında daha çox şey bilirlər.

Bunlar oxşar sahələr kimi görünür, lakin BOB-da Sifariş Emalı və Göndərmə Sistemində fərqli statuslar var. Məsələn, bəzi kuryer xidmətləri aralıq statusları deyil, yalnız son statusları göndərir: "çatdırıldı" və ya "itirildi". Digərləri, əksinə, malların hərəkəti haqqında çox ətraflı məlumat verirlər. Hər kəsin öz təsdiqləmə qaydaları var: bəziləri üçün e-poçt etibarlıdır, yəni emal olunacaq; digərləri üçün bu etibarlı deyil, lakin əlaqə üçün telefon nömrəsi olduğu üçün sifariş hələ də işlənəcək və kimsə belə bir sifarişin ümumiyyətlə işlənməyəcəyini söyləyəcək.

Məlumat axını

Kafka məsələsində məlumat axınının təşkili məsələsi ortaya çıxır. Bu tapşırıq bir neçə məqama əsaslanan strategiyanın seçilməsini nəzərdə tutur; gəlin hamısından keçək.

Bir mövzuda yoxsa fərqli mövzularda?

Tədbirin spesifikasiyası var. BOB-da biz belə və belə bir sifarişin çatdırılması lazım olduğunu yazırıq və göstəririk: sifariş nömrəsi, onun tərkibi, bəzi SKU-lar və ştrix-kodlar və s. Mallar anbara çatdıqda, çatdırılma statusları, vaxt ştamplarını və lazım olan hər şeyi ala biləcək. Lakin sonra biz BOB-da bu məlumatla bağlı yeniləmələri almaq istəyirik. Çatdırılmadan məlumatların alınmasında əks prosesimiz var. Bu eyni hadisədir? Yoxsa bu, öz mövzusuna layiq olan ayrıca bir mübadilədir?

Çox güman ki, onlar çox oxşar olacaqlar və bir mövzu yaratmaq istəyi əsassız deyil, çünki ayrıca mövzu ayrı-ayrı istehlakçılar, ayrıca konfiqurasiyalar, bütün bunların ayrıca nəsli deməkdir. Amma fakt deyil.

Yeni sahə və ya yeni hadisə?

Ancaq eyni hadisələrdən istifadə etsəniz, başqa bir problem yaranır. Məsələn, bütün çatdırılma sistemləri BOB-un yarada biləcəyi DTO növünü yarada bilməz. Biz onlara identifikatoru göndəririk, lakin ehtiyac olmadığı üçün onu saxlamırlar və hadisə avtobusu prosesinin başlaması baxımından bu sahə tələb olunur.

Hadisə avtobusu üçün bu sahənin tələb olunduğu bir qayda təqdim etsək, onda biz BOB-da və ya başlanğıc hadisə idarəedicisində əlavə yoxlama qaydaları təyin etməyə məcbur oluruq. Doğrulama bütün xidmətə yayılmağa başlayır - bu çox rahat deyil.

Başqa bir problem, artan inkişaf üçün şirnikdir. Bizə deyirlər ki, tədbirə nəsə əlavə etmək lazımdır, bəlkə də, fikir versək, bu, ayrıca tədbir olmalı idi. Amma bizim sxemimizdə ayrıca hadisə ayrı bir mövzudur. Ayrı bir mövzu yuxarıda təsvir etdiyim bütün prosesdir. Tərtibatçı sadəcə olaraq JSON sxeminə başqa bir sahə əlavə etmək və onu yenidən yaratmaq həvəsinə düşür.

Ödənişlərin geri qaytarılması vəziyyətində, hadisələrin baş verməsinə yarım il ərzində çatdıq. Geri qaytarma yeniləməsi adlı bir meta-tədbirimiz var idi və bu yeniləmənin əslində nə olduğunu təsvir edən bir növ sahəsi var idi. Buna görə də, bu hadisəni bu tiplə necə təsdiq edəcəyimizi söyləyən validatorlarla “gözəl” açarlarımız var idi.

Hadisə versiyası

Kafkadakı mesajları təsdiqləmək üçün istifadə edə bilərsiniz avro, lakin dərhal üzərinə uzanıb Confluentdən istifadə etmək lazım idi. Bizim vəziyyətimizdə versiya ilə diqqətli olmalıyıq. Replikasiya jurnalından mesajları təkrar oxumaq həmişə mümkün olmayacaq, çünki model “solmuş”. Əsasən, modelin geriyə uyğun olması üçün versiyaların qurulması ortaya çıxır: məsələn, sahəni müvəqqəti olaraq isteğe bağlı edin. Fərqlər çox güclüdürsə, yeni bir mövzuda yazmağa başlayırıq və müştərilər köhnəni oxuyub bitirdikdə köçürürük.

Arakəsmələrin oxunma sırasına zəmanət verilir

Kafkanın içindəki mövzular bölmələrə bölünür. Müəssisələri və mübadilələri hazırlayarkən bu o qədər də vacib deyil, lakin onu necə istehlak etmək və miqyaslaşdırmaq barədə qərar verərkən vacibdir.

Adi halda bir mövzunu Kafkada yazırsan. Varsayılan olaraq, bir bölmə istifadə olunur və bu mövzudakı bütün mesajlar ona gedir. İstehlakçı isə bu mesajları ardıcıl olaraq oxuyur. İndi deyək ki, mesajların iki fərqli istehlakçı tərəfindən oxunması üçün sistemi genişləndirməliyik. Məsələn, siz SMS göndərirsinizsə, o zaman Kafkaya əlavə bölmə yaratmağı söyləyə bilərsiniz və Kafka mesajları iki hissəyə bölməyə başlayacaq - yarısı burada, yarısı burada.

Kafka onları necə bölür? Hər mesajın gövdəsi (JSON-u saxladığımız) və açarı var. Bu düyməyə mesajın hansı bölməyə daxil olacağını müəyyən edən hash funksiyası əlavə edə bilərsiniz.

Geri qaytarma ilə bağlı vəziyyətimizdə bu vacibdir, əgər iki bölmə götürsək, o zaman paralel istehlakçının ikinci hadisəni birincidən əvvəl emal etməsi və problem olması şansı var. Hash funksiyası eyni açarı olan mesajların eyni bölmədə bitməsini təmin edir.

Hadisələr və əmrlər

Bu, qarşılaşdığımız başqa bir problemdir. Hadisə müəyyən bir hadisədir: biz deyirik ki, haradasa nəsə baş verib (bir şey_baş verib), məsələn, məhsul ləğv edilib və ya pul geri qaytarılıb. Əgər kimsə bu hadisələrə qulaq asarsa, o zaman “ləğv edilən maddə”yə uyğun olaraq, geri qaytarma subyekti yaradılacaq və quraşdırmaların bir yerində “geri ödəniş baş verdi” yazılacaq.

Ancaq adətən, hadisələri tərtib edərkən, onları boş yerə yazmaq istəmirsiniz - kiminsə onları oxuyacağına inanırsınız. Nəyinsə_baş verdiyini (ləğv edildiyini, pulun qaytarıldığını) deyil, nəyinsə_edilməli olduğunu yazmaq istəyi yüksəkdir. Məsələn, əşya geri qaytarılmağa hazırdır.

Bir tərəfdən, hadisənin necə istifadə ediləcəyini təklif edir. Digər tərəfdən, bu, normal bir hadisə adı kimi daha az səslənir. Bundan əlavə, do_something əmri buradan çox da uzaqda deyil. Amma kimsənin bu hadisəni oxuduğuna zəmanətiniz yoxdur; və əgər onu oxuyursansa, onda müvəffəqiyyətlə oxuyursan; və əgər siz onu müvəffəqiyyətlə oxuyursunuzsa, deməli, bir şey etdiniz və o da uğurlu oldu. Hadisə bir şeyə çevrildiyi anda rəy lazım olur və bu, problemdir.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

RabbitMQ-da asinxron mübadilədə, mesajı oxuduğunuz zaman http-ə gedin, cavabınız var - ən azı mesajın alındığına dair. Kafkaya yazanda elə bir mesaj var ki, Kafkaya yazmısan, amma onun necə işləndiyi barədə heç nə bilmirsən.

Ona görə də bizim vəziyyətimizdə cavab tədbiri tətbiq etməli və monitorinq qurmalı idik ki, bu qədər tədbir göndərilibsə, filan vaxtdan sonra eyni sayda cavab tədbirləri gəlsin. Əgər bu baş vermirsə, deməli, bir şey səhv getmiş kimi görünür. Məsələn, biz “ready_to_to_refund” tədbirini göndərmişiksə, geri ödənişin yaradılacağını, pulun müştəriyə qaytarılacağını və “pul_geri qaytarılmış” tədbirinin bizə göndəriləcəyini gözləyirik. Amma bu dəqiq deyil, ona görə də monitorinq lazımdır.

Nuances

Kifayət qədər açıq bir problem var: bir mövzudan ardıcıl oxusanız və bəzi pis mesajınız varsa, istehlakçı düşəcək və daha da irəli getməyəcəksiniz. Sizə lazımdır bütün istehlakçıları dayandırın, oxumağa davam etmək üçün daha çox ofset edin.

Biz bu haqda bilirdik, hesablaşdıq, amma yenə də baş verdi. Və bu ona görə baş verdi ki, hadisə hadisələr-avtobus nöqteyi-nəzərindən keçərli idi, hadisə tətbiqin validatoru nöqteyi-nəzərindən keçərli idi, lakin PostgreSQL nöqteyi-nəzərindən keçərli deyildi, çünki bizim bir sistemdə UNSIGNED INT ilə MySQL və yeni yazılmış sistemdə yalnız INT ilə PostgreSQL var idi. Onun ölçüsü bir az kiçikdir və Id uyğun gəlmir. Symfony istisna olmaqla öldü. Biz, əlbəttə ki, istisnanı tutduq, çünki ona güvənirdik və bu ofseti yerinə yetirmək niyyətindəydik, lakin bundan əvvəl problem sayğacını artırmaq istədik, çünki mesaj uğursuz şəkildə işlənildi. Bu layihədəki sayğaclar da verilənlər bazasındadır və Symfony artıq verilənlər bazası ilə əlaqəni bağlayıb və ikinci istisna ofset etmək şansı olmadan bütün prosesi öldürüb.

Xidmət bir müddət uzandı - xoşbəxtlikdən, Kafka ilə bu o qədər də pis deyil, çünki mesajlar qalır. İş bərpa edildikdə, onları oxuyub bitirə bilərsiniz. Rahatdır.

Kafka alətlər vasitəsilə ixtiyari ofset təyin etmək qabiliyyətinə malikdir. Ancaq bunu etmək üçün bütün istehlakçıları dayandırmalısınız - bizim vəziyyətimizdə istehlakçıların, yenidən yerləşdirmələrin olmayacağı ayrıca buraxılış hazırlayın. Sonra Kafkada alətlər vasitəsilə ofseti dəyişə bilərsiniz və mesaj keçəcək.

Başqa bir nüans - replikasiya jurnalı vs rdkafka.so - layihəmizin xüsusiyyətləri ilə bağlıdır. Biz PHP-dən istifadə edirik və PHP-də, bir qayda olaraq, bütün kitabxanalar Kafka ilə rdkafka.so repozitoriyası vasitəsilə əlaqə saxlayır və sonra bir növ sarğı var. Bəlkə də bunlar bizim şəxsi çətinliklərimizdir, amma məlum oldu ki, artıq oxuduqlarımızın bir hissəsini təkrar oxumaq o qədər də asan deyil. Ümumiyyətlə, proqram təminatı ilə bağlı problemlər var idi.

Bölmələrlə işləməyin xüsusiyyətlərinə qayıdaraq, bu, sənədlərdə birbaşa yazılmışdır istehlakçılar >= mövzu bölmələri. Amma mən bu haqda istədiyimdən çox gec öyrəndim. Ölçmək və iki istehlakçıya sahib olmaq istəyirsinizsə, ən azı iki bölmə lazımdır. Yəni, 20 min mesajın toplandığı bir bölməniz varsa və təzəsini etmisinizsə, mesajların sayı tezliklə bərabərləşməyəcək. Buna görə də, iki paralel istehlakçıya sahib olmaq üçün arakəsmələrlə məşğul olmaq lazımdır.

Monitorinq

Düşünürəm ki, bizim monitorinq üsulumuz mövcud yanaşmada hansı problemlərin olduğunu daha da aydınlaşdıracaq.

Məsələn, biz bazada nə qədər məhsulun son vaxtlar statusunu dəyişdiyini hesablayırıq və müvafiq olaraq bu dəyişikliklərə əsasən hadisələr baş verməli idi və bu rəqəmi monitorinq sistemimizə göndəririk. Sonra Kafkadan ikinci rəqəmi alırıq, əslində nə qədər hadisə qeydə alınıb. Aydındır ki, bu iki rəqəm arasındakı fərq həmişə sıfır olmalıdır.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Bundan əlavə, prodüserin necə getdiyini, hadisələr-avtobusun mesajlarını alıb-almadığını və istehlakçının necə davrandığını izləmək lazımdır. Məsələn, aşağıdakı qrafiklərdə, Geri Ödəniş Aləti yaxşı işləyir, lakin BOB-un bəzi problemləri var (mavi zirvələr).

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Mən artıq istehlakçı qruplarının geriləməsini qeyd etdim. Kobud desək, bu, oxunmamış mesajların sayıdır. Ümumiyyətlə, istehlakçılarımız tez işləyirlər, ona görə də gecikmə adətən 0 olur, lakin bəzən qısamüddətli pik ola bilər. Kafka bunu qutudan kənarda edə bilər, ancaq müəyyən interval təyin etmək lazımdır.

Layihə var dəməkbu sizə Kafka haqqında daha çox məlumat verəcəkdir. O, sadəcə olaraq, bu qrupun işinin vəziyyətini vermək üçün istehlakçı qrupu API-dən istifadə edir. OK və Failed əlavə olaraq, bir xəbərdarlıq var və istehlakçılarınızın istehsal tempinin öhdəsindən gələ bilməyəcəyini öyrənə bilərsiniz - yazılanları yoxlamaq üçün vaxtları yoxdur. Sistem olduqca ağıllıdır və istifadəsi asandır.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

API cavabı belə görünür. Budur qrup bob-live-fifa, partition refund.update.v1, status OK, lag 0 - sonuncu yekun ofset belə və belədir.

Kafka-da asinxron API ilə Refund Tool xidmətini inkişaf etdirmək təcrübəsi

Monitorinq yenilənmiş_SLA (ilişib) Artıq qeyd etdim. Məsələn, məhsul geri qaytarılmağa hazır statusuna dəyişib. Cron-u quraşdırırıq, deyir ki, 5 dəqiqə ərzində bu obyekt geri qaytarılmayıbsa (ödəniş sistemləri vasitəsilə pulu çox tez qaytarırıq), onda bir şey səhv getdi və bu, mütləq dəstək üçün bir işdir. Ona görə də biz sadəcə olaraq belə şeyləri oxuyan Cron-u götürürük və əgər onlar 0-dan böyükdürsə, o zaman xəbərdarlıq göndərir.

Xülasə etmək üçün hadisələrdən istifadə edərkən əlverişlidir:

  • məlumat bir neçə sistemə lazımdır;
  • emalın nəticəsi vacib deyil;
  • az hadisələr və ya kiçik hadisələr var.

Görünür ki, məqalənin çox konkret mövzusu var - Kafkada asinxron API, lakin bununla əlaqədar mən bir anda çox şeyi tövsiyə etmək istərdim.
Birincisi, sonrakı Yüksək Yük ++ noyabra qədər gözləmək lazımdır, aprel ayında Sankt-Peterburq versiyası olacaq və iyunda Novosibirskdə yüksək yüklər haqqında danışacağıq.
İkincisi, məruzənin müəllifi Sergey Zaika biliklərin idarə edilməsi üzrə yeni konfransımızın Proqram Komitəsinin üzvüdür. KnowledgeConf. Konfrans bir günlükdür, aprelin 26-da baş tutacaq, lakin proqramı çox gərgindir.
Və may ayında olacaq PHP Rusiya и RIT++ (DevOpsConf daxil olmaqla) - siz də orada mövzunu təklif edə, təcrübəniz haqqında danışa və doldurulmuş konuslarınızdan şikayət edə bilərsiniz.

Mənbə: www.habr.com

Добавить комментарий