Kafka və mikroservislər: ümumi baxış

Kafka və mikroservislər: ümumi baxış

Hamıya salam. Bu yazıda sizə Avitoda niyə doqquz ay əvvəl Kafkanı seçdiyimizi və onun nə olduğunu izah edəcəyəm. İstifadə vəziyyətlərindən birini - mesaj brokerini paylaşacağam. Və nəhayət, Kafkanı Xidmət yanaşması kimi istifadə etməklə əldə etdiyimiz üstünlüklərdən danışaq.

problem

Kafka və mikroservislər: ümumi baxış

Birincisi, bir az kontekst. Bir müddət əvvəl biz monolit memarlıqdan uzaqlaşmağa başladıq və indi Avito artıq bir neçə yüz müxtəlif xidmətlərə malikdir. Onların öz depoları, öz texnologiya yığını var və biznes məntiqinin öz hissəsinə cavabdehdirlər.

Çoxlu sayda xidmətlə bağlı problemlərdən biri də ünsiyyətdir. A xidməti tez-tez B Xidmətinin malik olduğu məlumatı bilmək istəyir.Bu halda A Xidməti sinxron API vasitəsilə B Xidmətinə daxil olur. B xidməti D və D xidmətlərində nə baş verdiyini bilmək istəyir və onlar da öz növbəsində A və B xidmətləri ilə maraqlanırlar. Belə “maraqlı” xidmətlər çox olduqda, onların arasındakı əlaqələr dolaşıq dolaşıqlığa çevrilir.

Eyni zamanda, A xidməti istənilən vaxt əlçatmaz ola bilər. Və bu halda B xidməti və ona bağlı bütün digər xidmətlər nə etməlidir? Və bir iş əməliyyatını başa çatdırmaq üçün ardıcıl sinxron zənglər zənciri tələb olunarsa, bütün əməliyyatın uğursuzluq ehtimalı daha da yüksək olur (və zəncir nə qədər uzun olsa, bir o qədər yüksəkdir).

Texnologiya seçimi

Kafka və mikroservislər: ümumi baxış

Yaxşı, problemlər aydındır. Xidmətlər arasında mərkəzləşdirilmiş mesajlaşma sistemi yaratmaqla onları aradan qaldırmaq olar. İndi xidmətlərin hər biri yalnız bu mesajlaşma sistemi haqqında bilməlidir. Bundan əlavə, sistemin özü nasazlığa dözümlü və üfüqi olaraq genişlənə bilən olmalıdır, həmçinin qəzalar zamanı sonrakı emal üçün giriş buferi toplamalıdır.

İndi mesajın çatdırılmasının həyata keçiriləcəyi texnologiyanı seçək. Bunu etmək üçün əvvəlcə ondan nə gözlədiyimizi anlayaq:

  • xidmətlər arasında mesajlar itməməlidir;
  • mesajlar təkrarlana bilər;
  • mesajlar bir neçə gün ərzində saxlanıla və oxuna bilər (davamlı bufer);
  • xidmətlər onları maraqlandıran məlumatlara abunə ola bilər;
  • birdən çox xidmət eyni məlumatları oxuya bilər;
  • mesajlar təfərrüatlı, həcmli yükdən ibarət ola bilər (hadisə ilə bağlı vəziyyətin ötürülməsi);
  • Bəzən mesajların sırasına zəmanət vermək lazımdır.

Yüksək ötürmə qabiliyyətinə malik (saniyədə bir neçə kilobaytlıq ən azı 100k mesaj) ən genişlənən və etibarlı sistemi seçmək bizim üçün çox vacib idi.

Bu nöqtədə biz RabbitMQ (yüksək rps-də sabit saxlamaq çətindir), SkyTools-dan PGQ (kifayət qədər sürətli deyil və yaxşı ölçülənmir) və NSQ (davamlı deyil) ilə vidalaşdıq. Biz şirkətimizdə bütün bu texnologiyalardan istifadə edirik, lakin onlar həll olunan problemə uyğun deyildi.

Sonra, bizim üçün yeni olan texnologiyalara - Apache Kafka, Apache Pulsar və NATS Streaming-ə baxmağa başladıq.

Pulsar ilk atılan oldu. Qərara gəldik ki, Kafka və Pulsar olduqca oxşar həllərdir. Pulsarın böyük şirkətlər tərəfindən sınaqdan keçirilməsinə, daha yeni olmasına və daha az gecikmə (nəzəri olaraq) təklif etməsinə baxmayaraq, biz bu ikisinin Kafkanı bu cür tapşırıqlar üçün faktiki standart olaraq tərk etmək qərarına gəldik. Gələcəkdə yəqin ki, Apache Pulsara qayıdacayıq.

İndi iki namizəd qalıb: NATS Streaming və Apache Kafka. Hər iki həll yolunu bir qədər təfərrüatı ilə öyrəndik və hər ikisi tapşırığa uyğun idi. Amma sonda biz NATS Streaming-in nisbi gəncliyindən (və əsas tərtibatçılardan biri olan Tayler Treat-ın layihəni tərk edib özünün layihəsini - Liftbridge-ə başlamaq qərarına gəlməsindən) qorxduq. Eyni zamanda, NATS Streaming-in Clustering rejimi güclü üfüqi miqyaslama imkanını təmin etmədi (yəqin ki, 2017-ci ildə bölmə rejiminin əlavə edilməsindən sonra bu, artıq problem deyil).

Bununla belə, NATS Streaming Go-da yazılmış və Cloud Native Computing Foundation tərəfindən dəstəklənən gözəl texnologiyadır. Apache Kafkadan fərqli olaraq, onun işləməsi üçün Zookeeper-ə ehtiyac yoxdur (bəlkə də tezliklə eyni şeyi Kafka haqqında da demək olar), çünki o, RAFT-i daxildə həyata keçirir. Eyni zamanda, NATS Streaming-i idarə etmək daha asandır. Gələcəkdə bu texnologiyaya qayıdacağımızı istisna etmirik.

Yenə də bu gün qalibimiz Apache Kafkadır. Testlərimizdə o, kifayət qədər sürətli (1 kilobayt mesaj həcmi ilə oxumaq və yazmaq üçün saniyədə bir milyondan çox mesaj), kifayət qədər etibarlı, yüksək miqyaslana bilən və böyük şirkətlərin istehsalında təcrübə ilə sübut edildiyini sübut etdi. Bundan əlavə, Kafka ən azı bir neçə böyük kommersiya şirkəti dəstəkləyir (biz, məsələn, Confluent versiyasından istifadə edirik) və Kafka da inkişaf etmiş bir ekosistemə malikdir.

Kafkaya baxış

Başlamazdan əvvəl dərhal əla bir kitabı tövsiyə etmək istərdim - "Kafka: Qəti bələdçi" (Rusca tərcüməsi də var, amma terminlər bir az ağılları qarışdırır). Bu, Kafka haqqında əsas anlayış və hətta bir az daha çox şey əldə etmək üçün lazım olan məlumatları ehtiva edir. Apache-nin sənədləri və Confluent-in bloqu da yaxşı yazılmış və oxunması asandır.

Odur ki, gəlin Kafkanın necə işlədiyinə quşbakışı baxaq. Kafkanın əsas topologiyası istehsalçı, istehlakçı, broker və zookeperdən ibarətdir.

Dəllal

Kafka və mikroservislər: ümumi baxış

Broker məlumatlarınızın saxlanmasına cavabdehdir. Bütün məlumatlar ikili formada saxlanılır və broker onların nə olduğunu və strukturunun nə olduğunu çox az bilir.

Hər bir məntiqi hadisə növü adətən öz ayrıca mövzusunda yerləşir. Məsələn, reklamın yaradılması hadisəsi item.created mövzusuna, onun dəyişdirilməsi hadisəsi item.changed-ə düşə bilər. Mövzular hadisə təsnifatı kimi qəbul edilə bilər. Mövzu səviyyəsində siz konfiqurasiya parametrlərini təyin edə bilərsiniz, məsələn:

  • saxlanılan məlumatların miqdarı və/və ya onun yaşı (tutma.bayt, saxlama.ms);
  • məlumat ehtiyatı faktoru (replikasiya faktoru);
  • bir mesajın maksimum ölçüsü (maksimum mesaj.bayt);
  • mövzuya verilənlərin yazıla biləcəyi ardıcıl replikaların minimum sayı (min.insync.replicas);
  • potensial məlumat itkisi (unclean.leader.election.enable);
  • və daha çox (https://kafka.apache.org/documentation/#topicconfigs).

Öz növbəsində, hər bir mövzu bir və ya bir neçə bölməyə bölünür. Hadisələr son nəticədə partiyalarda olur. Əgər klasterdə birdən çox broker varsa, o zaman bölmələr bütün brokerlər arasında bərabər paylanacaq (mümkün qədər), bu da bir mövzuya yazı və oxunma yükünü eyni anda bir neçə broker arasında miqyaslandırmağa imkan verəcək.

Diskdə hər bölmə üçün məlumatlar standart olaraq bir gigabayta bərabər seqment faylları şəklində saxlanılır (log.segment.bytes vasitəsilə idarə olunur). Əhəmiyyətli bir xüsusiyyət, verilənlərin seqmentlərdəki bölmələrdən (tutma işə salındıqda) silinməsidir (bölmədən bir hadisəni silə bilməzsiniz, yalnız bütün seqmenti və yalnız qeyri-aktivi silə bilərsiniz).

Zəkaçı

Zookeeper metadata anbarı və koordinator kimi çıxış edir. Məhz o, brokerlərin sağ olub-olmadığını deyə bilir (buna zookeeper-shell əmri ilə zookeperin gözü ilə baxa bilərsiniz) ls /brokers/ids), hansı broker nəzarətçidir (get /controller), bölmələrin replikaları ilə sinxronizasiya olub-olmaması (get /brokers/topics/topic_name/partitions/partition_number/state). Həmçinin, istehsalçı və istehlakçı əvvəlcə hansı brokerdə hansı mövzuların və arakəsmələrin saxlandığını öyrənmək üçün zookeper üçün gedəcəklər. Mövzu üçün 1-dən çox təkrarlama əmsalı göstərildiyi hallarda zookeeper hansı bölmələrin lider olduğunu göstərəcək (onlar yazılacaq və ondan oxunacaq). Broker nasazlığı halında, yeni lider bölmələri haqqında məlumat zookeeper-də qeyd olunacaq (1.1.0 versiyasından asinxron olaraq, və bu vacibdir).

Kafkanın köhnə versiyalarında zookeper ofsetlərin saxlanmasına da cavabdeh idi, lakin indi onlar xüsusi bir mövzuda saxlanılır. __consumer_offsets brokerdə (baxmayaraq ki, hələ də bu məqsədlər üçün zookeeperdən istifadə edə bilərsiniz).

Məlumatlarınızı balqabaq halına gətirməyin ən asan yolu zookeperdən məlumat itirməkdir. Belə bir ssenaridə nəyi və haradan oxumaq lazım olduğunu başa düşmək çox çətin olacaq.

Istehsalçı

İstehsalçı çox vaxt məlumatı birbaşa Apache Kafkaya yazan xidmətdir. İstehsalçı mövzu mesajlarını saxlamaq üçün mövzu seçir və ona məlumat yazmağa başlayır. Məsələn, istehsalçı bir reklam xidməti ola bilər. Bu zaman tematik mövzulara “reklam yaradıldı”, “reklam yeniləndi”, “reklam silindi” və s. kimi hadisələri göndərəcək. Hər bir hadisə açar-dəyər cütüdür.

Varsayılan olaraq, açar göstərilməyibsə (sifarişi itirir) və açar varsa, MurmurHash (açar) vasitəsilə (bir bölmə daxilində sifariş) istifadə edərək, bütün hadisələr mövzu bölmələri arasında bölüşdürülür.

Dərhal qeyd etmək lazımdır ki, Kafka yalnız bir partiyada hadisələrin ardıcıllığına zəmanət verir. Ancaq əslində bu, çox vaxt problem deyil. Məsələn, eyni bəyannamədəki bütün dəyişiklikləri bir bölməyə əlavə etməyinizə əmin ola bilərsiniz (beləliklə, bəyannamə daxilində bu dəyişikliklərin ardıcıllığını qoruyub saxlaya bilərsiniz). Siz həmçinin hadisə sahələrindən birinə ardıcıllıq nömrəsi göndərə bilərsiniz.

Istehlakçı

Kafka və mikroservislər: ümumi baxış

İstehlakçı Apache Kafka-dan məlumatların alınmasına cavabdehdir. Yuxarıdakı misala qayıtsaq, istehlakçı moderasiya xidməti ola bilər. Bu xidmət reklam xidməti mövzusuna abunə olacaq və yeni reklam görünəndə onu qəbul edəcək və müəyyən edilmiş bəzi siyasətlərə uyğunluğunu təhlil edəcək.

Apache Kafka istehlakçının hansı son hadisələri aldığını xatırlayır (bunun üçün xidmət mövzusu istifadə olunur). __consumer__offsets), bununla da oxumaq uğurlu olarsa, istehlakçının eyni mesajı iki dəfə almamasını təmin edir. Bununla belə, əgər enable.auto.commit = true variantından istifadə etsəniz və istehlakçının mövzudakı mövqeyini izləmək işini tamamilə Kafkaya həvalə etsəniz, məlumatları itirmək. İstehsal kodunda, əksər hallarda istehlakçının mövqeyi əl ilə idarə olunur (geliştirici oxunuş hadisəsinin baş verməli olduğu anı idarə edir).

Bir istehlakçının kifayət etmədiyi hallarda (məsələn, yeni hadisələrin axını çox böyükdür), siz onları bir istehlakçı qrupunda birləşdirərək daha bir neçə istehlakçı əlavə edə bilərsiniz. İstehlakçı qrupu məntiqi olaraq istehlakçı ilə eynidir, lakin məlumat qrup üzvləri arasında paylanır. Bu, hər bir iştirakçıya mesajların öz payını götürmək imkanı verir və bununla da oxuma sürətini artırır.

Test nəticələri

Kafka və mikroservislər: ümumi baxış

Burada çox izahlı mətn yazmayacağam, sadəcə əldə etdiyim nəticələri paylaşacam. Sınaq 3 fiziki maşında (12 CPU, 384 GB RAM, 15k SAS DISK, 10GBit/s Net) aparılıb, brokerlər və zookeeper lxc-də yerləşdirilib.

Performans testi

Test zamanı aşağıdakı nəticələr əldə edildi.

  • 1 istehsalçı tərəfindən eyni vaxtda 9KB mesajların qeydə alınması sürəti saniyədə 1300000 hadisədir.
  • 1 istehlakçının eyni vaxtda 9KB mesaj oxuma sürəti saniyədə 1500000 hadisədir.

Arızaya dözümlülük testi

Sınaq zamanı aşağıdakı nəticələr əldə edilmişdir (3 broker, 3 zooparkçı).

  • Brokerlərdən birinin anormal xitam verilməsi klasterin dayanmasına və ya əlçatmaz olmasına səbəb olmur. İş adi qaydada davam edir, amma qalan maklerlərin iş yükü ağırdır.
  • Üç brokerdən ibarət klaster və min.isr = 2 vəziyyətində iki brokerin qeyri-normal dayandırılması klasterin yazı üçün əlçatmaz olmasına, lakin oxumaq üçün əlçatan olmasına gətirib çıxarır. Əgər min.isr = 1 olarsa, klaster həm oxumaq, həm də yazmaq üçün əlçatan olmağa davam edir. Bununla belə, bu rejim yüksək məlumat təhlükəsizliyi tələbinə ziddir.
  • Zookeeper serverlərindən birinin anormal bağlanması klasterin dayanmasına və ya əlçatmaz olmasına səbəb olmur. İş adi qaydada davam edir.
  • İki Zookeeper serverinin anormal bağlanması Zookeeper serverlərindən ən azı biri bərpa olunana qədər klasterin əlçatan olmaması ilə nəticələnir. Bu ifadə 3 serverdən ibarət Zookeeper klasteri üçün doğrudur. Nəticədə, araşdırmalardan sonra nasazlığa dözümlülüyünü artırmaq üçün Zookeeper klasterinin 5 serverə qədər artırılması qərara alındı.

Kafka bir xidmət olaraq

Kafka və mikroservislər: ümumi baxış

Biz əminik ki, Kafka bizə tapşırılan vəzifəni həll etməyə imkan verən əla texnologiyadır (mesaj brokerini həyata keçirir). Bununla belə, xidmətlərin birbaşa Kafkaya daxil olmasını qadağan etmək qərarına gəldik və onu data-bus xidməti ilə bağladıq. Niyə bunu etdik? Əslində bir neçə səbəb var.

  • Data-bus, Kafka ilə inteqrasiya ilə bağlı bütün vəzifələri öz üzərinə götürdü (istehlakçıların və istehsalçıların həyata keçirilməsi və konfiqurasiyası, monitorinq, xəbərdarlıq, giriş, miqyaslama və s.). Beləliklə, mesaj brokeri ilə inteqrasiya mümkün qədər sadədir.

  • Data-bus bizə Kafka ilə işləmək üçün müəyyən bir dildən və ya kitabxanadan mücərrədləşməyə imkan verdi.

  • Məlumat avtobusu digər xidmətlərə saxlama təbəqəsini mücərrədləşdirməyə imkan verdi. Bəlkə nə vaxtsa biz Kafkanı Pulsara dəyişəcəyik və heç kim heç nə görməyəcək (bütün xidmətlər yalnız data-bus API haqqında bilir).

  • Data-bus hadisə sxemlərinin təsdiqini öz üzərinə götürdü.

  • Doğrulama data-bus istifadə edərək həyata keçirilir.

  • Data-bus örtüyü altında biz fasiləsiz Kafka versiyalarını sakitcə yeniləyə, istehsalçıların, istehlakçıların, brokerlərin və s. konfiqurasiyaları mərkəzləşdirilmiş şəkildə idarə edə bilərik.

  • Data-bus bizə Kafkada olmayan bizə lazım olan funksiyaları əlavə etməyə imkan verdi (məsələn, mövzuların yoxlanılması, klasterdəki anomaliyaların monitorinqi, DLQ yaradılması və s.).

  • Data-bus sizə bütün xidmətlər üçün mərkəzləşdirilmiş şəkildə əvəzlənməni həyata keçirməyə imkan verir.

Hal-hazırda, mesaj brokerinə hadisələr göndərməyə başlamaq üçün sadəcə kiçik bir kitabxananı xidmət kodunuza qoşmalısınız. Hamısı budur. Bir sətir kodla yazmaq, oxumaq və miqyasını dəyişmək bacarığınız var. Bütün icra sizdən gizlədilir, yalnız bir neçə toplu ölçülü tutacaqlar kənarda qalır. Başlıq altında data-avtobus xidməti Kubernetes-də lazımi sayda istehsalçı və istehlakçı nümunələrini artırır və onları lazımi konfiqurasiya ilə təmin edir, lakin bütün bunlar xidmətiniz üçün şəffafdır.

Əlbəttə ki, gümüş güllə yoxdur və bu yanaşmanın öz məhdudiyyətləri var.

  • Data-bus üçüncü tərəf kitabxanalarından fərqli olaraq, evdə dəstəklənməlidir.
  • Data-bus xidmətlər və mesaj brokeri arasında qarşılıqlı əlaqənin sayını artırır, bu da çılpaq Kafka ilə müqayisədə daha aşağı performansla nəticələnir.
  • Hər şeyi xidmətlərdən belə asanlıqla gizlətmək olmur; biz KSQL və ya Kafka Streams-in funksionallığını data-busda təkrarlamaq istəmirik, ona görə də bəzən xidmətlərin birbaşa getməsinə icazə verməliyik.

Bizim vəziyyətimizdə müsbət tərəflər mənfi cəhətləri üstələyirdi və mesaj brokerini ayrıca bir xidmətlə əhatə etmək qərarı əsaslandırıldı. Fəaliyyət göstərdiyimiz il ərzində heç bir ciddi qəza və problemimiz olmayıb.

PS Bu məqalə üçün gözəl şəkillərə görə sevgilim Ekaterina Obalyaevaya təşəkkür edirəm. Əgər onları bəyəndinizsə, burada qarşıda daha çox illüstrasiyalar var.

Mənbə: www.habr.com

DDoS mühafizəsi, VPS VDS serverləri olan saytlar üçün etibarlı hostinq alın 🔥 DDoS qorunması, VPS VDS serverləri ilə etibarlı veb sayt hostinqi alın | ProHoster