{"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\/et\/blog\/administrirovanie\/opyt-razrabotki-servisa-refund-tool-s-asinhronnym-api-na-kafka","title":{"rendered":"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Mis v\u00f5ib panna nii suurt ettev\u00f5tet nagu Lamoda, kellel on sujuv protsess ja k\u00fcmneid omavahel seotud teenuseid, oluliselt l\u00e4henemist muutma? Motivatsioon v\u00f5ib olla t\u00e4iesti erinev: alates seadusandlikest n\u00f5uetest kuni igale programmerimisega tegelejale iseloomuliku soovini katsetada.<\/p>\n<p>Aga see ei t\u00e4henda, et ei saa loota lisah\u00fcvedele. Mida t\u00e4pselt on v\u00f5imalik v\u00f5ita, kui rakendada s\u00fcndmusp\u00f5hise API-d Kafka-l, r\u00e4\u00e4gib Sergei Zaika (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/users\/fewald\/\" class=\"user_link\">fewald<\/a><\/noindex>). K\u00f5ikidest kogemustest ja huvitavatest avastustest tuleb samuti kindlasti juttu \u2013 ilma nendeta ei saa katsetamine juhtuda.<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/7ab959ab45ec5c6565b35b18b361c0ea.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<em>Disclaimer: See artikkel p\u00f5hineb materjalidel, mis esitati meetapil, mille Sergei viis l\u00e4bi novembris 2018 HighLoad++-il. Lamoda elav kogemus Kafka-ga t\u00f5mbas kuulajaid sama palju kui teised ettekanded ajakavas. Me arvame, et see on suurep\u00e4rane n\u00e4ide sellest, et alati on v\u00f5imalik ja vajalik leida m\u00f5ttekaaslasi, ning HighLoad++ korraldajad j\u00e4tkavad atmosf\u00e4\u00e4ri loomist, mis soosib seda.<\/em><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Protsessi kohta<\/h2>\n<p>\nLamoda \u2014 on suur e-kaubanduse platvorm, millel on oma kontaktikeskus, kohaletoimetamisteenus (ja palju partnereid), fotostuudio, suur laod ja k\u00f5ik see t\u00f6\u00f6tab oma tarkvara peal. Olemas on k\u00fcmneid makseviise, b2b-partnereid, kes saavad kasutada osa v\u00f5i k\u00f5iki neid teenuseid ja kes tahavad teada oma toodete kohta ajakohast teavet. Lisaks sellele t\u00f6\u00f6tab Lamoda kolmes riigis, v\u00e4lja arvatud RF, ja seal on k\u00f5ik veidi teisiti. Kokku on t\u00f5en\u00e4oliselt rohkem kui sada viisi, kuidas konfiguratsiooni uut tellimust, mida tuleb teisiti t\u00f6\u00f6delda. K\u00f5ik see t\u00f6\u00f6tab k\u00fcmnete teenuste abil, mis suhtlevad vahel mitte alati ilmnel viisil. Lisaks on olemas ka kesks\u00fcsteem, mille peamine vastutus on tellimuste staatused. Me nimetame seda BOB-iks, mina t\u00f6\u00f6tan selle s\u00fcsteemiga.<\/p>\n<h2>Tagasimakse t\u00f6\u00f6riist events-driven API-ga <\/h2>\n<p>\nS\u00f5na events-driven on \u00fcsna \u00fclekasutatud, veidi hiljem t\u00e4psustame, mida sellega silmas peame. Alustan kontekstist, milles me otsustasime katsetada events-driven API l\u00e4henemist Kafka kaudu. <\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/3bfdce47dd8420fc63d84645e76de647.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIgas poes, lisaks tellimustele, mille eest kliendid maksavad, on olukordi, kus poelt n\u00f5utakse raha tagastamist, kuna toode ei sobinud kliendile. See on suhteliselt l\u00fchike protsess: t\u00e4iendame teavet, kui vajalik, ja kanname raha tagasi. <\/p>\n<p>Kuid tagastamise protsess muutus keerulisemaks seadusanduse muutumise t\u00f5ttu, mist\u00f5ttu olime sunnitud selle kohandamiseks rakendama eraldi mikroteenust.<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/0e358df5476e7448976e0f1147a103fb.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMeie motivatsioon:<\/p>\n<ol>\n<li><strong>Seadus FZ-54<\/strong>\u00a0\u2014 l\u00fchidalt \u00f6eldes n\u00f5uab seadus iga rahatehingu, olgu see tagastus v\u00f5i sissevaart, teatamist maksuametile \u00fcsna l\u00fchikeses SLA-s, m\u00f5ne minuti jooksul. Meie, kui e-kaubandus, teeme \u00fcsna palju tehinguid. Tehniliselt t\u00e4hendab see uut vastutust (ja seega uut teenust) ning t\u00e4iustusi k\u00f5igis seotud s\u00fcsteemides.<\/li>\n<li><strong>BOB split<\/strong>\u00a0\u2014 ettev\u00f5tte sisemine projekt, et vabastada BOB suurest hulgast mitteprofesionaalsetest vastutustest ja v\u00e4hendada selle \u00fcldist keerukust.<\/li>\n<\/ol>\n<p>\n<img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/d3ecf9961bdb372fc5f84ee9389f73ef.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSellel skeemil on kujutatud peamisi Lamoda s\u00fcsteeme. Praegu esindab enamik neist pigem <strong>t\u00e4hekuju 5\u201310 mikroteenuse \u00fcmber, mis koondub v\u00e4heneva monoliidi \u00fcmber.<\/strong>. Nad vaikselt kasvavad, kuid me p\u00fc\u00fcame neid v\u00e4iksemaks teha, sest keskel fragmenti juurutamine on hirmutav \u2014 ei saa lubada, et see kukub. K\u00f5ik vahetused (nooled) peame varuma ja arvestama, et \u00fcksk\u00f5ik milline neist v\u00f5ib osutuda k\u00e4ttesaamatuks.<\/p>\n<p>BOB-is on samuti \u00fcsna palju vahetusi: makses\u00fcsteemid, kohaletoimetamine, teavitamine jne. <\/p>\n<p>Tehniliselt on BOB see:<\/p>\n<ul>\n<li>~150k koodirida + ~100k testirida;<\/li>\n<li>php7.2 + Zend 1 &amp; Symfony Components 3;<\/li>\n<li>&gt;100 API &amp; ~50 v\u00e4ljuvat integratsiooni;<\/li>\n<li>4 riiki oma \u00e4ri loogikaga. <\/li>\n<\/ul>\n<p>\nBOB-i juurutamine on kallis ja valus, koodi hulk ja lahendatavad \u00fclesanded on sellised, et keegi ei suuda seda t\u00e4ielikult peas hoida. \u00dches\u00f5naga, palju p\u00f5hjuseid selle lihtsustamiseks.<\/p>\n<h2>Tagastamisprotsess<\/h2>\n<p>\nAlguses on protsessis kaasatud kaks s\u00fcsteemi: BOB ja Payment. N\u00fc\u00fcd tulevad veel kaks:<\/p>\n<ul>\n<li>Fiskaliseerimise teenus, mis v\u00f5tab enda peale fiskaliseerimise probleemid ja suhtlemise v\u00e4listena teenustega.<\/li>\n<li>Tagasimakse t\u00f6\u00f6riist, kuhu lihtsalt kantakse uued vahetused, et mitte BOB-i paisutada.<\/li>\n<\/ul>\n<p>\nN\u00fc\u00fcd n\u00e4eb protsess v\u00e4lja j\u00e4rgmine:<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/13c02975881ad35c61304053c604cda3.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ol>\n<li>BOB saab tagasimakse taotluse.<\/li>\n<li>BOB teatab sellest Refund Tool-ile.<\/li>\n<li>Refund Tool \u00fctleb Payment'ile: \u201eTagasta raha\u201d.<\/li>\n<li>Payment tagastab raha.<\/li>\n<li>Refund Tool ja BOB s\u00fcnkroonivad oma staatuseid, kuna nad vajavad seda praegu koos. Me ei ole veel valmis t\u00e4ielikult Refund Tooli \u00fcle minema, kuna BOB-is on UI, raamatupidamise aruanded ja palju andmeid, mida niisama lihtsalt ei saa \u00fcle kanda. Tuleb istuda kahe tooli peal.<\/li>\n<li>Fiskaliseerimise taotlus saadetakse.<\/li>\n<\/ol>\n<p>\nL\u00f5puks olime loonud Kafka abil mingi s\u00fcndmusete busi - event-bus, millele k\u00f5ik toetuvad. Hurra, n\u00fc\u00fcd on meil \u00fcksik rikke punkt (sarcasm).<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/674edd7972998b4985071f5250612c7e.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPlussid ja miinused on \u00fcsna ilmsed. Me oleme loonud busi, mis t\u00e4hendab, et n\u00fc\u00fcd s\u00f5ltuvad k\u00f5ik teenused sellest. See lihtsustab projekteerimist, kuid toob s\u00fcsteemi sisse \u00fchtse rikke punkti. Kui Kafka kukub, siis protsess seiskub.<\/p>\n<h2>Mis on events-driven API <\/h2>\n<p>\nHea vastus sellele k\u00fcsimusele on Martin Fowleri raportis (GOTO 2017) <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/STKCRSUsyPO\">\u00abThe Many Meanings of Event-Driven Architecture\u00bb<\/a><\/noindex>. <\/p>\n<p>L\u00fchidalt, mida me tegime:<\/p>\n<ol>\n<li>Kaasasime k\u00f5ik as\u00fcnkroonsed vahetused l\u00e4bi <strong>events storage<\/strong>. Selle asemel, et teavitada igat huvitatud tarbijat v\u00f5rgu kaudu staatuse muutumisest, kirjutame kesksete andmete ladudesse s\u00fcndmuse oleku muutumisest ja teemaga huvitatud tarbijad loevad sealt k\u00f5ike, mis seal ilmub.<\/li>\n<li>S\u00fcndmus (event) antud juhul on teade (<strong>teated<\/strong>) selle kohta, et midagi kuskil on muutunud. N\u00e4iteks tellimuse staatuse muutmine. Tarbija, kellele on olulised m\u00f5ned saatmise staatus muutumised ja keda ei teavitata, saab ise nende staatust teada.<\/li>\n<li>Maksimaalne variant on t\u00e4ielik event sourcing, <strong>oleku \u00fclekanne<\/strong>, kus s\u00fcndmus sisaldab kogu infot, mis on vajalik t\u00f6\u00f6tlemiseks: kust ja millisesse olekusse mindi, kuidas t\u00e4pselt andmed muutusid jne. K\u00fcsimus on vaid selle otstarbekuses ja infomahus, mida saate endale lubada salvestada.<\/li>\n<\/ol>\n<p>\nRefund Tooli k\u00e4ivitamise raames kasutasime kolmandat varianti. See lihtsustas s\u00fcndmuste t\u00f6\u00f6tlemist, kuna ei olnud vaja detaile v\u00e4lja kaevata, ja v\u00e4listas stsenaariumi, kus iga uus s\u00fcndmus tekitab tarbijatelt palju t\u00e4psustavaid GET-p\u00e4ringuid.<\/p>\n<p>Refund Tool teenus <strong>ei ole koormatud<\/strong>, seega on Kafka seal pigem katse kui vajadus. Ma ei arva, et kui tagasiside teenus muutuks high-load projektiks, oleks \u00e4ri r\u00f5\u00f5mus.<\/p>\n<h4>Async exchange AS IS<\/h4>\n<p>\nAs\u00fcnkroonsete vahetuste jaoks kasutab PHP osakond tavaliselt RabbitMQ-d. Andmed kogutakse p\u00e4ringu jaoks, asetatakse j\u00e4rjekorda ja selle teenuse tarbija loeb selle \u00fcles ja saadab (v\u00f5i ei saada). API jaoks kasutab Lamoda aktiivselt Swaggerit. Kujundame API, kirjeldame seda Swaggeris, genereerime kliendi- ja serverikoodi. Samuti kasutame veidi laiendatud JSON RPC 2.0. <\/p>\n<p>M\u00f5nes kohas kasutatakse esb-busse, m\u00f5ned elavad activeMQ peal, kuid \u00fcldiselt, <strong>RabbitMQ on standard<\/strong>.<\/p>\n<h4>As\u00fcnkroonne vahetus TO BE<\/h4>\n<p>\nKujundades vahetust events-buse kaudu, on j\u00e4lgitav analoogia. Kirjeldame tulevasi andmevahetusi sarnasel viisil, nagu kirjeldame event'i struktuuri. YAML formaat, koodi genereerimine tuli ise teha, genereerija vastavalt spetsifikatsioonile loob DTO-d ja \u00f5petab kliente ja servereid nendega t\u00f6\u00f6tama. Genereerimine toimub kahele keelele - <strong>golang ja php<\/strong>. See v\u00f5imaldab hoida teeke koosk\u00f5las. Geneerija on kirjutatud golangis, mille t\u00f5ttu sai nimeks gogi.<\/p>\n<p>Event-sourcing Kafka peal on t\u00fc\u00fcpiline asi. On lahendus peamisest ettev\u00f5tteversioonist Kafka Confluent, on <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/nakadi\">nakadi<\/a><\/noindex>, lahendus meie \"vennadelt\" domeeni valdkonnas Zalando. Meie <strong>motiiv alustada vanilla Kafka'ga<\/strong>\u00a0\u2014 see on j\u00e4tta lahendus tasuta, kuni otsustame, kas me kavatseme seda laialdaselt kasutada, samuti j\u00e4tta endale man\u00f6\u00f6verdusruumi ja arendust\u00f6\u00f6d: me soovime oma toetust <strong>JSON RPC 2.0<\/strong>, genereerijad kahe keele jaoks ja vaatame, mis veel. <\/p>\n<p>Ironiseeriv on see, et isegi sellises \u00f5nnelikus olukorras, kus on umbes sarnane ettev\u00f5te Zalando, mis tegi umbes sarnase lahenduse, ei saa me seda t\u00f5husalt kasutada. <\/p>\n<p>Arhitektuuriliselt on k\u00e4ivitamisel muster selline: loeme otse Kafka-st, kuid kirjutame ainult l\u00e4bi events-bus. Kafka-s on palju valmis lahendusi: vahendajad, tasakaalustajad ja see on enam-v\u00e4hem valmis horisontaalseteks skaleerimiseks, mida tahtsime s\u00e4ilitada. Kirjutamine, aga meie soov oli m\u00e4hkida see \u00fche Gateway ehk Events-bus kaudu, ja sellep\u00e4rast.<\/p>\n<h3>Events-bus<\/h3>\n<p>\nV\u00f5i s\u00fcndmuste buss. See on lihtsalt stateless http gateway, mis v\u00f5taks enda kanda mitmeid olulisi rolle:<\/p>\n<ul>\n<li><strong>Produksiooni valideerimine<\/strong>\u00a0\u2014 kontrollime, et s\u00fcndmused vastavad meie spetsifikatsioonile.<\/li>\n<li><strong>S\u00fcndmuste meister-s\u00fcsteem<\/strong>, see, see, see see see \uff0c\u89c1 see \u8fd9\u79cd\u60c5\u51b5\u4e0b\u8fd9\u4e2a \u4ea7\u54c1\u662f . it \u516c\u53f8\u7684\u4e3b\u8981\u548c\u552f\u4e00\u7684\u7cfb\u7edf\uff0c\u5b83\u8d1f\u8d23\u56de\u7b54\u54ea\u4e9b events \u548c\u54ea\u4e9b\u7ed3\u6784\u88ab\u89c6\u4e3a\u5408\u6cd5\u7684\u3002 \u8fd9\u4e2a\u9a8c\u8bc1\u7b80\u5355\u5305\u62ec\u6570\u636e\u7c7b\u578b\u548c enums \u7528\u4e8e\u5185\u5bb9\u7684\u4e25\u683c\u89c4\u8303\u3002 <\/li>\n<li><strong>Hash-funktsioon<\/strong> ja , seal on sharding \u2014 Kafka s\u00f5numi struktuur on key-value ja see arvutab, kuhu see panna, vastavalt key hash'ile.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Miks<\/h3>\n<p>\nTegeleme suure ettev\u00f5ttega, kus on sisset\u00f6\u00f6tatud protsess. Miks peaks midagi muutma? <strong>See on eksperiment<\/strong>, ja me loodame saada mitmeid eeliseid.<\/p>\n<h4>1:n+1 vahetused (\u00fcks-kui-mitmed)<\/h4>\n<p>\nKafka \u00fchendamine uute tarbijatega on v\u00e4ga lihtne. <\/p>\n<p>Oletame, et teil on register, mida tuleb mitmes s\u00fcsteemis korraga ajakohasena hoida (ja m\u00f5nes uues). Varem kasutasime bundlet, mis rakendas set-API-d, ning teatasime peamisele s\u00fcsteemile tarbijate aadressid. N\u00fc\u00fcd saadab peamine s\u00fcsteem v\u00e4rskendusi teemasse ja k\u00f5ik, keda huvitab, loevad seda. Ilmus uus s\u00fcsteem \u2014 registreerisime selle teemasse. Jah, j\u00e4lle bundle, aga lihtsam.<\/p>\n<p>Refund-tool, mis on osa BOB-ist, suudame me lihtsalt l\u00e4bi Kafka neid s\u00fcnkroonida. Payment \u00fctleb, et raha on tagasi antud: BOB ja RT saavad sellest teada, muudavad oma staatuseid, Fiscalization Service saab samuti teada ja v\u00e4ljastab arve.<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/b01b22a333b58e87aeef0c52d40e6960.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMeie plaan on luua \u00fchine Notifications Service, mis teavitaks klienti tema tellimuse\/tagastuste kohta. Praegu on see vastutus hajutatud s\u00fcsteemide vahel. Meie jaoks piisab, kui \u00f5petada Notifications Service'ile Kafka kaudu asjakohast teavet hankima ja sellele reageerima (ja teistes s\u00fcsteemides need teavitused v\u00e4lja l\u00fclitama). Uusi otseseid vahetusi pole vaja.<\/p>\n<h4>Andmep\u00f5hine<\/h4>\n<p>\nTeave s\u00fcsteemide vahel muutub l\u00e4bipaistvaks \u2014 \u00fcksk\u00f5ik kui suur \"verine ettev\u00f5te\" teil on ja kui mahukas teie backlog on. Lamodas on Data Analytics osakond, mis kogub andmeid s\u00fcsteemidelt ja viib need edasi kasutatavasse vormi nii \u00e4ri kui ka intellektuaalsete s\u00fcsteemide jaoks. Kafka v\u00f5imaldab kiiresti neile palju andmeid anda ja hoida seda infovooge ajakohasena.<\/p>\n<h4>Replikatsiooni logi<\/h4>\n<p>\nS\u00f5numid ei kao p\u00e4rast lugemist, nagu RabbitMQ-s. Kui s\u00fcndmus sisaldab piisavalt teavet t\u00f6\u00f6tlemiseks, tekib meil objekti viimaste muudatuste ajalugu ning soovi korral ka v\u00f5imalus neid muudatusi rakendada.<\/p>\n<p>Replikatsioonilogide s\u00e4ilitamise aeg s\u00f5ltub salvestamise intensiivsusest sellele teemale; Kafka v\u00f5imaldab paindlikult seadistada talletamise ajapiire ja andmemahtu. Intensiivsete teemade puhul on oluline, et k\u00f5ik tarbijad suudaksid teavet lugeda enne, kui see kaob, isegi l\u00fchiajalise t\u00f6\u00f6katkestuse korral. Tavaliselt \u00f5nnestub andmeid s\u00e4ilitada\u00a0<strong>p\u00e4evade kaupa<\/strong>, mis on t\u00e4iesti piisav toe jaoks. <\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/0e08dd384155289123ebee96430c2370.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEdasi natuke dokumentatsiooni juttu, neile, kes ei ole Kafka'ga tuttavad (pilt ka dokumentatsioonist)<\/p>\n<p>AMQP-s on j\u00e4rjekorrad: kirjutame s\u00f5numid j\u00e4rjekorda tarbijale. \u00dcldiselt t\u00f6\u00f6tleb \u00fchte j\u00e4rjekorda \u00fcks s\u00fcsteem, millel on sama \u00e4riloogika. Kui on vaja teavitada mitmeid s\u00fcsteeme, saab rakendust \u00f5petada kirjutama mitmesse j\u00e4rjekorda v\u00f5i seadistada vahetus (exchange) fanout-mehhanismiga, mis kopeerib neid automaatselt.<\/p>\n<p>Kafkas on sarnane abstraktsioon <em>teema<\/em>, kuhu saadate s\u00f5numeid, kuid need ei kao p\u00e4rast lugemist. Vaikimisi, kui \u00fchendate Kafka-sse, saate k\u00f5ik s\u00f5numid ja teil on v\u00f5imalus salvestada koht, kus peatusite. See t\u00e4hendab, et loete j\u00e4rjekorras, saate mitte m\u00e4rkida s\u00f5numit loetuks, kuid salvestate id, kust j\u00e4tkate lugemist. Id, kus te peatusite, nimetatakse offsetiks, ja mehhanismiks on commit offset. <\/p>\n<p>Seega on v\u00f5imalik rakendada erinevat loogikat. N\u00e4iteks meie BOB eksisteerib 4 instantsis erinevates riikides \u2014 Lamoda on Venemaal, Kazahstanis, Ukrainas ja Valgevenes. Kuna need paigaldatakse eraldi, on neil veidi oma konfiguratsioonid ja oma \u00e4riloogika. Me m\u00e4\u00e4rame s\u00f5numis, millele riigile see kuulub. Iga BOB tarbija igas riigis loeb erinevate groupId-dega ja kui s\u00f5num ei kuulu tema alla, j\u00e4\u00e4b see vahele, t.j. kommitib kohe offset +1. Kui sama teemat loeb meie Makseteenus, siis teeb ta seda eraldi grupiga ja seet\u00f5ttu offsetid ei kattu.<\/p>\n<p><b>N\u00f5uded s\u00fcndmusele:<\/b><\/p>\n<ul>\n<li><strong>andmete t\u00e4ielikkus. <\/strong>Soovime, et s\u00fcndmusel oleks piisavalt teavet t\u00f6\u00f6tlemiseks. <\/li>\n<\/ul>\n<p><\/p>\n<ul>\n<li><strong>T\u00e4iuslikkus. <\/strong>Me kasutame Events-bus'i, et kontrollida, kas s\u00fcndmus on j\u00e4rjepidev ja kas seda saab t\u00f6\u00f6delda.<\/li>\n<li><strong>J\u00e4rjekord on oluline. <\/strong>Tagastamise korral peame tuginema ajaloole. Teavituste puhul pole j\u00e4rjekord oluline, kuna homogeensetel teavitustel on e-kiri sama, s\u00f5ltumata tellimuse saabumise j\u00e4rjekorrast. Tagastamise korral on protsess selge, ja kui j\u00e4rjekorda muuta, v\u00f5ivad tekkida erandid: tagasimakset ei genereerita ega t\u00f6\u00f6deldud \u2014 me j\u00f5uame teise staadiumisse.<\/li>\n<li><strong>Konsistentsus. <\/strong>Meil on salvestusruum, ja n\u00fc\u00fcd loome me API asemel s\u00fcndmusi. Meil on vaja kiiret ja odavat viisi, kuidas edastada meie teenustele teavet uutest s\u00fcndmustest ja juba olemasolevate muudatustest. See saavutatakse \u00fcldise spetsifikatsiooni kaudu eraldi git-repositooriumis ja koodigeneraatorite abil. Seega on klientide ja serverite \u00fchtsus tagatud erinevates teenustes.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Kafka Lamodas<\/h2>\n<p>\nMeil on kolm Kafka installatsiooni: <\/p>\n<ol>\n<li>Logid;<\/li>\n<li>R&amp;D;<\/li>\n<li>Events-bus.<\/li>\n<\/ol>\n<p>\nT\u00e4na r\u00e4\u00e4gime ainult viimasest punktist. Events-bus'is on meil mitte eriti suured installatsioonid \u2014 3 maaklerit (serverit) ja kokku 27 teemat. \u00dcldiselt on \u00fcks teema \u00fcks protsess. Kuid see on delikaatne k\u00fcsimus ja sellele me peagi j\u00f5uame.<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/f398852689b31429cc97b4cbffcabab5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00dclal on rps graafik. Tagastusprotsess on t\u00e4histatud t\u00fcrkiissinise joonega (jah-jah, see, mis asub X-teljel), ja roosa joonega on sisu v\u00e4rskendamise protsess. <\/p>\n<p>Lamoda kataloog sisaldab miljoneid tooteid, samas kui andmed uuendatakse pidevalt. \u00dched kollektsioonid kaovad moest, nende asemele tulevad uued, kataloogis ilmuvad pidevalt uued mudelid. P\u00fc\u00fcame ennustada, mis v\u00f5ib meie klientidele homme huvi pakkuda, seet\u00f5ttu ostame pidevalt uusi asju, pildistame neid ja uuendame vitriini. <\/p>\n<p>Roosad tipud t\u00e4histavad toote v\u00e4rskendust, see t\u00e4hendab muudatusi toodetes. N\u00e4ha on, et poisid pildistasid, pildistasid ja siis \u00e4kki \u2014 laadisid korraliku koguse s\u00fcndmusi \u00fcles.<\/p>\n<h2>Lamoda s\u00fcndmuste kasutusjuhtumid<\/h2>\n<p>\nEhitatud arhitektuuri kasutame selliste operatsioonide jaoks:<\/p>\n<ul>\n<li><strong>Tagastuste staatuste j\u00e4lgimine<\/strong>: call-to-action ja\u00a0seisundite j\u00e4lgimine k\u00f5ikidest seotud s\u00fcsteemidest. Maksmine, seisundid, fiskaalprobleemid, teavitused. Siin katsetasime l\u00e4henemist, l\u00f5ime t\u00f6\u00f6riistad, kogusime k\u00f5ik vead, kirjutasime dokumentatsiooni ja r\u00e4\u00e4kisime kolleegidele, kuidas seda kasutada.<\/li>\n<li><strong>Toote kaartide v\u00e4rskendamine: <\/strong>konfiguratsioon, metaandmed, omadused. \u00dcks s\u00fcsteem loeb (mis kuvab), mitmed kirjutavad.<\/li>\n<li><strong>Email, push ja sms<\/strong>: tellimus on kogutud, tellimus on kohale j\u00f5udnud, tagastus on aktsepteeritud jne., neid on palju. <\/li>\n<li><strong>Laoseis, laovaru v\u00e4rskendamine<\/strong>\u00a0\u2014 kvantitatiivne v\u00e4rskendamine nimedest, lihtsalt numbrid: laoseis, tagastus. On vajalik, et k\u00f5ik s\u00fcsteemid, mis on seotud kauba reserveerimisega, t\u00f6\u00f6taksid maksimaalselt aktuaalsete andmetega. Praegu on laovaru v\u00e4rskendamine \u00fcsna keeruline, Kafka lihtsustab seda.<\/li>\n<li><strong>Andmeanal\u00fc\u00fcs<\/strong> (R&amp;D-osakond), ML- t\u00f6\u00f6riistad, anal\u00fc\u00fcs, statistika. Soovime, et teave oleks l\u00e4bipaistev \u2014 selleks sobib Kafka h\u00e4sti.<\/li>\n<\/ul>\n<p>\nN\u00fc\u00fcd huvitavam osa vigadest ja huvitavatest avastustest, mis toimusid poole aasta jooksul.<\/p>\n<h2>Disainiprobleemid<\/h2>\n<p>\nOletame, et tahame luua midagi uut \u2014 n\u00e4iteks viia kogu kohaletoimetamise protsess \u00fcle Kafka. Praegu toimub osa protsessist Order Processingus BOBis. Tellimuse edastamine tarneteenusele, liikumine vahepealsesse ladustamisse ja muu on staatuse mudel. Seal on terve monoliit, isegi kaks, pluss palju API-sid, mis on p\u00fchendatud kohaletoimetamisele. Need teavad kohaletoimetamisest palju rohkem. <\/p>\n<p>Tundub, et need on sarnased valdkonnad, kuid Order Processing BOBis ja kohaletoimetamise s\u00fcsteemi staatused erinevad. N\u00e4iteks m\u00f5ned kulleriteenused ei edasta vahepealseid staatusi, vaid ainult l\u00f5plikud: \u201etoimetatud\u201d v\u00f5i \u201ekadunud\u201d. Teised, vastupidi, annavad v\u00e4ga detailselt teavet kauba liikumise kohta. Igal\u00fchel on oma valideerimise reeglid: m\u00f5ne jaoks on e-mail kehtiv, seega t\u00f6\u00f6deldakse seda; teiste jaoks ei ole see kehtiv, kuid tellimust t\u00f6\u00f6deldakse siiski, sest on olemas telefon, mida kasutada, ja m\u00f5ni \u00fctleb, et sellist tellimust ei hakata \u00fcldse t\u00f6\u00f6tlema.<\/p>\n<h3>Andmevoog<\/h3>\n<p>\nKafka puhul kerkib esile andmevoo korraldamise k\u00fcsimus. See \u00fclesanne on seotud strateegia valimisega mitmes punktis, vaatame neid k\u00f5iki l\u00e4bi.<\/p>\n<h4>\u00dchte teemat v\u00f5i erinevatesse?<\/h4>\n<p>\nMeil on s\u00fcndmuse spetsifikatsioon. BOBis kirjutame, et konkreetne tellimus tuleb kohaletoimetada ja n\u00e4itame: tellimuse number, selle sisu, mingid SKU-d ja baarikoodid jne. Kui kaup j\u00f5uab laole, saavad kohaletoimetajad staatuseid, ajatempleid ja k\u00f5ik vajalikud andmed. Siiski tahame BOBis saada nende andmete p\u00f5hjal uuendusi. Meil tekib tagasisideandmete protsess kohaletoimetamisest. Kas see on sama s\u00fcndmus? V\u00f5i on see eraldi vahetus, mis v\u00e4\u00e4rib eraldi teemat?<\/p>\n<p>T\u00f5en\u00e4oliselt on nad v\u00e4ga sarnased ja kiusatus teha \u00fcks teema on p\u00f5hjendatud, kuna eraldi teema t\u00e4hendab eraldi tarbijaid, eraldi seadistusi, eraldi genereerimist. Kuid see ei ole fakt.<\/p>\n<h4>Uus v\u00e4li v\u00f5i uus s\u00fcndmus?<\/h4>\n<p>\nKuid kui kasutada samu s\u00fcndmusi, siis tekib teine probleem. N\u00e4iteks ei suuda k\u00f5ik kohaletoimetamiss\u00fcsteemid genereerida sellist DTO-d, mida BOB suudaks genereerida. Saame neile id, kuid nad ei salvesta neid, kuna need pole neile vajalikud. Siiski on see v\u00e4li vajalik \u00fcrituste bussi protsessi k\u00e4ivitamiseks. <\/p>\n<p>Kui me seame event-bus'i jaoks reegli, et see v\u00e4li on kohustuslik, siis peame BOB-is v\u00f5i algse s\u00fcndmuse t\u00f6\u00f6tlejas seadma t\u00e4iendavad valideerimise reeglid. Valideerimine hakkab levi\u00admass teenuses \u2014 see ei ole v\u00e4ga mugav.<\/p>\n<p>Veel \u00fcks probleem on inclemental arendamise ahvatlus. Meile \u00f6eldakse, et peame s\u00fcndmusele midagi lisama, ja v\u00f5ib-olla, kui h\u00e4sti m\u00f5elda, oleks see pidanud olema eraldi s\u00fcndmus. Kuid meie skeemis on eraldi s\u00fcndmus eraldi teema. Eraldi teema on kogu see protsess, mida ma eespool kirjeldasin. Arendajal on kiusatus lihtsalt lisada JSON skeemile veel \u00fcks v\u00e4li ja uuesti genereerida.<\/p>\n<p>Refundide puhul j\u00f5udsime poole aasta jooksul s\u00fcndmuste s\u00fcndmuseni. Meil oli \u00fcks meta-s\u00fcndmus, mille nimi oli refund update, milles oli v\u00e4li type, mis kirjeldas, milles see uuendus t\u00e4pselt seisneb. Sellega olid meil \"suurep\u00e4rased\" l\u00fclitid valideerijatega, mis \u00fctlesid, kuidas seda s\u00fcndmust selle type'iga valideerida.<\/p>\n<h4>S\u00fcndmuste versioonimine<\/h4>\n<p>\nKafka s\u00f5numite valideerimiseks saab kasutada <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.confluent.io\/current\/schema-registry\/docs\/index.html\">Avro<\/a><\/noindex>, kuid seda pidi kohe arvesse v\u00f5tma ja kasutama Confluent'i. Meie versioonimisjuhtumi puhul tuleb olla ettevaatlik. K\u00f5ikide teateid replication log'ist uuesti lugeda ei pruugi alati \u00f5nnestuda, kuna mudel 'p\u00f5geneb'. Peamiselt \u00f5nnestub ehitada versioone nii, et mudel oleks tagasi \u00fchilduv: n\u00e4iteks v\u00f5ib teha v\u00e4lja ajutiselt mitte kohustuslikuks. Kui erinevused on liiga suured, hakkame kirjutama uude teema ja kliendid vahetavad, kui nad on vana l\u00f5petanud.<\/p>\n<h4>Partitsioonide lugemise j\u00e4rjekorra garantii<\/h4>\n<p>\nKafka sees jagunevad teemad partitsioonideks. See ei ole kuigi oluline seni, kuni projekteerime entiteete ja vahetusi, kuid see on oluline, kui otsustame, kuidas seda tarbida ja skaleerida.<\/p>\n<p>Tavaliselt kirjutate Kafka-sse \u00fche teema. Vaikimisi kasutatakse \u00fchte partition'i, ja k\u00f5ik selle teema s\u00f5numid l\u00e4hevad sinna. Tarbija loeb need s\u00f5numid j\u00e4rjestikku. Oletame, et n\u00fc\u00fcd on vajalik s\u00fcsteemi laiendamine nii, et s\u00f5numeid loeksid kaks erinevat tarbijat. Kui teil n\u00e4iteks saata SMS, siis saate paluda, et Kafka teeks t\u00e4iendava partition'i, ja Kafka hakkab s\u00f5numeid kahe osa peale jagama \u2014 poole sinna, poole t\u00e4nne. <\/p>\n<p>Kuidas Kafka neid jagab? Igal s\u00f5numil on sisu (kus me hoiame JSON-i) ja on olemas key. Sellele v\u00f5tmele saab rakendada hash-funktsiooni, mis m\u00e4\u00e4rab, millisesse partition'i s\u00f5num satub.<\/p>\n<p>Meie puhul, mis puudutab tagasimakseid, on see oluline: kui v\u00f5tame kaks partition'i, on v\u00f5imalus, et paralleelne tarbija t\u00f6\u00f6tleb teise s\u00fcndmuse enne esimest ja see on probleem. Hash-funktsioon tagab, et sama v\u00f5tmega s\u00f5numid satuvad \u00fchte ja samasse partition'i. <\/p>\n<h4>S\u00fcndmused vs k\u00e4sud<\/h4>\n<p>\nSee on veel \u00fcks probleem, millega me silmitsi seisame. \u00dcritus on konkreetne s\u00fcndmus: me r\u00e4\u00e4gime, et midagi kuskil juhtus (something_happened), n\u00e4iteks, et ese t\u00fchistati v\u00f5i toimus tagasimakse. Kui keegi neid s\u00fcndmusi kuulab, siis 'ese t\u00fchistati' loob tagasimakse (refund) entiteedi, ja 'toimus tagasimakse' registreeritakse kuskil seadistustes.<\/p>\n<p>Aga tavaliselt, kui te disainite s\u00fcndmusi, ei taha te neid ju asjata kirjutada \u2014 te loodate, et keegi neid loeb. On suur kiusatus kirjutada mitte something_happened (item_canceled, refund_refunded), vaid something_should_be_done. N\u00e4iteks, ese on tagastamiseks valmis.<\/p>\n<p>\u00dchelt poolt annab see vihje, kuidas s\u00fcndmust hakatakse kasutama. Teiselt poolt, see n\u00e4eb palju v\u00e4hem v\u00e4lja nagu normaalne s\u00fcndmuse nimetus. Lisaks sellele ei ole sellest kaugel ka k\u00e4sk do_something. Kuid teil ei ole garanteeritud, et keegi seda s\u00fcndmust \u00fcldse luges; ja isegi kui luges, siis v\u00f5ib-olla mitte edukalt; ja kui luges edukalt, siis tegi midagi, ja see midagi l\u00e4ks edukalt. Selle hetke jooksul, kui s\u00fcndmus muutub do_something'iks, muutub tagasiside vajalikuks, ja see on probleem.<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/b755d91208092bd9791a41ce4633fb48.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nRabbitMQ as\u00fcnkroonses suhtluses, kui olete s\u00f5numi lugenud, l\u00e4inud HTTP-sse ja saanud vastuse \u2014 v\u00e4hemalt selle, et s\u00f5num on vastu v\u00f5etud. Kui olete Kafka'sse kirja pannud, siis on s\u00f5num, et olete Kafka'sse kirjutanud, kuid selle t\u00f6\u00f6tlemise kohta ei tea te midagi. <\/p>\n<p>Seet\u00f5ttu pidime meie puhul rakendama tagasiside s\u00fcndmuse ja seadistama monitooringu, et kui teatud arv s\u00fcndmusi on v\u00e4lja heidetud, siis mingisuguse aja jooksul peaks tulema sama palju vastavaid s\u00fcndmusi. Kui seda ei juhtunud, siis n\u00e4ib, et midagi l\u00e4ks valesti. N\u00e4iteks, kui me saatsime s\u00fcndmuse \u00abitem_ready_to_refund\u00bb, siis ootame, et tagasimakse luuakse, kliendile tagastatakse raha ja meile tuleb s\u00fcndmus \u00abmoney_refunded\u00bb. Kuid see ei ole kindel, seet\u00f5ttu on monitooring vajalik.<\/p>\n<h3>N\u00fcansid<\/h3>\n<p>\nOn \u00fcsna ilmselge probleem: kui loete j\u00e4rjestikku topikust ja teil on m\u00f5ni halb s\u00f5num, siis tarbija kukub v\u00e4lja ja edasi te ei liigu. Teil on vaja <strong>peatada k\u00f5ik tarbijad<\/strong>, kommitida edasiminek, et edasi lugemist j\u00e4tkata.<\/p>\n<p>Me teadsime sellest, me arvestasime sellega, ja see juhtus ikka. Ja see juhtus sellep\u00e4rast, et s\u00fcndmus oli valideeritud events-bus'i seisukohalt, s\u00fcndmus oli valideeritud rakenduse valideerija seisukohalt, kuid see ei olnud valideeritud PostgreSQL'i seisukohalt, kuna meil oli \u00fches s\u00fcsteemis MySQL, kus oli UNSIGNED INT, ja v\u00e4rskelt kirjutatud s\u00fcsteemis oli PostgreSQL lihtsalt INT. Selle suurus on veidi v\u00e4iksem ja Id ei mahtunud \u00e4ra. Symfony suri erandisse. Loomulikult p\u00fc\u00fcdsime me erandi kinni, kuna olime selle jaoks arvestanud, ja kavas oli kommitida see offset, aga enne seda soovisime probleemide loendit suurendada, kuna s\u00f5num t\u00f6\u00f6tati eba\u00f5nnestunult l\u00e4bi. Loendurid selle projekti jaoks on samuti andmebaasis, kuid Symfony oli juba l\u00f5petanud suhtluse andmebaasiga, ja teine erand tappis kogu protsessi ilma v\u00f5imaluseta offset'i kommitida.<\/p>\n<p>M\u00f5nda aega service seisis - \u00f5nneks, Kafka puhul pole see nii hirmus, kuna s\u00f5numid j\u00e4\u00e4vad alles. Kui t\u00f6\u00f6 taastub, saab neid edasi lugeda. See on mugav.<\/p>\n<p>Kafkal on v\u00f5imalik t\u00f6\u00f6riistade kaudu seada suvaline offset. Kuid selleks, et seda teha, tuleb k\u00f5ik tarbijad peatada \u2014 meie puhul t\u00e4hendab see eraldi v\u00e4ljaande ettevalmistamist, kus ei ole tarbijaid, redeployments. Siis saab Kafkas t\u00f6\u00f6riistade kaudu offseti nihutada ning s\u00f5num l\u00e4bib.<\/p>\n<p>Teine n\u00fcanss \u2014 <strong>replikatsioonilog vs rdkafka.so<\/strong>\u00a0\u2014 on seotud meie projekti spetsiifikaga. Meil on PHP ja PHP-s suhtlevad enamasti k\u00f5ik raamatukogud Kafkaga l\u00e4bi rdkafka.so hoidla, ja edasi tuleb mingisugune wrapper. V\u00f5ib-olla on need meie isiklikud raskused, kuid selgus, et lihtsalt varem loetud osa \u00fcle lugemine ei ole sugugi nii lihtne. Kokkuv\u00f5ttes esines programmeerimisprobleeme.<\/p>\n<p>R\u00e4\u00e4kides partitsioonide t\u00f6\u00f6tamisest, on otse dokumentatsioonis kirjas <strong>tarbijad &gt;= teemade partitsioonid<\/strong>. Kuid ma sain sellest teada palju hiljem, kui oleksin soovinud. Kui soovite skaleeruda ja omada kahte tarbijat, vajate v\u00e4hemalt kahte partitsiooni. See t\u00e4hendab, et kui teil oli \u00fcks partitsioon, kuhu on kogunenud 20 tuhat s\u00f5numit, ja te tegite uue, siis s\u00f5numite arv ei tasandu kohe. Seega, et omada kahte paralleelset tarbimist, tuleb tegeleda partitsioonidega.<\/p>\n<h2>J\u00e4lgimine<\/h2>\n<p>\nArvan, et meie j\u00e4lgimise p\u00f5hjal on veel selgem, millised probleemid esinevad praeguses l\u00e4henemisviisis.<\/p>\n<p>N\u00e4iteks loeme, kui palju kaupu andmebaasis on hiljuti staatust muutnud, ja vastavalt sellele peaks toimuma s\u00fcndmused, ning saadame selle arvu oma j\u00e4lgimisse s\u00fcsteemi. Seej\u00e4rel saame Kafkast teise arvu, kui palju tegelikult s\u00fcndmusi on registreeritud. Ilmselgelt peaks nende kahe arvu vahe olema alati null.<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/07d8ed08514f2fb97d9019466b96342c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLisaks tuleb j\u00e4lgida, kuidas l\u00e4heb producentidel, kas events-bus on s\u00f5numeid vastu v\u00f5tnud, ja kuidas l\u00e4heb tarbijatel. N\u00e4iteks allolevatel diagrammidel on Refund Toolil k\u00f5ik h\u00e4sti, kuid BOB-iga on selgelt probleeme (sinised tipud).<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/57112dbe70d2b388c53f19c34cca6f63.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOlen juba maininud tarbijagruppi viivitust. Teisis\u00f5nu, see on lugemata s\u00f5numite arv. \u00dcldiselt t\u00f6\u00f6tavad meie tarbijad kiiresti, seega on viivitus tavaliselt 0, kuid m\u00f5nikord v\u00f5ivad esineda l\u00fchiajalised tipud. Kafka suudab seda karbis hallata, kuid tuleb m\u00e4\u00e4rata mingisugune intervall. <\/p>\n<p>On projekt <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/linkedin\/Burrow\">Burrow<\/a><\/noindex>, mis annab rohkem teavet Kafka kohta. See tagastab lihtsalt API kaudu consumer-group'i staatuse, kuidas selle grupi asjad edenevad. Lisaks OK ja Failed'on seal ka warning, ja saate teada, et teie tarbijad ei suuda tootmispeed'iga sammu pidada \u2014 ei j\u00f5ua lugeda seda, mis kirjutatakse. S\u00fcsteem on \u00fcsna nutikas, seda on mugav kasutada. <\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/cece8495801e187b155487a802e1a35a.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNii n\u00e4eb v\u00e4lja API vastus. Siin on grupp bob-live-fifa, jagu refund.update.v1, staatuse OK, lag 0 \u2014 viimane l\u00f5plik offset on selline.<\/p>\n<p><img decoding=\"async\" alt=\"Refund Tooli teenuse arendamise kogemus as\u00fcnkroosse API-ga Kafka-l\" src=\"\/wp-content\/uploads\/2019\/04\/1538b2ccc390e9b83075f54566f1039b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nJ\u00e4lgimine <strong>updated_at SLA (kinni j\u00e4\u00e4nud)<\/strong> ma olen juba maininud. N\u00e4iteks, toode on l\u00e4inud staatusele, et see on tagastamiseks valmis. Seame Croni, mis \u00fctleb, et kui selle objekti staatust ei muudetud 5 minuti jooksul refund'iks (tagastame raha makses\u00fcsteemide kaudu v\u00e4ga kiiresti), siis on midagi kindlasti valesti, ja see on kindlasti juhtum, millega tegeleb tugi. Seet\u00f5ttu v\u00f5tame lihtsalt Croni, mis loeb selliseid asju, ja kui need on rohkem kui 0, siis saadab h\u00e4ire.<\/p>\n<p><b>Kokkuv\u00f5tteks, s\u00fcndmuste kasutamine on mugav, kui<\/b>:<\/p>\n<ul>\n<li>teave on vajalik mitmele s\u00fcsteemile;<\/li>\n<li>tulemuse t\u00f6\u00f6tlemine pole oluline;<\/li>\n<li>s\u00fcndmusi on v\u00e4he v\u00f5i s\u00fcndmused on v\u00e4iksed. <\/li>\n<\/ul>\n<blockquote><p>Esmap\u00e4rane, et artikli teema on \u00fcsna konkreetne - as\u00fcnkroonne API Kafka p\u00f5hjal, kuid selle taga on palju soovitusi.<br \/>\nEsiteks, j\u00e4rgmine <noindex><a rel=\"nofollow\" href=\"https:\/\/www.highload.ru\/\">HighLoad++<\/a><\/noindex> ei pea ootama novembrini, juba aprillis on selle Peterburi versioon ja juunis r\u00e4\u00e4gime suurtest koormustest Novosibirskis.<br \/>\nTeiseks, ettekande autor Sergei Zaika kuulub meie uue konverentsi teadmiste haldamise programmkotta <noindex><a rel=\"nofollow\" href=\"https:\/\/knowledgeconf.ru\/2019\">KnowledgeConf<\/a><\/noindex>. Konverents on \u00fchep\u00e4evane ja toimub 26. aprillil, kuid programmil on v\u00e4ga tihe sisu.<br \/>\nJa maikuus toimub <noindex><a rel=\"nofollow\" href=\"https:\/\/phprussia.ru\/2019\">PHP Russia<\/a><\/noindex> ja\u00a0<noindex><a rel=\"nofollow\" href=\"https:\/\/ritfest.ru\/2019\">RIT++<\/a><\/noindex> (DevOpsConfi koosseisus) - sinna saab veel oma teemat pakkuda, r\u00e4\u00e4kida oma kogemusest ja kurtma oma kogetud probleemidest.<\/p><\/blockquote>\n<p>Allikas: <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\/et\/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=\"et_EE\" \/>\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\/et\/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\udd47Kogemus Refund Tool teenuse arendamisest as\u00fcnkroonse API-ga Kafka | ProHoster","description":"Mis v\u00f5iks panna nii suurt ettev\u00f5tet nagu Lamoda, kellel on korralik protsess ja k\u00fcmneid omavahel seotud teenuseid, oluliselt oma l\u00e4henemist muutma? Motivatsioon v\u00f5ib olla t\u00e4iesti erinev: seadusandlikest muudatustest kuni k\u00f5igile programmeerijatele omase katsetamisv\u00f5imeni. Kuid see ei t\u00e4henda, et ei saa loota ka lisakasule. Milles t\u00e4pselt on v\u00f5imalik v\u00f5ita, kui rakendame Kafka-p\u00f5hist events-driven API-d, r\u00e4\u00e4gib Sergei Zaika (fewald). Ta jagab ka oma kogemusi ja huvitavaid avastusi.","canonical_url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/opyt-razrabotki-servisa-refund-tool-s-asinhronnym-api-na-kafka","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"et_EE","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\/et\/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\/et\/wp-json\/wp\/v2\/posts\/30778","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=30778"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/30778\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media\/22763"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=30778"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=30778"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=30778"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}