{"id":30778,"date":"2019-10-31T21:37:23","date_gmt":"2019-10-31T18:37:23","guid":{"rendered":"https:\/\/prohoster.info\/blog\/opyt-razrabotki-servisa-refund-tool-s-asinhronnym-api-na-kafka\/"},"modified":"2019-10-31T21:37:23","modified_gmt":"2019-10-31T18:37:23","slug":"opyt-razrabotki-servisa-refund-tool-s-asinhronnym-api-na-kafka","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/opyt-razrabotki-servisa-refund-tool-s-asinhronnym-api-na-kafka","title":{"rendered":"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>\u00c7far\u00eb mund ta b\u00ebj\u00eb nj\u00eb kompani kaq t\u00eb madhe si Lamoda, e cila ka nj\u00eb proces t\u00eb organizuar dhe dhjet\u00ebra sh\u00ebrbime t\u00eb nd\u00ebrlidhura, t\u00eb ndryshoj\u00eb ndjesh\u00ebm qasjen e saj? Motivimi mund t\u00eb jet\u00eb krejt ndryshe: nga legjislative deri te d\u00ebshira p\u00ebr t\u00eb eksperimentuar q\u00eb kan\u00eb t\u00eb gjith\u00eb programuesit.<\/p>\n<p>Por kjo nuk do t\u00eb thot\u00eb se nuk mund t\u00eb pritet nj\u00eb p\u00ebrfitim shtes\u00eb. \u00c7far\u00eb konkretisht mund t\u00eb fitohet n\u00ebse implementohet nj\u00eb API i bazuar n\u00eb ngjarje n\u00eb Kafka, do t\u00eb tregoj\u00eb Sergey Zaika (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/users\/fewald\/\" class=\"user_link\">fewald<\/a><\/noindex>). Rreth gafeve dhe zbulimeve interesante gjithashtu do t\u00eb ket\u00eb patjet\u00ebr - nuk mund t\u00eb ket\u00eb eksperiment pa to.<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/7ab959ab45ec5c6565b35b18b361c0ea.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<em>Disclaimer: Ky artikull bazohet n\u00eb materialet e mitapit q\u00eb Sergey mbajti n\u00eb n\u00ebntor 2018 n\u00eb HighLoad++. Eksperienca p\u00ebr Lamoda me Kafka t\u00ebrhoqi d\u00ebgjuesit jo m\u00eb pak se prezantimet e tjera nga programi. Na duket se kjo \u00ebsht\u00eb nj\u00eb shembull i shk\u00eblqyer se gjithmon\u00eb mund dhe duhet t\u00eb gjejm\u00eb mendimtar\u00eb t\u00eb ngjash\u00ebm, dhe organizator\u00ebt e HighLoad++ do t\u00eb vazhdojn\u00eb t\u00eb krijojn\u00eb nj\u00eb atmosfer\u00eb q\u00eb inkurajon k\u00ebt\u00eb.<\/em><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Rreth procesit<\/h2>\n<p>\nLamoda \u2014 \u00ebsht\u00eb nj\u00eb platform\u00eb e madhe e-commerce, e cila ka qendr\u00ebn e saj t\u00eb kontakteve, sh\u00ebrbimin e dor\u00ebzimit (dhe shum\u00eb partner\u00eb), studio fotografike, nj\u00eb magazin\u00eb t\u00eb madhe dhe gjith\u00e7ka funksionon me softin e saj. Ka dhjet\u00ebra m\u00ebnyra pagesash, partner\u00eb B2B q\u00eb mund t\u00eb p\u00ebrdorin disa ose t\u00eb gjitha k\u00ebto sh\u00ebrbime dhe duan t\u00eb din\u00eb informacionin m\u00eb t\u00eb fundit p\u00ebr produktet e tyre. P\u00ebr m\u00eb tep\u00ebr, Lamoda operon n\u00eb tri vende p\u00ebrve\u00e7 RF dhe atje gjith\u00e7ka \u00ebsht\u00eb pak ndryshe. Pra, ndoshta ekzistojn\u00eb m\u00eb shum\u00eb se nj\u00ebqind m\u00ebnyra p\u00ebr t\u00eb konfiguruar nj\u00eb porosi t\u00eb re, e cila duhet t\u00eb p\u00ebrpunoj\u00eb ndryshe. E gjith\u00eb kjo funksionon me ndihm\u00ebn e dhjet\u00ebra sh\u00ebrbimeve, t\u00eb cilat ndonj\u00ebher\u00eb komunikojn\u00eb n\u00eb m\u00ebnyra jo t\u00eb qarta. Ka edhe nj\u00eb sistem qendror, p\u00ebrgjegj\u00ebsia kryesore e s\u00eb cil\u00ebs jan\u00eb statuset e porosive. Ne e quajm\u00eb at\u00eb BOB, un\u00eb punoj me t\u00eb.<\/p>\n<h2>Refund Tool me API t\u00eb ngacmuar nga ngjarjet <\/h2>\n<p>\nFjala ngacmuar nga ngjarjet \u00ebsht\u00eb mjaft e p\u00ebrdorur, m\u00eb tutje do t\u00eb p\u00ebrcaktojm\u00eb n\u00eb detaje se \u00e7far\u00eb n\u00ebnkupton kjo. Do ta filloj me kontekstin n\u00eb t\u00eb cilin vendos\u00ebm t\u00eb provojm\u00eb qasjen API t\u00eb ngacmuar nga ngjarjet n\u00eb Kafka. <\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/3bfdce47dd8420fc63d84645e76de647.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nN\u00eb \u00e7do dyqan, p\u00ebrve\u00e7 porosive p\u00ebr t\u00eb cilat klient\u00ebt paguajn\u00eb, ka raste kur dyqani k\u00ebrkohet t\u00eb kthej\u00eb para, sepse produkti nuk i p\u00ebrshtatet klientit. Ky \u00ebsht\u00eb nj\u00eb proces relativisht i shkurt\u00ebr: sqarojm\u00eb informacionin, n\u00ebse \u00ebsht\u00eb e nevojshme, dhe transferojm\u00eb parat\u00eb. <\/p>\n<p>Por, kthimi u komplikuar p\u00ebr shkak t\u00eb ndryshimit t\u00eb legjislacionit, dhe na u desh t\u00eb realizonim nj\u00eb mikrosh\u00ebrbim t\u00eb ve\u00e7ant\u00eb p\u00ebr k\u00ebt\u00eb.<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/0e358df5476e7448976e0f1147a103fb.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMotivimi yn\u00eb:<\/p>\n<ol>\n<li><strong>Ligji FZ-54<\/strong>\u00a0\u2014 n\u00eb shkurt, ligji k\u00ebrkon q\u00eb t\u00eb raportohet n\u00eb tatim mbi \u00e7do operacion financiar, qoft\u00eb kthim, qoft\u00eb pranimi, n\u00eb nj\u00eb SLA mjaft t\u00eb shkurt\u00ebr prej disa minutash. Ne, si e-commerce, realizojm\u00eb shum\u00eb operacione. Kjo teknike do t\u00eb thot\u00eb nj\u00eb p\u00ebrgjegj\u00ebsi t\u00eb re (dhe pra nj\u00eb sh\u00ebrbim t\u00eb ri) dhe p\u00ebrmir\u00ebsime n\u00eb t\u00eb gjitha sistemet e p\u00ebrfshira.<\/li>\n<li><strong>BOB split<\/strong>\u00a0\u2014 nj\u00eb projekt i brendsh\u00ebm i kompanis\u00eb p\u00ebr t\u00eb eliminuar nj\u00eb num\u00ebr t\u00eb madh p\u00ebrgjegj\u00ebsish t\u00eb pa profilizuara nga BOB dhe p\u00ebr t\u00eb reduktuar kompleksitetin e tij t\u00eb p\u00ebrgjithsh\u00ebm.<\/li>\n<\/ol>\n<p>\n<img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/d3ecf9961bdb372fc5f84ee9389f73ef.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nN\u00eb k\u00ebt\u00eb skem\u00eb jan\u00eb skicuar sistemet kryesore t\u00eb Lamoda. Tani p\u00ebr tani, shumica e tyre p\u00ebrb\u00ebjn\u00eb m\u00eb tep\u00ebr <strong>nj\u00eb grup prej 5-10 mikrosh\u00ebrbimesh rreth nj\u00eb monoliti n\u00eb zvog\u00eblim.<\/strong>. Ato po ngjashen, por p\u00ebrpiqemi t'i b\u00ebjm\u00eb ato m\u00eb t\u00eb vogla, sepse \u00ebsht\u00eb e frikshme t\u00eb krijosh nj\u00eb pjes\u00eb t\u00eb dedikuar n\u00eb mes \u2014 nuk mund t\u00eb lejojm\u00eb q\u00eb ajo t\u00eb bie. T\u00eb gjitha shk\u00ebmbimet (shigjetat) jemi t\u00eb detyruar t'i rezervojm\u00eb dhe t\u00eb llogarisim se \u00e7far\u00ebdo prej tyre mund t\u00eb jet\u00eb e paperceptueshme.<\/p>\n<p>N\u00eb BOB ka gjithashtu mjaft shk\u00ebmbime: sisteme pagesash, dor\u00ebzimesh, njoftimesh, etj. <\/p>\n<p>Teknikisht, BOB \u00ebsht\u00eb:<\/p>\n<ul>\n<li>~150k rreshta kode + ~100k rreshta teste;<\/li>\n<li>php7.2 + Zend 1 &amp; Symfony Components 3;<\/li>\n<li>&gt;100 API &amp; ~50 integrime t\u00eb dala;<\/li>\n<li>4 vende me logjik\u00ebn e tyre biznesore. <\/li>\n<\/ul>\n<p>\nDeployimi i BOB-s\u00eb \u00ebsht\u00eb i kushtuesh\u00ebm dhe i dhimbsh\u00ebm, numri i kodeve dhe detyrave q\u00eb ai zgjidh \u00ebsht\u00eb i till\u00eb sa askush nuk mund ta mbahet at\u00eb n\u00eb mend t\u00ebr\u00eb.<\/p>\n<h2>Procesi i kthimit<\/h2>\n<p>\nFillimisht, n\u00eb proces p\u00ebrfshihen dy sisteme: BOB dhe Pagesa. Tani shfaqen edhe dy t\u00eb tjera:<\/p>\n<ul>\n<li>Sh\u00ebrbimi i Fiskalizimit, i cili do t\u00eb marr\u00eb p\u00ebrsip\u00ebr problemet me fiskalizimin dhe komunikimin me sh\u00ebrbime t\u00eb jashtme.<\/li>\n<li>Mjeti i Kthimit, n\u00eb t\u00eb cilin thjesht p\u00ebrfshihen shk\u00ebmbimet e reja, p\u00ebr t\u00eb mos e fryr\u00eb BOB.<\/li>\n<\/ul>\n<p>\nTani procesi duket k\u00ebshtu:<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/13c02975881ad35c61304053c604cda3.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ol>\n<li>BOB merr nj\u00eb k\u00ebrkes\u00eb p\u00ebr kthimin e parave.<\/li>\n<li>BOB e njofton k\u00ebt\u00eb Mjetin e Kthimit.<\/li>\n<li>Mjeti i Kthimit i thot\u00eb Pages\u00ebs: \u00abKthe parat\u00eb\u00bb.<\/li>\n<li>Pagesa kthen parat\u00eb.<\/li>\n<li>Refund Tool dhe BOB sinkronizojn\u00eb statuset e tyre, sepse aktualisht jan\u00eb t\u00eb dy t\u00eb nevojsh\u00ebm. Nuk jemi ende t\u00eb gatsh\u00ebm t\u00eb kalojm\u00eb plot\u00ebsisht n\u00eb Refund Tool, pasi n\u00eb BOB ka UI, raporte p\u00ebr kontabilitetin, dhe gjithashtu shum\u00eb t\u00eb dh\u00ebna q\u00eb nuk jan\u00eb kaq leht\u00eb p\u00ebr t'u transferuar. Na duhet t\u00eb q\u00ebndrojm\u00eb n\u00eb dy karrige.<\/li>\n<li>Po d\u00ebrgohet k\u00ebrkesa p\u00ebr fiskalizim.<\/li>\n<\/ol>\n<p>\nSi rezultat, b\u00ebm\u00eb nj\u00eb bus ngjarjesh n\u00eb Kafka \u2014 event-bus, n\u00eb t\u00eb cilin gjith\u00e7ka u lidh. Hurrah, tani kemi nj\u00eb pik\u00eb t\u00eb vetme d\u00ebshtimi (sarcastik).<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/674edd7972998b4985071f5250612c7e.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPikat e forta dhe t\u00eb dob\u00ebta jan\u00eb mjaft t\u00eb qarta. Krijuam nj\u00eb bus, q\u00eb do t\u00eb thot\u00eb se tani t\u00eb gjith\u00eb sh\u00ebrbimet varen nga ajo. Kjo e thjeshton projektimin, por sjell nj\u00eb pik\u00eb t\u00eb vetme d\u00ebshtimi n\u00eb sistem. N\u00ebse Kafka bie, procesi do t\u00eb ndaloj\u00eb.<\/p>\n<h2>\u00c7far\u00eb \u00ebsht\u00eb API me ngjarje? <\/h2>\n<p>\nNj\u00eb p\u00ebrgjigje e mir\u00eb p\u00ebr k\u00ebt\u00eb pyetje \u00ebsht\u00eb n\u00eb raportin e Martin Fowler (GOTO 2017) <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/STKCRSUsyPO\">\"The Many Meanings of Event-Driven Architecture\"<\/a><\/noindex>. <\/p>\n<p>P\u00ebrmbledhje e asaj q\u00eb b\u00ebm\u00eb:<\/p>\n<ol>\n<li>Ambalazhuam t\u00eb gjith\u00eb shk\u00ebmbimet asinkrone p\u00ebrmes <strong>storage t\u00eb ngjarjeve<\/strong>. N\u00eb vend q\u00eb t\u00eb njoftojm\u00eb n\u00eb rrjet \u00e7do konsumator t\u00eb interesuar p\u00ebr ndryshimin e statusit, ne shkruajm\u00eb n\u00eb nj\u00eb depo t\u00eb centralizuar nj\u00eb ngjarje p\u00ebr ndryshimin e gjendjes, dhe konsumator\u00ebt e interesuar n\u00eb tem\u00eb e lexojn\u00eb prej aty gjith\u00e7ka q\u00eb shfaqet.<\/li>\n<li>Nj\u00eb ngjarje (event) n\u00eb k\u00ebt\u00eb rast \u00ebsht\u00eb nj\u00eb njoftim (<strong>njoftimet<\/strong>) q\u00eb di\u00e7ka ka ndryshuar diku. P\u00ebr shembull, ka ndryshuar statusi i porosis\u00eb. Konsumatori, t\u00eb cilit i interesojn\u00eb disa t\u00eb dh\u00ebna shoq\u00ebruese t\u00eb informacionit t\u00eb statusit dhe q\u00eb nuk jan\u00eb n\u00eb njoftim, mund t\u00eb m\u00ebsoj\u00eb vet\u00eb gjendjen e tyre.<\/li>\n<li>Alternativa maksimale \u00ebsht\u00eb nj\u00eb sourcing ngjarjesh t\u00eb plot\u00eb, <strong>transferimi i gjendjes<\/strong>, ku ngjarja p\u00ebrmban t\u00eb gjith\u00eb informacionin e nevojsh\u00ebm p\u00ebr p\u00ebrpunim: nga e ku e kaloi statusin dhe si ndryshuan t\u00eb dh\u00ebnat etj. \u00c7\u00ebshtja \u00ebsht\u00eb vet\u00ebm n\u00eb racionalitetin dhe sasin\u00eb e informacionit q\u00eb mund t\u00eb lejoni t\u00eb ruhet.<\/li>\n<\/ol>\n<p>\nN\u00eb kuad\u00ebr t\u00eb lan\u00e7imit t\u00eb Refund Tool kemi p\u00ebrdorur variantin e tret\u00eb. Kjo e ka thjeshtuar p\u00ebrpunimin e ngjarjeve, pasi nuk ka nevoj\u00eb p\u00ebr t\u00eb nxjerr\u00eb informacion t\u00eb detajuar, p\u00ebr m\u00eb tep\u00ebr, p\u00ebrjashton skenarin ku \u00e7do ngjarje e re shkakton nj\u00eb shp\u00ebrthim t\u00eb k\u00ebrkesave p\u00ebr sqarime nga konsumator\u00ebt.<\/p>\n<p>Sh\u00ebrbimi Refund Tool <strong>nuk \u00ebsht\u00eb i ngarkuar<\/strong>, k\u00ebshtu q\u00eb Kafka atje \u00ebsht\u00eb m\u00eb shum\u00eb nj\u00eb prov\u00eb se nj\u00eb nevoj\u00eb. Nuk mendoj se, n\u00ebse sh\u00ebrbimi i rikthimit t\u00eb fondeve do t\u00eb b\u00ebhej nj\u00eb projekt me ngarkes\u00eb t\u00eb lart\u00eb, biznesi do t\u00eb ishte i lumtur.<\/p>\n<h4>Shk\u00ebmbimi asinkron AS IS<\/h4>\n<p>\nP\u00ebr shk\u00ebmbimet asinkrone, departamenti i PHP zakonisht p\u00ebrdor RabbitMQ. Kemi mbledhur t\u00eb dh\u00ebnat p\u00ebr k\u00ebrkes\u00ebn, i vendos\u00ebm n\u00eb radh\u00eb, dhe konsumatori i k\u00ebtij sh\u00ebrbimi e lexoi dhe e d\u00ebrgoi (ose nuk e d\u00ebrgoi). P\u00ebr API-n\u00eb e saj, Lamoda e p\u00ebrdor aktivisht Swagger. Projektojm\u00eb API-n\u00eb, e p\u00ebrshkruajm\u00eb at\u00eb n\u00eb Swagger, gjenerojm\u00eb kodin p\u00ebr klient\u00ebt dhe server\u00ebt. Ne gjithashtu p\u00ebrdorim nj\u00eb JSON RPC 2.0 t\u00eb zgjeruar. <\/p>\n<p>Disa vende p\u00ebrdorin bus-esb, dikush jeton me activeMQ, por, n\u00eb p\u00ebrgjith\u00ebsi, <strong>RabbitMQ \u00ebsht\u00eb standardi<\/strong>.<\/p>\n<h4>Shk\u00ebmbim asinkron DO T\u00cb JET\u00cb<\/h4>\n<p>\nKur projektojm\u00eb shk\u00ebmbimin p\u00ebrmes events-bus, ka nj\u00eb analogji. Ne p\u00ebrshkruajm\u00eb n\u00eb m\u00ebnyr\u00eb t\u00eb ngjashme shk\u00ebmbimin e t\u00eb dh\u00ebnave t\u00eb ardhsh\u00ebm p\u00ebrmes p\u00ebrshkrimeve t\u00eb struktur\u00ebs s\u00eb event-it. Formati \u00ebsht\u00eb yaml, dhe na duhej t\u00eb b\u00ebnim vet\u00eb gjenerimin e kodit, gjeneratori sipas specifikimit krijon DTO dhe i m\u00ebson klient\u00ebt dhe server\u00ebt t\u00eb punojn\u00eb me ta. Gjenerimi shkon n\u00eb dy gjuh\u00eb - <strong>golang dhe php<\/strong>. Kjo lejon q\u00eb bibliotekat t\u00eb mbahen t\u00eb sinkronizuara. Gjeneratori \u00ebsht\u00eb shkruar n\u00eb golang, p\u00ebr t\u00eb cilin mori emrin gogi.<\/p>\n<p>Event-sourcing n\u00eb Kafka \u00ebsht\u00eb nj\u00eb gj\u00eb tipike. Ekziston nj\u00eb zgjidhje nga versioni kryesor i Kafka Confluent, ka <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/nakadi\">nakadi<\/a><\/noindex>, nj\u00eb zgjidhje nga 'v\u00ebllez\u00ebrit' tan\u00eb n\u00eb fush\u00ebn e domenit Zalando. Moti <strong>motivi yn\u00eb p\u00ebr t\u00eb filluar me vanilla Kafka<\/strong>\u00a0\u2014 \u00ebsht\u00eb ta mbani zgjidhjen falas, derisa t\u00eb vendosim n\u00ebse do ta p\u00ebrdorim at\u00eb gjithandej, si dhe t\u00eb mbajm\u00eb hap\u00ebsir\u00eb p\u00ebr manovra dhe p\u00ebrmir\u00ebsime: ne d\u00ebshirojm\u00eb mb\u00ebshtetje p\u00ebr t\u00eb. <strong>JSON RPC 2.0<\/strong>, gjenerator\u00eb p\u00ebr dy gjuh\u00eb dhe do t\u00eb shohim se \u00e7far\u00eb tjet\u00ebr. <\/p>\n<p>Ironike \u00ebsht\u00eb q\u00eb, edhe n\u00eb nj\u00eb rast kaq t\u00eb lumtur, kur ka nj\u00eb biznes t\u00eb ngjash\u00ebm ndaj Zalando, i cili b\u00ebri nj\u00eb zgjidhje mjaft t\u00eb ngjashme, nuk mund ta p\u00ebrdorim at\u00eb n\u00eb m\u00ebnyr\u00eb efektive. <\/p>\n<p>Arkitektonikisht, n\u00eb lan\u00e7im pattern-i \u00ebsht\u00eb i till\u00eb: lexojm\u00eb drejtp\u00ebrdrejt nga Kafka, por shkruajm\u00eb vet\u00ebm p\u00ebrmes events-bus. P\u00ebr t\u00eb lexuar n\u00eb Kafka ka shum\u00eb t\u00eb gatshme: broker\u00eb, balancer\u00eb dhe \u00ebsht\u00eb m\u00eb shum\u00eb-m\u00eb pak e gatshme p\u00ebr t\u00eb skalator horizontalisht, kjo donim ta mbaja. Nd\u00ebrsa p\u00ebr shkrimin, ne do t\u00eb donim ta paketojm\u00eb p\u00ebrmes nj\u00eb Gateway aka Events-bus, dhe ja p\u00ebrse.<\/p>\n<h3>Events-bus<\/h3>\n<p>\nOse autobusi i ngjarjeve. \u00cbsht\u00eb thjesht nj\u00eb gateway http pa shtet, i cili merr mbi vete disa role t\u00eb r\u00ebnd\u00ebsishme:<\/p>\n<ul>\n<li><strong>Validimi i prodhimit<\/strong>\u00a0\u2014 kontrollojm\u00eb q\u00eb ngjarjet p\u00ebrputhen me specifikimin ton\u00eb.<\/li>\n<li><strong>Sistemi kryesor p\u00ebr ngjarjet<\/strong>, q\u00eb do t\u00eb thot\u00eb kjo \u00ebsht\u00eb sistemi kryesor dhe i vet\u00ebm n\u00eb kompani, i cili p\u00ebrgjigjet n\u00eb pyetjen se cilat ngjarje me cilat struktura konsiderohen si t\u00eb vlefshme. Validimi p\u00ebrfshin vet\u00ebm llojet e t\u00eb dh\u00ebnave dhe enums p\u00ebr specifikimin e rrept\u00eb t\u00eb p\u00ebrmbajtjes. <\/li>\n<li><strong>Funksioni Hash<\/strong> p\u00ebr sharding - struktura e mesazhit Kafka \u00ebsht\u00eb key-value dhe k\u00ebtu sipas hashes nga key, llogaritet se ku duhet ta vendosim k\u00ebt\u00eb.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Pse<\/h3>\n<p>\nNe punojm\u00eb n\u00eb nj\u00eb kompani t\u00eb madhe me nj\u00eb proces t\u00eb organizuar. Pse t\u00eb ndryshojm\u00eb di\u00e7ka? <strong>Ky \u00ebsht\u00eb nj\u00eb eksperiment<\/strong>, dhe ne presim t\u00eb fitojm\u00eb disa avantazhe.<\/p>\n<h4>1:n+1 shk\u00ebmbime (nj\u00eb me shum\u00eb)<\/h4>\n<p>\nMe Kafka \u00ebsht\u00eb shum\u00eb e leht\u00eb t\u00eb lidheni me API-t\u00eb e konsumator\u00ebve t\u00eb rinj. <\/p>\n<p>Supozoni se keni nj\u00eb regjist\u00ebr q\u00eb duhet t\u00eb mbahet i azhurnuar n\u00eb disa sisteme nj\u00ebher\u00ebsh (dhe n\u00eb disa t\u00eb reja). M\u00eb par\u00eb ne shpiknim nj\u00eb bundle q\u00eb realizonte set-API, dhe sistemit master i raportonim adresat e konsumator\u00ebve. Tani sistemi master d\u00ebrgon azhurnime n\u00eb nj\u00eb topic, dhe t\u00eb gjith\u00eb ata q\u00eb jan\u00eb t\u00eb interesuar lexojn\u00eb. Pati nj\u00eb sistem t\u00eb ri - e regjistruam at\u00eb n\u00eb topic. Po, gjithashtu bundle, por m\u00eb e thjesht\u00eb.<\/p>\n<p>N\u00eb rastin e refund-tool, q\u00eb \u00ebsht\u00eb nj\u00eb cop\u00ebz BOB, na p\u00ebrshtatet t\u00eb mbajm\u00eb ato t\u00eb sinkronizuara p\u00ebrmes Kafka. Pagesa thot\u00eb se parat\u00eb jan\u00eb rikthyer: BOB, RT jan\u00eb njoftuar, kan\u00eb ndryshuar statuset e tyre, Sh\u00ebrbimi i Fik\u00ebs ka marr\u00eb lajmin dhe ka l\u00ebshuar fatur\u00ebn.<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/b01b22a333b58e87aeef0c52d40e6960.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKemi plane p\u00ebr t\u00eb krijuar nj\u00eb Sh\u00ebrbim Njoftimesh t\u00eb nj\u00ebjt\u00eb, q\u00eb do t\u00eb informonte klientin p\u00ebr lajmet n\u00eb lidhje me porosin\u00eb e tij\/rikthimet. Tani, kjo p\u00ebrgjegj\u00ebsi \u00ebsht\u00eb e shp\u00ebrndar\u00eb mes sistemeve. Na mjafton t\u00eb m\u00ebsojm\u00eb Sh\u00ebrbimin e Njoftimeve t\u00eb kap\u00eb informacione relevante nga Kafka dhe t\u00eb reagoj\u00eb ndaj tyre (dhe t\u00eb fikim k\u00ebto njoftime n\u00eb sistemet e tjera). Nuk do t\u00eb nevojiten nd\u00ebrrime t\u00eb reja t\u00eb drejtp\u00ebrdrejta.<\/p>\n<h4>T\u00eb dh\u00ebnat e drejtuara nga t\u00eb dh\u00ebnat<\/h4>\n<p>\nInformacioni mes sistemeve b\u00ebhet i qart\u00eb \u2014 \u00e7far\u00ebdo \u00abenterprise-i t\u00eb dhimbsh\u00ebm\u00bb q\u00eb keni dhe sa i m\u00ebdha t\u00eb jet\u00eb backlog-u juaj. N\u00eb Lamoda, ekziston nj\u00eb departament i Analitik\u00ebs s\u00eb t\u00eb Dh\u00ebnave, q\u00eb mbledh t\u00eb dh\u00ebna nga sistemet dhe i sjell ato n\u00eb nj\u00eb form\u00eb t\u00eb rip\u00ebrdorshme, si p\u00ebr biznesin ashtu edhe p\u00ebr sistemet inteligjente. Kafka lejon t\u00eb jepni shpejt shum\u00eb t\u00eb dh\u00ebna dhe t\u00eb mbani k\u00ebt\u00eb shp\u00ebrndarje informacioni t\u00eb azhurnuar.<\/p>\n<h4>Dita e replikimit<\/h4>\n<p>\nMesazhet nuk shp\u00ebrb\u00ebhen pas leximit, si n\u00eb RabbitMQ. Kur ngjarja p\u00ebrmban mjaft informacion p\u00ebr p\u00ebrpunim, ne kemi nj\u00eb histori t\u00eb ndryshimeve t\u00eb fundit p\u00ebr objektin dhe, n\u00ebse d\u00ebshirohet, mund\u00ebsin\u00eb p\u00ebr t'i aplikuar k\u00ebto ndryshime.<\/p>\n<p>Koha e ruajtjes s\u00eb replikimit varet nga intensiteti i shkrimit n\u00eb k\u00ebt\u00eb tem\u00eb; Kafka lejon t\u00eb p\u00ebrshtaten fleksib\u00ebl kufijt\u00eb mbi koh\u00ebn e ruajtjes dhe mbi volumin e t\u00eb dh\u00ebnave. P\u00ebr temat me intensitet t\u00eb lart\u00eb, \u00ebsht\u00eb e r\u00ebnd\u00ebsishme q\u00eb t\u00eb gjith\u00eb konsumator\u00ebt t\u00eb arrijn\u00eb t\u00eb lexojn\u00eb informacionin p\u00ebrpara se ai t\u00eb zhduket, madje edhe n\u00eb rast t\u00eb nj\u00eb mosfunksionimi t\u00eb p\u00ebrkohsh\u00ebm. Zakonisht, \u00ebsht\u00eb e mundur t\u00eb ruhet informacioni p\u00ebr\u00a0<strong>nj\u00ebsi dit\u00ebsh<\/strong>, q\u00eb \u00ebsht\u00eb mjaft e mjaftueshme p\u00ebr mb\u00ebshtetje. <\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/0e08dd384155289123ebee96430c2370.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nM\u00eb pas, pak p\u00ebrmbledhje e dokumentacionit p\u00ebr ata q\u00eb nuk jan\u00eb t\u00eb njohur me Kafka (imazhi gjithashtu nga dokumentacioni)<\/p>\n<p>N\u00eb AMQP ka radh\u00eb: shkruajm\u00eb mesazhe n\u00eb radh\u00eb p\u00ebr konsumatorin. Zakonisht, nj\u00eb radh\u00eb p\u00ebrpunon nj\u00eb sistem me nj\u00eb logjik\u00eb biznesi t\u00eb nj\u00ebjt\u00eb. N\u00ebse duam t\u00eb njoftojm\u00eb disa sisteme, mund ta m\u00ebsojm\u00eb aplikacionin t\u00eb shkruaj\u00eb n\u00eb disa radh\u00eb ose t\u00eb konfiguroni exchange me mekanizmin fanout, i cili vet\u00eb i klonon ato.<\/p>\n<p>N\u00eb Kafka ka nj\u00eb abstraksion t\u00eb ngjash\u00ebm <em>tem\u00eb<\/em>, n\u00eb t\u00eb cilin shkruani mesazhe, por ato nuk zhduken pas leximit. N\u00eb m\u00ebnyr\u00eb t\u00eb paracaktuar, kur lidheni me Kafka, merrni t\u00eb gjitha mesazhet dhe keni mund\u00ebsin\u00eb ta ruani vendin ku keni ndaluar. Dometh\u00ebn\u00eb, i lexoni ato n\u00eb m\u00ebnyr\u00eb t\u00eb nj\u00ebpasnj\u00ebshme, nuk \u00ebsht\u00eb e nevojshme t\u00eb sh\u00ebnohet mesazhi si t\u00eb lexuar, por mund ta ruani id, nga e cila do t\u00eb vazhdoni m\u00eb pas me leximin. Id, n\u00eb t\u00eb cil\u00ebn keni ndaluar, quhet offset, nd\u00ebrsa mekanizmi quhet commit offset. <\/p>\n<p>P\u00ebr pasoj\u00eb, mund t\u00eb realizojm\u00eb logjik\u00eb t\u00eb ndryshme. P\u00ebr shembull, kemi BOB-in q\u00eb ekziston n\u00eb 4 instanca p\u00ebr vende t\u00eb ndryshme - Lamoda \u00ebsht\u00eb n\u00eb Rusi, Kazakistan, Ukrain\u00eb dhe Bjellorusi. Pasi q\u00eb ato deplohen ve\u00e7mas, kan\u00eb pak interpretime t\u00eb ndryshme dhe logjik\u00ebn e tyre t\u00eb biznesit. Ne tregojm\u00eb n\u00eb mesazh se p\u00ebr cilin vend \u00ebsht\u00eb. \u00c7do konsumator BOB n\u00eb \u00e7do vend lexon me grupe t\u00eb ndryshme ID dhe, n\u00ebse mesazhi nuk i p\u00ebrket atij, e kalon, dmth. menj\u00ebher\u00eb komiton offset +1. N\u00ebse po, tema q\u00eb lexon Sh\u00ebrbimi yn\u00eb i Pagesave, at\u00ebher\u00eb ai e b\u00ebn k\u00ebt\u00eb me nj\u00eb grup t\u00eb ve\u00e7ant\u00eb, dhe p\u00ebr k\u00ebt\u00eb arsye offset-et nuk preken.<\/p>\n<p><b>K\u00ebrkesat p\u00ebr ngjarjet:<\/b><\/p>\n<ul>\n<li><strong>Plot\u00ebsia e t\u00eb dh\u00ebnave. <\/strong>Do t\u00eb doja q\u00eb ngjarja t\u00eb kishte t\u00eb dh\u00ebna t\u00eb mjaftueshme p\u00ebr t'u p\u00ebrpunuar. <\/li>\n<\/ul>\n<p><\/p>\n<ul>\n<li><strong>Integriteti. <\/strong>Ne delegojm\u00eb Events-bus kontrollin e faktit q\u00eb ngjarja \u00ebsht\u00eb konsistente dhe se ai mund ta p\u00ebrpunoj\u00eb at\u00eb.<\/li>\n<li><strong>Renditja \u00ebsht\u00eb e r\u00ebnd\u00ebsishme. <\/strong>N\u00eb rastin e rikthimit, ne detyrohemi t\u00eb punojm\u00eb me historin\u00eb. Me njoftimet rendi nuk \u00ebsht\u00eb i r\u00ebnd\u00ebsish\u00ebm, n\u00ebse jan\u00eb njoftime homogjene, emaili do t\u00eb jet\u00eb i nj\u00ebjt\u00eb pavar\u00ebsisht nga porosia q\u00eb ka mb\u00ebrritur e para. N\u00eb rast rikthimi ka nj\u00eb proces t\u00eb qart\u00eb; n\u00ebse ndryshojm\u00eb rendin, do t\u00eb ndodhin p\u00ebrjashtime, rikthimi nuk do t\u00eb krijohet ose nuk do t\u00eb p\u00ebrpunohet - do t\u00eb p\u00ebrfundojm\u00eb n\u00eb nj\u00eb status tjet\u00ebr.<\/li>\n<li><strong>Konsistenca. <\/strong>Ne kemi nj\u00eb depo, dhe tani ne krijojm\u00eb ngjarjet n\u00eb vend t\u00eb API-s\u00eb. Na nevojitet nj\u00eb m\u00ebnyr\u00eb p\u00ebr t\u00eb kaluar shpejt dhe lir\u00eb informacionin p\u00ebr ngjarje t\u00eb reja dhe p\u00ebr ndryshime n\u00eb ato ekzistuese n\u00eb sh\u00ebrbimet tona. Kjo arrihet p\u00ebrmes nj\u00eb specifikimi t\u00eb p\u00ebrbashk\u00ebt n\u00eb nj\u00eb depo t\u00eb ve\u00e7ant\u00eb git dhe gjenerator\u00ebve t\u00eb kodit. Prandaj, klient\u00ebt dhe server\u00ebt n\u00eb sh\u00ebrbime t\u00eb ndryshme jan\u00eb t\u00eb harmonizuara.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Kafka n\u00eb Lamoda<\/h2>\n<p>\nNe kemi tre instalime t\u00eb Kafka: <\/p>\n<ol>\n<li>Logs;<\/li>\n<li>R&amp;D;<\/li>\n<li>Events-bus.<\/li>\n<\/ol>\n<p>\nSot kemi p\u00ebr t\u00eb folur vet\u00ebm p\u00ebr pik\u00ebn e fundit. N\u00eb events-bus ne nuk kemi instalime shum\u00eb t\u00eb m\u00ebdha \u2014 3 broker\u00eb (servera) dhe vet\u00ebm 27 tema. N\u00eb p\u00ebrgjith\u00ebsi, nj\u00eb tem\u00eb \u00ebsht\u00eb nj\u00eb proces. Por ky \u00ebsht\u00eb nj\u00eb detaj delikat, dhe tani do ta prekem\u00eb at\u00eb.<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/f398852689b31429cc97b4cbffcabab5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nM\u00eb lart \u00ebsht\u00eb grafiku rps. Procesi i kthimeve sh\u00ebnohet me nj\u00eb vij\u00eb t\u00eb ngjyr\u00ebs s\u00eb turkizit (po, ajo q\u00eb ndodhet n\u00eb boshtin X), nd\u00ebrsa me ngjyr\u00eb roz\u00eb \u2014 procesi i azhurnimit t\u00eb p\u00ebrmbajtjes. <\/p>\n<p>Katalogu Lamoda p\u00ebrmban miliona produkte, dhe t\u00eb dh\u00ebnat p\u00ebrdit\u00ebsohen vazhdimisht. Disa koleksione dalin jasht\u00eb mode, nd\u00ebrsa t\u00eb reja l\u00ebshohen n\u00eb vend t\u00eb tyre, dhe n\u00eb katalog vazhdimisht shfaqen modele t\u00eb reja. Ne p\u00ebrpiqemi t\u00eb parashikojm\u00eb se \u00e7far\u00eb do t'i interesoj\u00eb klient\u00ebve tan\u00eb nes\u00ebr, prandaj vazhdimisht blejm\u00eb artikuj t\u00eb rinj, i fotografom\u00eb dhe p\u00ebrdit\u00ebsojm\u00eb vitrin\u00ebn. <\/p>\n<p>Majat roz\u00eb jan\u00eb azhurnime produktesh, q\u00eb do t\u00eb thot\u00eb ndryshime n\u00eb produkte. Mund t\u00eb shihet se ata kan\u00eb fotografuar, fotografuar, dhe pastaj bam! \u2014 ngarkuan nj\u00eb s\u00ebr\u00eb ngjarjesh.<\/p>\n<h2>Rastet e p\u00ebrdorimit t\u00eb Lamoda Events<\/h2>\n<p>\nArkitektur\u00ebn e nd\u00ebrtuar e p\u00ebrdorim p\u00ebr operacione t\u00eb tilla:<\/p>\n<ul>\n<li><strong>Ndjekja e statusit t\u00eb kthimeve<\/strong>: thirrje p\u00ebr veprim dhe ndjekje e statusit nga t\u00eb gjitha sistemet e angazhuara. Pagesa, statuset, fiskalizimi, njoftimet. K\u00ebtu kemi provuar nj\u00eb qasje, zhvilluar mjetet, mbledhur t\u00eb gjitha defektet, shkruar dokumentacionin dhe treguar koleg\u00ebve se si t\u00eb p\u00ebrdorin ato.<\/li>\n<li><strong>P\u00ebrdit\u00ebsimi i kartelave t\u00eb produkteve: <\/strong>konfigurimi, meta-t\u00eb dh\u00ebnat, karakteristikat. Nj\u00eb sistem lexon (q\u00eb paraqitet), nd\u00ebrsa disa shkruajn\u00eb.<\/li>\n<li><strong>Email, push dhe sms<\/strong>: porosia \u00ebsht\u00eb mbledhur, porosia ka mb\u00ebrritur, kthimi \u00ebsht\u00eb pranuar, etj., shum\u00eb t\u00eb till\u00eb. <\/li>\n<li><strong>Stoku, p\u00ebrdit\u00ebsimi i magazin\u00ebs<\/strong>\u00a0\u2014 p\u00ebrdit\u00ebsimi sasiore i emrave, thjesht numra: ardhja n\u00eb magazin\u00eb, kthimi. Nevojitet q\u00eb t\u00eb gjitha sistemet, t\u00eb lidhura me rezervimin e produkteve, t\u00eb operojn\u00eb me t\u00eb dh\u00ebna sa m\u00eb t\u00eb sakta. Aktualisht, sistemi i p\u00ebrdit\u00ebsimit t\u00eb stokut \u00ebsht\u00eb mjaft kompleks, Kafka do ta thjeshtoj\u00eb at\u00eb.<\/li>\n<li><strong>Analiza e t\u00eb Dh\u00ebnave<\/strong> (departamenti R&amp;D), mjete ML, analiza, statistika. Ne duam q\u00eb informacioni t\u00eb jet\u00eb transparent \u2014 p\u00ebr k\u00ebt\u00eb, Kafka \u00ebsht\u00eb shum\u00eb e p\u00ebrshtatshme.<\/li>\n<\/ul>\n<p>\nTani pjesa m\u00eb interesante rreth ngjarjeve t\u00eb papritura dhe zbulimeve interesante q\u00eb ndodh\u00ebn p\u00ebr gjasht\u00eb muaj.<\/p>\n<h2>Problemet e dizajnimit<\/h2>\n<p>\nSupozoni se d\u00ebshirojm\u00eb t\u00eb b\u00ebjm\u00eb nj\u00eb gj\u00eb t\u00eb re \u2014 p\u00ebr shembull, t\u00eb transferojm\u00eb t\u00eb gjith\u00eb procesin e dor\u00ebzimit n\u00eb Kafka. Tani nj\u00eb pjes\u00eb e procesit realizohet n\u00eb Order Processing n\u00eb BOB. Pas kalimit t\u00eb porosis\u00eb n\u00eb sh\u00ebrbimin e d\u00ebrges\u00ebs, l\u00ebvizjes n\u00eb magazin\u00ebn nd\u00ebrmjet\u00ebse dhe \u00e7\u00ebshtjeve t\u00eb tjera q\u00ebndron nj\u00eb model statusi. Ka nj\u00eb monolit t\u00eb t\u00ebr\u00eb, madje dy, plus nj\u00eb mori API q\u00eb i kushtohen d\u00ebrges\u00ebs. Ata din\u00eb shum\u00eb m\u00eb tep\u00ebr rreth dor\u00ebzimit. <\/p>\n<p>Duket se jan\u00eb fusha t\u00eb ngjashme, por p\u00ebr Order Processing n\u00eb BOB dhe p\u00ebr sistemin e d\u00ebrges\u00ebs, statuset dallojn\u00eb. P\u00ebr shembull, disa sh\u00ebrbime t\u00eb kurier\u00ebve nuk d\u00ebrgojn\u00eb statuset nd\u00ebrmjet\u00ebse, por vet\u00ebm finale: \"d\u00ebrguar\" ose \"humbur\". T\u00eb tjerat, p\u00ebrkundrazi, raportojn\u00eb shum\u00eb holl\u00ebsisht p\u00ebr l\u00ebvizjen e mallrave. T\u00eb gjith\u00eb kan\u00eb rregulla t\u00eb veta p\u00ebr verifikimin: p\u00ebr disa, nj\u00eb email i vlefsh\u00ebm do t\u00eb thot\u00eb q\u00eb do t\u00eb p\u00ebrpunojn\u00eb; p\u00ebr t\u00eb tjer\u00ebt \u2014 nj\u00eb email jo i vlefsh\u00ebm, por porosia do t\u00eb p\u00ebrpunoj\u00eb p\u00ebr shkak se ka nj\u00eb telefon p\u00ebr kontakt, nd\u00ebrsa disa do t\u00eb thon\u00eb q\u00eb nj\u00eb porosi e till\u00eb nuk do t\u00eb p\u00ebrpunohet fare.<\/p>\n<h3>Shkalla e t\u00eb dh\u00ebnave<\/h3>\n<p>\nN\u00eb rastin e Kafka-s, lind pyetja e organizimit t\u00eb shkall\u00ebs s\u00eb t\u00eb dh\u00ebnave. Ky detyr\u00eb lidhet me zgjedhjen e strategjis\u00eb n\u00eb disa pika, do t\u00eb kalojm\u00eb n\u00ebp\u00ebr to t\u00eb gjitha.<\/p>\n<h4>N\u00eb nj\u00eb tem\u00eb apo n\u00eb t\u00eb ndryshme?<\/h4>\n<p>\nNe kemi nj\u00eb specifikim ngjarjeje. N\u00eb BOB ne shkruajm\u00eb se cila porosi duhet t\u00eb d\u00ebrgohet dhe tregojm\u00eb: numrin e porosis\u00eb, p\u00ebrb\u00ebrjen e saj, disa SKU dhe barkodet, etj. Kur produkti t\u00eb arrij\u00eb n\u00eb magazin\u00eb, d\u00ebrgesa do t\u00eb mund t\u00eb marr\u00eb statuse, timestamps dhe gjith\u00e7ka q\u00eb nevojitet. Por pastaj ne duam t\u00eb marrim p\u00ebrdit\u00ebsime n\u00eb BOB p\u00ebr k\u00ebto t\u00eb dh\u00ebna. K\u00ebtu krijohet nj\u00eb proces i kund\u00ebrt p\u00ebr marrjen e t\u00eb dh\u00ebnave nga d\u00ebrgesa. A \u00ebsht\u00eb kjo e nj\u00ebjta ngjarje? Ose \u00ebsht\u00eb nj\u00eb shk\u00ebmbim i ve\u00e7ant\u00eb q\u00eb meriton nj\u00eb tem\u00eb t\u00eb ve\u00e7ant\u00eb?<\/p>\n<p>Me sa duket, ato do t\u00eb jen\u00eb shum\u00eb t\u00eb ngjashme dhe sugjerimi p\u00ebr t\u00eb krijuar nj\u00eb tem\u00eb t\u00eb vetme \u00ebsht\u00eb i arsyesh\u00ebm, sepse nj\u00eb tem\u00eb e ve\u00e7ant\u00eb do t\u00eb thot\u00eb konsumator\u00eb t\u00eb ve\u00e7ant\u00eb, konfigurime t\u00eb ve\u00e7anta, dhe gjenerimin e gjith\u00e7kaje t\u00eb k\u00ebsaj. Por nuk \u00ebsht\u00eb e sigurt.<\/p>\n<h4>Fush\u00eb e re apo ngjarje e re?<\/h4>\n<p>\nPor n\u00ebse p\u00ebrdoren t\u00eb nj\u00ebjtat ngjarje, ndodh nj\u00eb problem tjet\u00ebr. P\u00ebr shembull, jo t\u00eb gjitha sistemet e d\u00ebrges\u00ebs mund t\u00eb gjenerojn\u00eb nj\u00eb DTO t\u00eb till\u00eb q\u00eb mund t\u00eb gjenerojn\u00eb BOB. Ne iu d\u00ebrgojm\u00eb atyre id, por ata nuk i ruajn\u00eb, sepse nuk u nevojiten, nd\u00ebrsa nga pik\u00ebpamja e fillimit t\u00eb procesit t\u00eb event-bus, kjo fush\u00eb \u00ebsht\u00eb e domosdoshme. <\/p>\n<p>N\u00ebse vendosim nj\u00eb rregull p\u00ebr event-bus q\u00eb ky fush\u00eb \u00ebsht\u00eb e detyrueshme, at\u00ebher\u00eb jemi t\u00eb detyruar t\u00eb vendosim rregulla shtes\u00eb verifikimi n\u00eb BOB ose n\u00eb p\u00ebrpunuesin e ngjarjeve fillestare. Verifikimi fillon t\u00eb p\u00ebrhapet n\u00eb sh\u00ebrbim \u2014 kjo nuk \u00ebsht\u00eb shum\u00eb e p\u00ebrshtatshme.<\/p>\n<p>Nj\u00eb tjet\u00ebr problem \u00ebsht\u00eb tundimi i zhvillimit inkremental. Na thon\u00eb se duhet t\u00eb shtojm\u00eb di\u00e7ka n\u00eb ngjarje, dhe ndoshta, n\u00ebse mendoni mir\u00eb, kjo duhej t\u00eb ishte nj\u00eb ngjarje e ve\u00e7ant\u00eb. Por n\u00eb skem\u00ebn ton\u00eb, nj\u00eb ngjarje e ve\u00e7ant\u00eb \u00ebsht\u00eb nj\u00eb tem\u00eb e ve\u00e7ant\u00eb. Nj\u00eb tem\u00eb e ve\u00e7ant\u00eb \u00ebsht\u00eb gjith\u00eb ai proces q\u00eb e p\u00ebrshkrova m\u00eb sip\u00ebr. Zhvilluesi ka tundimin t\u00eb thjesht t\u00eb shtoj\u00eb nj\u00eb fush\u00eb tjet\u00ebr n\u00eb skem\u00ebn JSON dhe t\u00eb gjeneroj\u00eb p\u00ebrs\u00ebri.<\/p>\n<p>N\u00eb rastin e refunds, ashtu arrit\u00ebm pas gjasht\u00eb muajsh n\u00eb ngjarjen e ngjarjeve. Kemi pasur nj\u00eb meta-ngjarje q\u00eb quhet rifreskim i rimbursimit, e cila kishte nj\u00eb fush\u00eb tipi, duke p\u00ebrshkruar se n\u00eb \u00e7far\u00eb konsiston ky rifreskim. Nga kjo kishim 'fantastike' switch-e me verifikuesit, q\u00eb tregonin si duhet t\u00eb verifikohet kjo ngjarje me k\u00ebt\u00eb tip.<\/p>\n<h4>Versionimi i ngjarjeve<\/h4>\n<p>\nP\u00ebr verifikimin e mesazheve n\u00eb Kafka, mund t\u00eb p\u00ebrdorim <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.confluent.io\/current\/schema-registry\/docs\/index.html\">Avro<\/a><\/noindex>, por duhet te planifikohet qe t\u00eb p\u00ebrdoret Confluent. N\u00eb rastin ton\u00eb me versionimin duhet t\u00eb jemi t\u00eb kujdessh\u00ebm. Nuk do t\u00eb jet\u00eb gjithmon\u00eb e mundur t\u00eb rivizitojm\u00eb mesazhet nga replication log, p\u00ebr shkak se modeli u zhvendos. Kryesisht, arrihet t\u00eb nd\u00ebrtojm\u00eb versione n\u00eb m\u00ebnyr\u00eb q\u00eb modeli t\u00eb jet\u00eb n\u00eb p\u00ebrputhje prapavepruese: p\u00ebr shembull, ta b\u00ebjm\u00eb nj\u00eb fush\u00eb p\u00ebrkoh\u00ebsisht t\u00eb panevojshme. N\u00ebse dallimet jan\u00eb shum\u00eb t\u00eb m\u00ebdha, fillojm\u00eb t\u00eb shkruajm\u00eb n\u00eb nj\u00eb tem\u00eb t\u00eb re, dhe klient\u00ebt migr p\u00ebrshtaten kur t\u00eb p\u00ebrfundojn\u00eb leximin e atij t\u00eb vjetri.<\/p>\n<h4>Garancia e rendit t\u00eb leximit t\u00eb partitions<\/h4>\n<p>\nTemat brenda Kafka jan\u00eb t\u00eb ndara n\u00eb partitions. Kjo nuk \u00ebsht\u00eb shum\u00eb e r\u00ebnd\u00ebsishme derisa t\u00eb projektom\u00eb entitetet dhe shk\u00ebmbimet, por \u00ebsht\u00eb e r\u00ebnd\u00ebsishme kur vendosim si t\u2019i konsumohem dhe t\u00eb shkall\u00ebzojm\u00eb.<\/p>\n<p>N\u00eb gjendjen e zakonshme, ju shkruani nj\u00eb topic n\u00eb Kafka. N\u00ebse nuk ndryshohet, p\u00ebrdoret nj\u00eb partition dhe t\u00eb gjitha mesazhet e atij topic-i shkojn\u00eb aty. Konsumatori pastaj lexon k\u00ebto mesazhe nj\u00eb pas nj\u00eb. Le t\u00eb themi tani se duhet t\u00eb zgjeroni sistemin n\u00eb m\u00ebnyr\u00eb q\u00eb mesazhet t\u00eb lexohen nga dy konsumator\u00eb t\u00eb ndrysh\u00ebm. N\u00ebse ju, p\u00ebr shembull, d\u00ebrgoni nj\u00eb SMS, mund t\u00eb thoni se Kafka duhet t\u00eb krijoj\u00eb nj\u00eb partition t\u00eb shtuar dhe Kafka do t\u00eb filloj\u00eb t\u00eb ndaj\u00eb mesazhet n\u00eb dy pjes\u00eb \u2014 gjysm\u00ebn aty, gjysm\u00ebn k\u00ebtu. <\/p>\n<p>Si i ndan Kafka ato? \u00c7do mesazh ka nj\u00eb trup (ku ruajm\u00eb JSON) dhe nj\u00eb \u00e7el\u00ebs. N\u00eb k\u00ebt\u00eb \u00e7el\u00ebs mund t\u00eb aplikoni nj\u00eb funksion hash, q\u00eb do t\u00eb p\u00ebrcaktoj\u00eb se n\u00eb cilin partition do t\u00eb bjer\u00eb mesazhi.<\/p>\n<p>N\u00eb rastin ton\u00eb me refunds, kjo \u00ebsht\u00eb e r\u00ebnd\u00ebsishme; n\u00ebse marrim dy partition, ka nj\u00eb mund\u00ebsi q\u00eb konsumatori paralel t\u00eb p\u00ebrpunoj\u00eb ngjarjen e dyt\u00eb p\u00ebrpara asaj t\u00eb par\u00eb dhe kjo do t\u00eb ishte nj\u00eb problem. Funksioni hash garanton q\u00eb mesazhet me \u00e7el\u00ebsa t\u00eb nj\u00ebjte do t\u00eb bien n\u00eb t\u00eb nj\u00ebjtin partition. <\/p>\n<h4>Ngjarjet vs urdhra<\/h4>\n<p>\nKjo \u00ebsht\u00eb nj\u00eb tjet\u00ebr \u00e7\u00ebshtje me t\u00eb cil\u00ebn jemi p\u00ebrballur. Nj\u00eb ngjarje \u00ebsht\u00eb nj\u00eb lloj ngjarjeje: ne themi se di\u00e7ka ndodhi diku (something_happened), p\u00ebr shembull, artikulli u anulua ose ndodhi nj\u00eb rimbursim. N\u00ebse dikush e d\u00ebgjon k\u00ebto ngjarje, at\u00ebher\u00eb p\u00ebr 'artikulli u anulua' do t\u00eb krijohet entiteti i rimbursimit, dhe 'ndodhi nj\u00eb rimbursim' do t\u00eb regjistrohet diku n\u00eb konfigurime.<\/p>\n<p>Por zakonisht, kur projektoni ngjarje, nuk doni t'i shkruani ato kot \u2014 ju mb\u00ebshteteni se dikush do t'i lexoj\u00eb ato. Ka nj\u00eb tundim t\u00eb lart\u00eb t\u00eb shkruani di\u00e7ka q\u00eb nuk \u00ebsht\u00eb something_happened (item_canceled, refund_refunded), por di\u00e7ka si something_should_be_done. P\u00ebr shembull, artikulli \u00ebsht\u00eb gati p\u00ebr kthim.<\/p>\n<p>Nga nj\u00ebra an\u00eb, kjo tregon se si do t\u00eb p\u00ebrdoret ngjarja. Nga ana tjet\u00ebr, kjo duket shum\u00eb m\u00eb pak si nj\u00eb em\u00ebr normal ngjarjeje. Posht\u00eb k\u00ebsaj, \u00ebsht\u00eb nj\u00eb hap i vog\u00ebl deri te komanda do_something. Por nuk keni garanci se kjo ngjarje do t\u00eb lexohet nga dikush; dhe n\u00ebse \u00ebsht\u00eb lexuar, at\u00ebher\u00eb \u00ebsht\u00eb lexuar me sukses; dhe n\u00ebse \u00ebsht\u00eb lexuar me sukses, at\u00ebher\u00eb b\u00ebri di\u00e7ka, dhe ajo di\u00e7ka kaloi me sukses. N\u00eb momentin q\u00eb ngjarja b\u00ebhet do_something, nevoja p\u00ebr p\u00ebrgjigje b\u00ebhet e domosdoshme, dhe kjo \u00ebsht\u00eb nj\u00eb problem.<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/b755d91208092bd9791a41ce4633fb48.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nN\u00eb shk\u00ebmbimin asinkron n\u00eb RabbitMQ, kur lexoni nj\u00eb mesazh dhe b\u00ebni nj\u00eb k\u00ebrkes\u00eb http, keni nj\u00eb p\u00ebrgjigje - pavar\u00ebsisht se mesazhi \u00ebsht\u00eb pranuar. Kur shkruani n\u00eb Kafka, ka nj\u00eb mesazh q\u00eb e keni shkruar n\u00eb Kafka, por nuk dini asgj\u00eb p\u00ebr m\u00ebnyr\u00ebn se si u procesua. <\/p>\n<p>Prandaj, n\u00eb rastin ton\u00eb, ishte e nevojshme t\u00eb futnim nj\u00eb ngjarje p\u00ebrgjigjeje dhe t\u00eb konfiguroni monitorimin p\u00ebr at\u00eb q\u00eb, n\u00ebse ndodhin kaq shum\u00eb ngjarje, pas nj\u00eb kohe t\u00eb caktuar duhet t\u00eb arrijn\u00eb kaq shum\u00eb ngjarje p\u00ebrgjigjeje. N\u00ebse kjo nuk ndodhi, duket se di\u00e7ka shkoi keq. P\u00ebr shembull, n\u00ebse d\u00ebrguam ngjarjen \u00abitem_ready_to_refund\u00bb, presim q\u00eb t\u00eb krijohet nj\u00eb rimbursim, klientit tia kthejm\u00eb parat\u00eb, dhe t\u00eb na dal\u00eb ngjarja \u00abmoney_refunded\u00bb. Por kjo nuk \u00ebsht\u00eb e sigurt, prandaj \u00ebsht\u00eb e nevojshme t\u00eb monitorohet.<\/p>\n<h3>Nuancat<\/h3>\n<p>\nKa nj\u00eb problem t\u00eb duksh\u00ebm: n\u00ebse lexoni me radh\u00eb nga nj\u00eb tem\u00eb dhe keni nj\u00eb mesazh t\u00eb keq, konsumatori bie, dhe m\u00eb pas nuk mund t\u00eb vazhdoni. Ju nevojitet <strong>t\u00eb ndaloni t\u00eb gjith\u00eb konsumator\u00ebt<\/strong>, t\u00eb komitoni offset-in m\u00eb tej, p\u00ebr t\u00eb vazhduar leximin.<\/p>\n<p>Ne e dim\u00eb q\u00eb kjo ndodhi, e planifikuam, por megjithat\u00eb ndodhi. K\u00ebtu ndodhi sepse ngjarja ishte e vlefshme sipas events-bus, ngjarja ishte e vlefshme sipas validatorit t\u00eb aplikacionit, por nuk ishte e vlefshme sipas PostgreSQL, sepse kemi nj\u00eb sistem MySQL me UNSIGNED INT, nd\u00ebrsa n\u00eb sistemin e ri kishte vet\u00ebm PostgreSQL me INT. Ai ka nj\u00eb madh\u00ebsi pak m\u00eb t\u00eb vog\u00ebl dhe Id nuk u fut. Symfony u ndal me nj\u00eb p\u00ebrjashtim. Ne, natyrisht, kap\u00ebm p\u00ebrjashtimin, sepse e kishim parashikuar at\u00eb dhe planifikonim t\u00eb angazhonim k\u00ebt\u00eb offset, por para k\u00ebsaj donim t\u00eb inkrementonim numrin e problemeve, pasi mesazhi d\u00ebshtoi gjat\u00eb p\u00ebrpunimit. Numrat n\u00eb k\u00ebt\u00eb projekt gjithashtu jan\u00eb n\u00eb baz\u00eb, kurse Symfony tashm\u00eb e kishte mbyllur komunikimin me baz\u00ebn, dhe p\u00ebrjashtimi i dyt\u00eb vrau gjith\u00eb procesin pa mund\u00ebsi p\u00ebr t\u00eb angazhuar offset.<\/p>\n<p>P\u00ebr nj\u00eb koh\u00eb sh\u00ebrbimi q\u00ebndroi \u2013 p\u00ebr fat t\u00eb mir\u00eb, me Kafka kjo nuk \u00ebsht\u00eb aq e frikshme, sepse mesazhet mbeten. Kur puna t\u00eb rifilloj\u00eb, do t\u00eb jet\u00eb e mundur t\u00eb merren ato. Kjo \u00ebsht\u00eb komode.<\/p>\n<p>N\u00eb Kafka ka mund\u00ebsi q\u00eb p\u00ebrmes tooling t\u00eb vendosni nj\u00eb offset t\u00eb caktuar. Por p\u00ebr ta b\u00ebr\u00eb k\u00ebt\u00eb, duhet t\u00eb ndaloni t\u00eb gjith\u00eb konsumator\u00ebt \u2014 n\u00eb rastin ton\u00eb, t\u00eb p\u00ebrgatisim nj\u00eb version t\u00eb ve\u00e7ant\u00eb, n\u00eb t\u00eb cilin nuk do t\u00eb ket\u00eb konsumator\u00eb, redeployments. At\u00ebher\u00eb n\u00eb Kafka p\u00ebrmes tooling mund t\u00eb zhvendosni offset-in dhe mesazhi do t\u00eb kaloj\u00eb.<\/p>\n<p>Nj\u00eb tjet\u00ebr nuanc\u00eb \u2014 <strong>replication log vs rdkafka.so<\/strong>\u00a0\u2014 \u00ebsht\u00eb i lidhur me specifikat e projektit ton\u00eb. Ne p\u00ebrdorim PHP dhe n\u00eb PHP, zakonisht t\u00eb gjitha bibliotekat komunikojn\u00eb me Kafka p\u00ebrmes repository rdkafka.so, dhe m\u00eb pas vjen ndonj\u00eblloj mb\u00ebshtetje. Ndoshta, k\u00ebto jan\u00eb v\u00ebshtir\u00ebsit\u00eb tona personale, por rezultoi se t\u00eb riflitet nj\u00eb cop\u00eb e lexuar m\u00eb par\u00eb nuk \u00ebsht\u00eb aq e leht\u00eb. N\u00eb p\u00ebrgjith\u00ebsi, kishim probleme me softuerin.<\/p>\n<p>Duke u kthyer n\u00eb ve\u00e7orit\u00eb e pun\u00ebs me partitions, n\u00eb dokumentacionin e drejtp\u00ebrdrejt\u00eb shkruhet <strong>consumers &gt;= topic partitions<\/strong>. Por e m\u00ebsova k\u00ebt\u00eb shum\u00eb m\u00eb von\u00eb se sa doja. N\u00ebse d\u00ebshironi t\u00eb shkalloni dhe t\u00eb keni dy konsumator\u00eb, ju nevojiten t\u00eb pakt\u00ebn dy partitions. Pra, n\u00ebse keni pasur nj\u00eb partition, n\u00eb t\u00eb cilin jan\u00eb grumbulluar 20 mij\u00eb mesazhe dhe krijoni nj\u00eb t\u00eb ri, numri i mesazheve nuk do t\u00eb rregullohet shpejt. Prandaj, p\u00ebr t\u00eb pasur dy konsumator\u00eb paralel\u00eb, duhet t\u00eb merret me partitions.<\/p>\n<h2>Monitorimi<\/h2>\n<p>\nMendoj se, nga monitorimi yn\u00eb, do t\u00eb jet\u00eb m\u00eb e qart\u00eb se cilat probleme ka qasja aktuale.<\/p>\n<p>P\u00ebr shembull, ne num\u00ebrojm\u00eb sa produkte n\u00eb baz\u00eb kan\u00eb ndryshuar statusin s\u00eb fundmi, dhe n\u00eb p\u00ebrputhje me k\u00ebto ndryshime, ndodhin ngjarje, dhe e d\u00ebrgojm\u00eb k\u00ebt\u00eb num\u00ebr n\u00eb sistemin ton\u00eb t\u00eb monitorimit. M\u00eb pas, nga Kafka marrim numrin e dyt\u00eb, sa ngjarje jan\u00eb regjistruar n\u00eb t\u00eb v\u00ebrtet\u00eb. \u00cbsht\u00eb e qart\u00eb, diferenca mes k\u00ebtyre dy numrave gjithmon\u00eb duhet t\u00eb jet\u00eb zero.<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/07d8ed08514f2fb97d9019466b96342c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nP\u00ebrve\u00e7 k\u00ebsaj, duhet t\u00eb monitorojm\u00eb se si po shkon puna me prodhuesin, n\u00ebse events-bus ka pranuar mesazhet, dhe si po shkon puna me konsumatorin. P\u00ebr shembull, n\u00eb grafiket m\u00eb posht\u00eb, gjith\u00e7ka \u00ebsht\u00eb mir\u00eb me Refund Tool, por me BOB duksh\u00ebm ka disa probleme (pikat blu).<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/57112dbe70d2b388c53f19c34cca6f63.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKisha p\u00ebrmendur tashm\u00eb vones\u00ebn e grupit t\u00eb konsumator\u00ebve. N\u00eb thelb, kjo \u00ebsht\u00eb numri i mesazheve t\u00eb papara. N\u00eb p\u00ebrgjith\u00ebsi, konsumator\u00ebt tan\u00eb punojn\u00eb shpejt, prandaj vonesa zakonisht \u00ebsht\u00eb 0, por ndonj\u00ebher\u00eb mund t\u00eb ket\u00eb nj\u00eb pik\u00eb t\u00eb shkurt\u00ebr. Kafka e b\u00ebn k\u00ebt\u00eb nga kuti, por \u00ebsht\u00eb e nevojshme t\u00eb vendosim nj\u00eb interval. <\/p>\n<p>Ka nj\u00eb projekt <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/linkedin\/Burrow\">Burrow<\/a><\/noindex>, q\u00eb do t'ju jap\u00eb m\u00eb shum\u00eb informacion mbi Kafka. Ai thjesht jep statusin e grupit t\u00eb konsumator\u00ebve p\u00ebrmes API-s\u00eb. P\u00ebrve\u00e7 OK dhe Failed, ka nj\u00eb warning, dhe do t\u00eb jeni n\u00eb gjendje t\u00eb dini n\u00ebse konsumator\u00ebt tuaj nuk po p\u00ebrballohen me ritmin e prodhimit \u2013 nuk arrijn\u00eb t\u00eb lexojn\u00eb at\u00eb q\u00eb shkruhet. Sistemi \u00ebsht\u00eb mjaft i men\u00e7ur, \u00ebsht\u00eb leht\u00eb p\u00ebr t'u p\u00ebrdorur. <\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/cece8495801e187b155487a802e1a35a.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nK\u00ebtu \u00ebsht\u00eb si duket p\u00ebrgjigja n\u00eb API. K\u00ebtu grupi bob-live-fifa, ndarja refund.update.v1, statusi OK, lag 0 \u2013 offseti i fundit \u00ebsht\u00eb i till\u00eb.<\/p>\n<p><img decoding=\"async\" alt=\"Eksperienca n\u00eb zhvillimin e sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka\" src=\"\/wp-content\/uploads\/2019\/04\/1538b2ccc390e9b83075f54566f1039b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMonitorimi <strong>updated_at SLA (ngrir\u00eb)<\/strong> un\u00eb tashm\u00eb e kam p\u00ebrmendur. P\u00ebr shembull, produkti kaloi n\u00eb statusin q\u00eb \u00ebsht\u00eb gati p\u00ebr kthim. Ne vendosim nj\u00eb Cron, q\u00eb thot\u00eb se n\u00ebse brenda 5 minutave ky objekt nuk kalon n\u00eb refund (ne i kthejm\u00eb parat\u00eb p\u00ebrmes sistemeve t\u00eb pagesave shum\u00eb shpejt), at\u00ebher\u00eb di\u00e7ka ka shkuar ndryshe, dhe ky \u00ebsht\u00eb nj\u00eb rast i sigurt p\u00ebr suportin. Prandaj, thjesht marrim Cron-in q\u00eb lexon k\u00ebto gj\u00ebra dhe n\u00ebse ato jan\u00eb m\u00eb shum\u00eb se 0, d\u00ebrgon nj\u00eb alarme.<\/p>\n<p><b>N\u00eb p\u00ebrfundim, p\u00ebrdorimi i ngjarjeve \u00ebsht\u00eb i p\u00ebrshtatsh\u00ebm kur<\/b>:<\/p>\n<ul>\n<li>informacioni k\u00ebrkohet nga disa sisteme;<\/li>\n<li>rezultati i p\u00ebrpunimit nuk ka r\u00ebnd\u00ebsi;<\/li>\n<li>ngjarjet jan\u00eb pak ose ngjarjet jan\u00eb t\u00eb vogla. <\/li>\n<\/ul>\n<blockquote><p>Duket sikur artikulli ka nj\u00eb tem\u00eb shum\u00eb specifike - API asinkron n\u00eb Kafka, por n\u00eb lidhje me t\u00eb ka shum\u00eb t\u00eb tjera q\u00eb do t\u00eb rekomandoja menj\u00ebher\u00eb.<br \/>\nS\u00eb pari, e ardhmja <noindex><a rel=\"nofollow\" href=\"https:\/\/www.highload.ru\/\">HighLoad++<\/a><\/noindex> nuk duhet t\u00eb prisni deri n\u00eb n\u00ebntor, versioni i Sh\u00ebn Petersburgut do t\u00eb jet\u00eb n\u00eb prill, dhe n\u00eb qershor do t\u00eb flasim p\u00ebr ngarkesat e r\u00ebnda n\u00eb Novosibirsk.<br \/>\nS\u00eb dyti, autori i raportit, Sergei Zaika, \u00ebsht\u00eb pjes\u00eb e Komitetit Organizativ t\u00eb konferenc\u00ebs son\u00eb t\u00eb re p\u00ebr menaxhimin e njohurive <noindex><a rel=\"nofollow\" href=\"https:\/\/knowledgeconf.ru\/2019\">KnowledgeConf<\/a><\/noindex>. Konferenca do t\u00eb jet\u00eb nj\u00eb ditore, do t\u00eb zhvillohet m\u00eb 26 prill, por programi i saj \u00ebsht\u00eb shum\u00eb i pasur.<br \/>\nDhe n\u00eb maj do t\u00eb ket\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/phprussia.ru\/2019\">PHP Russia<\/a><\/noindex> dhe\u00a0<noindex><a rel=\"nofollow\" href=\"https:\/\/ritfest.ru\/2019\">RIT++<\/a><\/noindex> (me DevOpsConf n\u00eb p\u00ebrb\u00ebrje) - atje mund t\u00eb ofroni ende tem\u00ebn tuaj, t\u00eb flisni p\u00ebr p\u00ebrvoj\u00ebn tuaj dhe t\u00eb ankohemi p\u00ebr dh\u00ebmbjet tuaja.<\/p><\/blockquote>\n<p>Burimi: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/oleg-bunin\/blog\/445424\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0427\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044e \u043a\u0430\u043a Lamoda \u0441\u00a0\u043e\u0442\u043b\u0430\u0436\u0435\u043d\u043d\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0438\u00a0\u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434? \u041c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0440\u0430\u0437\u043d\u0430\u044f: \u043e\u0442\u00a0\u0437\u0430\u043a\u043e\u043d\u043e\u0434\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u00a0\u043f\u0440\u0438\u0441\u0443\u0449\u0435\u0433\u043e \u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u043c \u0436\u0435\u043b\u0430\u043d\u0438\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041d\u043e\u00a0\u044d\u0442\u043e \u0432\u043e\u0432\u0441\u0435 \u043d\u0435\u00a0\u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u00a0\u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0432\u044b\u0433\u043e\u0434\u0443. \u0412\u00a0\u0447\u0435\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0438\u0433\u0440\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c events-driven API \u043d\u0430\u00a0Kafka, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442 \u0421\u0435\u0440\u0433\u0435\u0439 \u0417\u0430\u0438\u043a\u0430 (fewald). \u041f\u0440\u043e \u043d\u0430\u0431\u0438\u0442\u044b\u0435 \u0448\u0438\u0448\u043a\u0438 \u0438\u00a0\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0442\u043e\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":22763,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-30778","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0427\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044e \u043a\u0430\u043a Lamoda \u0441 \u043e\u0442\u043b\u0430\u0436\u0435\u043d\u043d\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0438 \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434? \u041c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0440\u0430\u0437\u043d\u0430\u044f: \u043e\u0442 \u0437\u0430\u043a\u043e\u043d\u043e\u0434\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u043e \u043f\u0440\u0438\u0441\u0443\u0449\u0435\u0433\u043e \u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u043c \u0436\u0435\u043b\u0430\u043d\u0438\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041d\u043e \u044d\u0442\u043e \u0432\u043e\u0432\u0441\u0435 \u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0432\u044b\u0433\u043e\u0434\u0443. \u0412 \u0447\u0435\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0438\u0433\u0440\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c events-driven API \u043d\u0430 Kafka, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442 \u0421\u0435\u0440\u0433\u0435\u0439 \u0417\u0430\u0438\u043a\u0430 (fewald). \u041f\u0440\u043e \u043d\u0430\u0431\u0438\u0442\u044b\u0435 \u0448\u0438\u0448\u043a\u0438 \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0442\u043e\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/opyt-razrabotki-servisa-refund-tool-s-asinhronnym-api-na-kafka\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"sq_AL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041e\u043f\u044b\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 Refund Tool \u0441 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c API \u043d\u0430 Kafka | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0427\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044e \u043a\u0430\u043a Lamoda \u0441 \u043e\u0442\u043b\u0430\u0436\u0435\u043d\u043d\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0438 \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434? \u041c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0440\u0430\u0437\u043d\u0430\u044f: \u043e\u0442 \u0437\u0430\u043a\u043e\u043d\u043e\u0434\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u043e \u043f\u0440\u0438\u0441\u0443\u0449\u0435\u0433\u043e \u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u043c \u0436\u0435\u043b\u0430\u043d\u0438\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041d\u043e \u044d\u0442\u043e \u0432\u043e\u0432\u0441\u0435 \u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0432\u044b\u0433\u043e\u0434\u0443. \u0412 \u0447\u0435\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0438\u0433\u0440\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c events-driven API \u043d\u0430 Kafka, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442 \u0421\u0435\u0440\u0433\u0435\u0439 \u0417\u0430\u0438\u043a\u0430 (fewald). \u041f\u0440\u043e \u043d\u0430\u0431\u0438\u0442\u044b\u0435 \u0448\u0438\u0448\u043a\u0438 \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0442\u043e\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/opyt-razrabotki-servisa-refund-tool-s-asinhronnym-api-na-kafka\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:37:23+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:37:23+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Eksperienca e zhvillimit t\u00eb sh\u00ebrbimit Refund Tool me API asinkron n\u00eb Kafka | ProHoster","description":"\u00c7far\u00eb mund ta b\u00ebj\u00eb nj\u00eb kompani t\u00eb madhe si Lamoda, me proceset e saj t\u00eb konsoliduara dhe dhjet\u00ebra sh\u00ebrbime t\u00eb lidhura, t\u00eb ndryshoj\u00eb ndjesh\u00ebm t\u00ebr\u00ebsisht qasje? Motivimi mund t\u00eb jet\u00eb krejt ndryshe: nga legjislativet deri te d\u00ebshira e p\u00ebrbashk\u00ebt e programuesve p\u00ebr t\u00eb eksperimentuar. Por kjo nuk do t\u00eb thot\u00eb q\u00eb nuk mund t\u00eb pritet nj\u00eb p\u00ebrfitim shtes\u00eb. Cili \u00ebsht\u00eb p\u00ebrfitimi konkret q\u00eb mund t\u00eb merret nga implementimi i API-ve t\u00eb orientuara nga ngjarjet n\u00eb Kafka, do t\u00eb tregoj\u00eb Sergey Zaika (fewald). Rreth d\u00ebmtimeve t\u00eb p\u00ebsuara dhe zbulimeve interesante do t\u00eb flitet gjithashtu.","canonical_url":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/opyt-razrabotki-servisa-refund-tool-s-asinhronnym-api-na-kafka","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sq_AL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041e\u043f\u044b\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 Refund Tool \u0441 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c API \u043d\u0430 Kafka | ProHoster","og:description":"\u0427\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044e \u043a\u0430\u043a Lamoda \u0441 \u043e\u0442\u043b\u0430\u0436\u0435\u043d\u043d\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0438 \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434? \u041c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0440\u0430\u0437\u043d\u0430\u044f: \u043e\u0442 \u0437\u0430\u043a\u043e\u043d\u043e\u0434\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u043e \u043f\u0440\u0438\u0441\u0443\u0449\u0435\u0433\u043e \u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u043c \u0436\u0435\u043b\u0430\u043d\u0438\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041d\u043e \u044d\u0442\u043e \u0432\u043e\u0432\u0441\u0435 \u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0432\u044b\u0433\u043e\u0434\u0443. \u0412 \u0447\u0435\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0438\u0433\u0440\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c events-driven API \u043d\u0430 Kafka, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442 \u0421\u0435\u0440\u0433\u0435\u0439 \u0417\u0430\u0438\u043a\u0430 (fewald). \u041f\u0440\u043e \u043d\u0430\u0431\u0438\u0442\u044b\u0435 \u0448\u0438\u0448\u043a\u0438 \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0442\u043e\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e","og:url":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/opyt-razrabotki-servisa-refund-tool-s-asinhronnym-api-na-kafka","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:37:23+00:00","article:modified_time":"2019-10-31T18:37:23+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"30778","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 02:58:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:29:56","updated":"2026-01-21 02:58:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/30778","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/comments?post=30778"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/30778\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/media\/22763"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/media?parent=30778"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/categories?post=30778"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/tags?post=30778"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}