{"id":54431,"date":"2019-12-26T00:00:00","date_gmt":"2019-12-25T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/kak-kafka-stala-bylyu"},"modified":"2020-02-18T14:02:26","modified_gmt":"2020-02-18T11:02:26","slug":"kak-kafka-stala-bylyu","status":"publish","type":"post","link":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-kafka-stala-bylyu","title":{"rendered":"Kako je Kafka postala stvarnost","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Kako je Kafka postala stvarnost\" src=\"\/wp-content\/uploads\/2019\/12\/e61bf54b10e4e44a5c680185b0c16655.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Bok, Habr!<\/p>\n<p><\/p>\n<p>Radim u timu Tinkoff koji se bavi razvojem vlastitog centra za obavijesti. Ve\u0107inom programiram u Javi koriste\u0107i Spring Boot i rje\u0161avam razne tehni\u010dke probleme koji se pojavljuju u projektu.<\/p>\n<p><\/p>\n<p>Ve\u0107ina na\u0161ih mikroservisa asinkrono me\u0111usobno komunicira putem posrednika poruka. Ranije smo koristili IBM MQ kao posrednika, koji je prestao odolijevati optere\u0107enju, iako je imao visoka jamstva isporuke.<\/p>\n<p><\/p>\n<p>Kao zamjenu nam je predlo\u017een Apache Kafka, koja ima visoki potencijal za skaliranje, ali na\u017ealost zahtijeva gotovo individualni pristup konfiguraciji za razli\u010dite scenarije. Osim toga, mehanizam 'at least once delivery', koji radi u Kafki prema defaultu, nije omogu\u0107avao odr\u017eavanje potrebnog nivoa konzistentnosti iz kutije. U nastavku \u0107u podijeliti na\u0161e iskustvo s konfiguracijom Kafke, a posebno \u0107u opisati kako postaviti i \u017eivjeti s 'exactly once delivery'.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"garantirovannaya-dostavka-i-ne-tolko\">Jam\u010dena isporuka i ne samo to<\/h2>\n<p><\/p>\n<p>Parametri o kojima \u0107emo govoriti dalje \u0107e pomo\u0107i u sprje\u010davanju niza problema s postavkama povezivanja prema zadanim postavkama. No prvo bih \u017eelio obratiti pa\u017enju na jedan parametar koji \u0107e olak\u0161ati mogu\u0107u dijagnostiku.<\/p>\n<p><\/p>\n<p>U tome \u0107e pomo\u0107i <strong>client.id<\/strong> za Producer i Consumer. Na prvi pogled, kao vrijednost se mo\u017ee koristiti ime aplikacije, i u ve\u0107ini slu\u010dajeva to \u0107e funkcionirati. Me\u0111utim, situacija kada aplikacija koristi vi\u0161e Consumer-a i za njih postavljate isti client.id dovodi do sljede\u0107e upozorenja:<\/p>\n<p><\/p>\n<pre><code class=\"java\">org.apache.kafka.common.utils.AppInfoParser \u2014 Gre\u0161ka pri registraciji AppInfo mbean javax.management.InstanceAlreadyExistsException: kafka.consumer:type=app-info,id=kafka.test-0<\/code><\/pre>\n<p><\/p>\n<p>Ako \u017eelite koristiti JMX u aplikaciji s Kafkom, to mo\u017ee predstavljati problem. U tom slu\u010daju najbolje je koristiti kombinaciju imena aplikacije i, na primjer, imena topica kao vrijednost client.id. Rezultat na\u0161e konfiguracije mo\u017eete vidjeti u izlazu komande <strong>kafka-consumer-groups<\/strong> iz Confluentovih alata:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Kako je Kafka postala stvarnost\" src=\"\/wp-content\/uploads\/2019\/12\/f807a93f36f262522a613161a549eb91.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sada \u0107emo razmotriti scenarij jam\u010dene isporuke poruke. Kafka Producer ima parametar <strong>acks<\/strong>, koji omogu\u0107ava postavljanje nakon koliko potvrda lideru klastera treba smatrati poruku uspje\u0161no zapisanu. Ovaj parametar mo\u017ee imati sljede\u0107e vrijednosti:<\/p>\n<p><\/p>\n<ul>\n<li>0 \u2014 potvrde se ne\u0107e ra\u010dunati.<\/li>\n<li>1 \u2014 parametar po defaultu, potrebna je potvrda samo od 1 replike.<\/li>\n<li>\u22121 \u2014 zahtijevaju se acknowledge od svih sinkroniziranih replika (konfiguracija klastera <strong>min.insync.replicas<\/strong>).<\/li>\n<\/ul>\n<p><\/p>\n<p>Iz navedenih vrijednosti jasno je da acks jednako \u22121 pru\u017ea najja\u010de garancije da poruka ne\u0107e biti izgubljena. <\/p>\n<p><\/p>\n<p>Kao \u0161to svi znamo, distribuirani sustavi nisu pouzdani. Kako bismo se za\u0161titili od povremenih kvarova, Kafka Producer nudi parametar <strong>retries<\/strong>, koji omogu\u0107uje postavljanje broja poku\u0161aja ponovnog slanja tijekom <strong>delivery.timeout.ms<\/strong>. Budu\u0107i da parametar retries ima zadanu vrijednost Integer.MAX_VALUE (2147483647), broj ponovnih slanja poruke mo\u017ee se regulirati promjenom samo delivery.timeout.ms.<\/p>\n<p><\/p>\n<h2 id=\"dvizhemsya-k-exactly-once-delivery\">Idemo prema exactly once delivery<\/h2>\n<p><\/p>\n<p>Navedene postavke omogu\u0107uju na\u0161em Produceru da dostavlja poruke s visokom garancijom. Sada razgovarajmo o tome kako osigurati da se samo jedna kopija poruke zapi\u0161e u Kafka-topik? U najjednostavnijem slu\u010daju, za to treba postaviti parametar <strong>enable.idempotence<\/strong> na true. Idempotentnost jam\u010di da se samo jedna poruka zapise u odre\u0111enu particiju jednog topika. Preduvjet za uklju\u010divanje idempotentnosti su vrijednosti <strong>acks = all, retry &gt; 0, max.in.flight.requests.per.connection \u2264 5<\/strong>. Ako ovi parametri nisu postavljeni od strane programera, automatski \u0107e se postaviti navedene vrijednosti.<\/p>\n<p><\/p>\n<p>Kada je idempotentnost postavljena, potrebno je osigurati da iste poruke svaki put zavr\u0161e u istim particijama. To se mo\u017ee posti\u0107i konfiguriranjem klju\u010da i parametra partitioner.class na Produceru. Zapo\u010dnimo s klju\u010dem. Za svako slanje mora biti isti. To se lako posti\u017ee kori\u0161tenjem bilo kojeg poslovnog identifikatora iz originalne poruke. Parametar partitioner.class ima zadanu vrijednost \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/apache\/kafka\/blob\/trunk\/clients\/src\/main\/java\/org\/apache\/kafka\/clients\/producer\/internals\/DefaultPartitioner.java\">DefaultPartitioner<\/a><\/noindex>. Pri ovoj strategiji particioniranja prema zadanim postavkama djelujemo ovako:<\/p>\n<p><\/p>\n<ul>\n<li>Ako je particija izri\u010dito navedena prilikom slanja poruke, koristimo je.<\/li>\n<li>Ako particija nije navedena, ali je naveden klju\u010d \u2014 biramo particiju prema he\u0161iranju od klju\u010da.<\/li>\n<li>Ako particija i klju\u010d nisu navedeni \u2014 biramo particije naizmjeni\u010dno (round-robin).<\/li>\n<\/ul>\n<p><\/p>\n<p>Osim toga, kori\u0161tenje klju\u010da i idempotentnog slanja s parametrima <strong>max.in.flight.requests.per.connection = 1<\/strong> pru\u017ea vam strukturiranu obradu poruka na Consumeru. Tako\u0111er je va\u017eno napomenuti da, ako je na va\u0161em klasteru postavljena kontrola pristupa, trebate imati prava za idempotentno pisanje u temu.<\/p>\n<p><\/p>\n<p>Ako vam nedostaje mogu\u0107nosti idempotentnog slanja po klju\u010devoj ili logika na strani Producenta zahtijeva o\u010duvanje dosljednosti podataka izme\u0111u razli\u010ditih particija, tu su transakcije kao pomo\u0107. Osim toga, putem lan\u010dane transakcije mo\u017eete uvjetno sinkronizirati zapis u Kafki, na primjer, sa zapisom u bazi podataka. Da biste uklju\u010dili transakcijsko slanje na Producentu, potrebno je da on ima idempotentnost i dodatno postaviti <strong>transactional.id<\/strong>. Ako je na va\u0161em Kafka klasteru postavljena kontrola pristupa, tada su, kao i za idempotentno, potrebna prava za pisanje koja se mogu dodijeliti putem maske koriste\u0107i vrijednost pohranjenu u transactional.id.<\/p>\n<p><\/p>\n<p>Formalno kao identifikator transakcije mo\u017eete koristiti bilo koji niz, kao \u0161to je ime aplikacije. No, ako pokre\u0107ete nekoliko instancija jedne aplikacije s istim transactional.id, prva pokrenuta instanca \u0107e biti zaustavljena s gre\u0161kom, jer \u0107e Kafka smatrati da je to zombirani proces. <\/p>\n<p><\/p>\n<pre><code class=\"java\">org.apache.kafka.common.errors.ProducerFencedException: Producent je poku\u0161ao izvr\u0161iti operaciju sa starom epohom. Ili postoji noviji producent s istim transactionalId, ili je transakcija producenta istekla od strane poslu\u017eitelja.<\/code><\/pre>\n<p><\/p>\n<p>Da bismo rije\u0161ili ovaj problem, dodajemo sufiks imenu aplikacije u obliku naziva hosta koji dobivamo iz varijabli okru\u017eenja. <\/p>\n<p><\/p>\n<p>Producent je postavljen, ali transakcije na Kafki upravljaju samo podru\u010djem vidljivosti poruke. Bez obzira na status transakcije, poruka odmah ulazi u temu, ali ima dodatne sistemske atribute.<\/p>\n<p><\/p>\n<p>Da takve poruke ne bi bile o\u010ditane od strane Consumer-a prerano, potrebno je postaviti parametar <strong>isolation.level<\/strong> na vrijednost read_committed. Takav Consumer mo\u0107i \u0107e \u010ditati netransakcijske poruke kao i dosad, a transakcijske samo nakon potvrde.<br \/>\nAko ste postavili sve prethodno navedene postavke, postavili ste exactly once delivery. \u010cestitam!<\/p>\n<p><\/p>\n<p>Ali postoji jo\u0161 jedan detalj. Transactional.id, koji smo postavili ranije, zapravo je prefiks transakcije. Na upravitelju transakcija dodaje se redni broj. Dobiveni identifikator se izdaje na <strong>transactional.id.expiration.ms<\/strong>, koji se konfigurira na Kafka klasteru i ima zadanu vrijednost \u201e7 dana\u201d. Ako tijekom tog vremena aplikacija nije primila nikakve poruke, prilikom sljede\u0107e transakcijske po\u0161iljke dobit \u0107ete <strong>InvalidPidMappingException<\/strong>. Nakon toga koordinator transakcija dodijelit \u0107e novi redni broj za sljede\u0107u transakciju. Pri tome poruka mo\u017ee biti izgubljena ako se InvalidPidMappingException ne obra\u0111uje ispravno. <\/p>\n<p><\/p>\n<h2 id=\"vmesto-itogov\">Umjesto zaklju\u010daka<\/h2>\n<p><\/p>\n<p>Kao \u0161to se mo\u017ee primijetiti, nije dovoljno samo slati poruke u Kafka-u. Potrebno je odabrati kombinaciju parametara i biti spreman na brze promjene. U ovom \u010dlanku nastojao sam detaljno prikazati postavke exactly once delivery i opisati nekoliko problema s konfiguracijama client.id i transactional.id s kojima smo se susreli. U nastavku su u kratkom obliku navedene postavke Producer-a i Consumer-a.<\/p>\n<p><\/p>\n<p>Producer:<\/p>\n<p><\/p>\n<ol>\n<li>acks = all<\/li>\n<li>retries &gt; 0<\/li>\n<li>enable.idempotence = true<\/li>\n<li>max.in.flight.requests.per.connection \u2264 5 (1 \u2014 za ure\u0111eno slanje)<\/li>\n<li>transactional.id = ${application-name}-${hostname}<\/li>\n<\/ol>\n<p><\/p>\n<p>Consumer:<\/p>\n<p><\/p>\n<ol>\n<li>isolation.level = read_committed<\/li>\n<\/ol>\n<p><\/p>\n<p>Kako bismo umanjili gre\u0161ke u budu\u0107im aplikacijama, izradili smo vlastitu oblogu nad spring-konfiguracijom, gdje su ve\u0107 postavljene vrijednosti za neke od navedenih parametara.<\/p>\n<p><\/p>\n<p>Evo nekoliko materijala za samostalno u\u010denje:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/cwiki.apache.org\/confluence\/display\/KAFKA\/KIP-98+-+Exactly+Once+Delivery+and+Transactional+Messaging\">KIP-98 \u2014 Exactly Once Delivery and Transactional Messaging<\/a><\/noindex> <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/kafka.apache.org\/documentation\/#configuration\">Opis postavki <\/a><\/noindex><\/li>\n<\/ul>\n<p>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/tinkoff\/blog\/481784\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 Tinkoff, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u043d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439. \u041f\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u044f \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e \u043d\u0430 Java \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Spring boot \u0438 \u0440\u0435\u0448\u0430\u044e \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0449\u0438\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435. \u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043d\u0430\u0448\u0438\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u0431\u0440\u043e\u043a\u0435\u0440 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0420\u0430\u043d\u0435\u0435 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0440\u043e\u043a\u0435\u0440\u0430 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 IBM MQ, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0441 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-54431","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.5 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 Tinkoff.\" \/>\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\/hr\/blog\/administrirovanie\/kak-kafka-stala-bylyu\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.5\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\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\u041a\u0430\u043a Kafka \u0441\u0442\u0430\u043b\u0430 \u0431\u044b\u043b\u044c\u044e | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 Tinkoff.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-kafka-stala-bylyu\" \/>\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-12-25T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:02:26+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\udd47 Kako je Kafka postala stvarnost | ProHoster","description":"Pozdrav, Habr! Radim u timu Tinkoff.","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-kafka-stala-bylyu","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"hr_HR","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\u041a\u0430\u043a Kafka \u0441\u0442\u0430\u043b\u0430 \u0431\u044b\u043b\u044c\u044e | ProHoster","og:description":"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 Tinkoff.","og:url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-kafka-stala-bylyu","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-12-25T21:00:00+00:00","article:modified_time":"2020-02-18T11:02:26+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"54431","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-24 11:22:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:06:37","updated":"2026-01-24 11:22:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/54431","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=54431"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/54431\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=54431"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=54431"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=54431"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}