{"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\/it\/blog\/administrirovanie\/kak-kafka-stala-bylyu","title":{"rendered":"Come Kafka \u00e8 diventata realt\u00e0","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Come Kafka \u00e8 diventata realt\u00e0\" src=\"\/wp-content\/uploads\/2019\/12\/e61bf54b10e4e44a5c680185b0c16655.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ciao, Habr!<\/p>\n<p><\/p>\n<p>Lavoro nel team di Tinkoff che si occupa dello sviluppo del proprio centro di notifiche. Per lo pi\u00f9 sviluppo in Java utilizzando Spring Boot e risolvo vari problemi tecnici che sorgono nel progetto.<\/p>\n<p><\/p>\n<p>La maggior parte dei nostri microservizi interagisce in modo asincrono tra loro tramite un broker di messaggi. In precedenza utilizzavamo IBM MQ come broker, ma ha smesso di poter reggere il carico, pur avendo elevate garanzie di consegna.<\/p>\n<p><\/p>\n<p>Come sostituzione ci \u00e8 stato proposto Apache Kafka, che ha un alto potenziale di scalabilit\u00e0, ma purtroppo richiede un approccio quasi personalizzato alla configurazione per diversi scenari. Inoltre, il meccanismo di consegna almeno una volta, che funziona in Kafka per impostazione predefinita, non permetteva di mantenere il livello di coerenza necessario di default. Di seguito condivider\u00f2 la nostra esperienza di configurazione di Kafka, in particolare parler\u00f2 di come configurare e vivere con la consegna esattamente una volta.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"garantirovannaya-dostavka-i-ne-tolko\">Consegna garantita e non solo<\/h2>\n<p><\/p>\n<p>Le impostazioni di cui parleremo aiuteranno a prevenire una serie di problemi con le impostazioni di connessione predefinite. Ma prima voglio mettere in evidenza un'impostazione che faciliter\u00e0 un eventuale debug.<\/p>\n<p><\/p>\n<p>Questo sar\u00e0 utile per <strong>client.id<\/strong> per il Producer e il Consumer. A prima vista, come valore si pu\u00f2 utilizzare il nome dell'applicazione, e nella maggior parte dei casi funzioner\u00e0. Tuttavia, la situazione in cui un'applicazione utilizza pi\u00f9 Consumer e si assegna lo stesso client.id porta al seguente avviso:<\/p>\n<p><\/p>\n<pre><code class=\"java\">org.apache.kafka.common.utils.AppInfoParser \u2014 Errore nella registrazione dell'AppInfo mbean javax.management.InstanceAlreadyExistsException: kafka.consumer:type=app-info,id=kafka.test-0<\/code><\/pre>\n<p><\/p>\n<p>Se desideri utilizzare JMX in un'applicazione con Kafka, questo potrebbe essere un problema. In questo caso, \u00e8 meglio utilizzare come valore del client.id una combinazione tra il nome dell'applicazione e, ad esempio, il nome del topic. Il risultato della nostra configurazione pu\u00f2 essere visualizzato nell'output del comando <strong>kafka-consumer-groups<\/strong> delle utilit\u00e0 di Confluent:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Come Kafka \u00e8 diventata realt\u00e0\" src=\"\/wp-content\/uploads\/2019\/12\/f807a93f36f262522a613161a549eb91.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ora esaminiamo lo scenario della consegna garantita di un messaggio. Un Kafka Producer ha un'impostazione <strong>acks<\/strong>, che permette di configurare dopo quanti acknowledge il leader del cluster deve considerare il messaggio registrato con successo. Questa impostazione pu\u00f2 assumere i seguenti valori:<\/p>\n<p><\/p>\n<ul>\n<li>0 \u2014 gli acknowledge non verranno conteggiati.<\/li>\n<li>1 \u2014 impostazione predefinita, \u00e8 richiesto l'acknowledge solo da 1 replica.<\/li>\n<li>\u22121 \u2014 sono necessari acknowledge da tutti i replica sincronizzati (configurazione del cluster <strong>min.insync.replicas<\/strong>).<\/li>\n<\/ul>\n<p><\/p>\n<p>Dai valori elencati si pu\u00f2 vedere che un acks pari a \u22121 offre le garanzie pi\u00f9 forti che il messaggio non venga perso. <\/p>\n<p><\/p>\n<p>Come sappiamo, i sistemi distribuiti non sono affidabili. Per proteggersi da guasti temporanei, il Kafka Producer offre il parametro <strong>retries<\/strong>, che consente di definire il numero di tentativi di reinvio entro <strong>delivery.timeout.ms<\/strong>. Poich\u00e9 il parametro retries ha un valore predefinito di Integer.MAX_VALUE (2147483647), il numero di reinvii del messaggio pu\u00f2 essere regolato cambiando solo delivery.timeout.ms.<\/p>\n<p><\/p>\n<h2 id=\"dvizhemsya-k-exactly-once-delivery\">Ci stiamo avvicinando alla consegna exactly once<\/h2>\n<p><\/p>\n<p>Le impostazioni sopra menzionate consentono al nostro Producer di consegnare messaggi con elevata garanzia. Ora parliamo di come garantire la registrazione di una sola copia del messaggio nel topic di Kafka? Nel caso pi\u00f9 semplice, per questo il Producer deve impostare il parametro <strong>enable.idempotence<\/strong> su true. L'idempotenza garantisce la registrazione di un solo messaggio in una specifica partizione di un topic. Le condizioni preliminari per abilitare l'idempotenza sono i valori <strong>acks = all, retry &gt; 0, max.in.flight.requests.per.connection \u2264 5<\/strong>. Se questi parametri non sono specificati dallo sviluppatore, verranno automaticamente impostati i valori sopraindicati.<\/p>\n<p><\/p>\n<p>Quando l'idempotenza \u00e8 configurata, \u00e8 necessario assicurarsi che messaggi identici finiscano sempre nelle stesse partizioni. Questo pu\u00f2 essere fatto configurando la chiave e il parametro partitioner.class sul Producer. Iniziamo dalla chiave. Per ogni invio, deve essere la stessa. Questo \u00e8 facile da realizzare utilizzando un identificatore aziendale del messaggio originale. Il parametro partitioner.class ha come valore predefinito \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>. Con questa strategia di partizionamento predefinita, agiamo in questo modo:<\/p>\n<p><\/p>\n<ul>\n<li>Se la partizione \u00e8 esplicitamente specificata durante l'invio del messaggio, allora la utilizziamo.<\/li>\n<li>Se la partizione non \u00e8 specificata, ma \u00e8 stata fornita una chiave \u2014 scegliamo la partizione in base all'hash della chiave.<\/li>\n<li>Se n\u00e9 la partizione n\u00e9 la chiave sono specificate \u2014 scegliamo le partizioni in modo ciclico (round-robin).<\/li>\n<\/ul>\n<p><\/p>\n<p>Inoltre, l'uso della chiave e l'invio idempotente con il parametro <strong>max.in.flight.requests.per.connection = 1<\/strong> ti offre un'elaborazione ordinata dei messaggi su Consumer. \u00c8 importante ricordare che, se nel tuo cluster \u00e8 configurato il controllo dell'accesso, avrai bisogno dei diritti per la scrittura idempotente nel topic.<\/p>\n<p><\/p>\n<p>Se ti manca la possibilit\u00e0 di inviare in modo idempotente per chiave o se la logica lato Producer richiede di mantenere la coerenza dei dati tra diverse partizioni, le transazioni possono aiutarti. Inoltre, tramite una transazione a catena, puoi sincronizzare condizionalmente una scrittura in Kafka, ad esempio, con una scrittura nel database. Per abilitare l'invio transazionale, il Producer deve essere idempotente e deve anche impostare <strong>transactional.id<\/strong>. Se nel tuo cluster Kafka \u00e8 implementato il controllo dell'accesso, anche per la scrittura transazionale, cos\u00ec come per quella idempotente, saranno necessari diritti di scrittura, che possono essere forniti tramite una maschera utilizzando il valore memorizzato in transactional.id.<\/p>\n<p><\/p>\n<p>Formalmente, qualsiasi stringa pu\u00f2 essere utilizzata come identificatore della transazione, ad esempio il nome dell'applicazione. Tuttavia, se stai eseguendo pi\u00f9 istanze della stessa applicazione con lo stesso transactional.id, la prima istanza avviata verr\u00e0 fermata con un errore, poich\u00e9 Kafka la considerer\u00e0 un processo zombie. <\/p>\n<p><\/p>\n<pre><code class=\"java\">org.apache.kafka.common.errors.ProducerFencedException: Il Producer ha tentato un'operazione con un'epoca precedente. O c'\u00e8 un producer pi\u00f9 recente con lo stesso transactionalId, o la transazione del producer \u00e8 scaduta dal broker.<\/code><\/pre>\n<p><\/p>\n<p>Per risolvere questo problema, aggiungiamo al nome dell'applicazione un suffisso con il nome host ottenuto dalle variabili d'ambiente. <\/p>\n<p><\/p>\n<p>Il Producer \u00e8 configurato, ma le transazioni su Kafka gestiscono solo l'ambito del messaggio. Indipendentemente dallo stato della transazione, il messaggio viene immediatamente inviato nel topic, ma possiede attributi sistemici aggiuntivi.<\/p>\n<p><\/p>\n<p>Affinch\u00e9 tali messaggi non vengano letti dal Consumer prima del tempo, \u00e8 necessario impostare il parametro <strong>isolation.level<\/strong> su read_committed. Questo Consumer potr\u00e0 leggere i messaggi non transazionali come prima, e quelli transazionali solo dopo il commit.<br \/>\nSe hai impostato tutte le configurazioni precedentemente elencate, hai configurato la consegna exactly once. Congratulazioni!<\/p>\n<p><\/p>\n<p>Ma c'\u00e8 un ulteriore aspetto. Il transactional.id, che abbiamo configurato sopra, \u00e8 in realt\u00e0 il prefisso della transazione. Al gestore delle transazioni viene aggiunto un numero di sequenza. L'identificatore risultante viene emesso su <strong>transactional.id.expiration.ms<\/strong>, che \u00e8 configurato su un cluster Kafka e ha un valore predefinito di \u00ab7 giorni\u00bb. Se durante questo periodo l'applicazione non ha ricevuto alcun messaggio, allora tentare la successiva invio transazionale restituir\u00e0 <strong>InvalidPidMappingException<\/strong>. Dopo di che, il coordinatore delle transazioni emetter\u00e0 un nuovo numero di sequenza per la successiva transazione. In questo caso, il messaggio potrebbe andare perso se InvalidPidMappingException non viene gestito correttamente. <\/p>\n<p><\/p>\n<h2 id=\"vmesto-itogov\">Invece dei risultati<\/h2>\n<p><\/p>\n<p>Come puoi notare, non \u00e8 sufficiente inviare messaggi a Kafka. \u00c8 necessario scegliere una combinazione di parametri ed essere pronti a effettuare rapide modifiche. In questo articolo ho cercato di mostrare nel dettaglio la configurazione di exactly once delivery e ho descritto alcuni problemi di configurazione legati a client.id e transactional.id che abbiamo affrontato. Di seguito sono riportate in forma concisa le configurazioni del Producer e del Consumer.<\/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 per l'invio ordinato)<\/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>Per minimizzare gli errori nelle applicazioni future, abbiamo creato un nostro wrapper attorno alla configurazione di spring, dove sono gi\u00e0 impostati i valori per alcuni dei parametri elencati.<\/p>\n<p><\/p>\n<p>Ecco un paio di materiali per lo studio autonomo:<\/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\">Descrizione delle impostazioni <\/a><\/noindex><\/li>\n<\/ul>\n<p>Fonte: <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.1.1 - 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\/it\/blog\/administrirovanie\/kak-kafka-stala-bylyu\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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\/it\/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\udd47Come Kafka \u00e8 diventata realt\u00e0 | ProHoster","description":"Ciao, Habr! Lavoro nel team di Tinkoff.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-kafka-stala-bylyu","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/54431","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=54431"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/54431\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=54431"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=54431"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=54431"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}