{"id":147,"date":"2024-07-20T17:23:39","date_gmt":"2024-07-20T20:23:39","guid":{"rendered":"https:\/\/alice.com.br\/tech\/sem-categoria\/descomplicando-o-apache-kafka\/"},"modified":"2026-01-22T10:42:22","modified_gmt":"2026-01-22T13:42:22","slug":"descomplicando-o-apache-kafka","status":"publish","type":"post","link":"https:\/\/alice.com.br\/tech\/descomplicando-o-apache-kafka\/","title":{"rendered":"Descomplicando o Apache Kafka"},"content":{"rendered":"<h2>Introdu\u00e7\u00e3o<\/h2>\n<p>Na Alice, temos a <a href=\"https:\/\/medium.com\/alice-tech\/como-tomamos-decis%C3%B5es-860121def07f\">cultura de tomada de decis\u00f5es em conjunto<\/a> para assuntos que impactem a engenharia como um todo. Isso sendo desde a defini\u00e7\u00e3o da <a href=\"https:\/\/medium.com\/alice-tech\/flutter-eu-escolho-voc%C3%AA-83ef5ee5c4a3?source=---------5-----------------------\">tecnologia a ser usada para desenvolvimento mobile<\/a>, at\u00e9 a arquitetura de processamento ass\u00edncrono dos servi\u00e7os (spoiler: ela \u00e9 baseada em\u00a0Kafka).<\/p>\n<p>Mas antes de contar como e porque escolhemos o Kafka, vale uma n\u0336\u00e3\u0336o\u0336 \u0336t\u0336\u00e3\u0336o\u0336 breve introdu\u00e7\u00e3o sobre\u00a0ele.<\/p>\n<h2><strong>O que \u00e9 o Apache\u00a0Kafka?<\/strong><\/h2>\n<p>Resumidamente, o Kafka pode ser definido como um sistema de processamento de stream de dados em tempo real \/ um sistema de mensageria (messaging system) publish-subscribe distribu\u00eddo.<\/p>\n<p>Ele possui como principais caracter\u00edsticas\u200a\u2014\u200ase comparado com outros sistemas de mensageria\u200a\u2014\u200aum alto throughput, clusteriza\u00e7\u00e3o no DNA (permitindo escalabilidade horizontal), ordenamento e persist\u00eancia de mensagens com estrutura de disco O(1) (entraremos em mais detalhes sobre o que isto representa).<\/p>\n<h2><strong>O que \u00e9 um sistema de mensageria?<\/strong><\/h2>\n<p>Um sistema de mensageria nada mais \u00e9 do que uma forma de comunica\u00e7\u00e3o ass\u00edncrona entre duas (ou mais) aplica\u00e7\u00f5es. Neste conceito, as aplica\u00e7\u00f5es se comunicam atrav\u00e9s de uma fila (message queue), de forma totalmente desacoplada, onde o produtor da mensagem (producer) n\u00e3o tem conhecimento de quem a processar\u00e1, assim como o consumidor (consumer) tamb\u00e9m n\u00e3o possui ci\u00eancia de quem a produziu. Ambas as pontas apenas se preocupam com o conte\u00fado da mensagem.<\/p>\n<p>Existem dois tipos de padr\u00f5es de mensageria: ponta \u00e0 ponta (point to point) e publish-subscribe (pub-sub).<\/p>\n<h3><strong>Sistema de mensageria ponta \u00e0\u00a0ponta<\/strong><\/h3>\n<p>Um sistema de mensageria ponta \u00e0 ponta \u00e9 caracterizado pelo fato de que cada mensagem apenas poder ser consumida uma \u00fanica vez. Neste sistema, a mensagem \u00e9 persistida na fila e, a partir do momento que um consumidor l\u00ea esta mensagem, ela \u00e9 automaticamente removida da fila. Exemplos de sistemas neste modelo temos o Amazon Simple Queue Service (SQS) e o Microsoft Message Queuing\u00a0(MSMQ).<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/454\/0*jdcRsgpQHczaw322\" alt=\"(Fig. 1: Ilustra\u00e7\u00e3o de fila ponta \u00e0 ponta. https:\/\/docs.oracle.com\/cd\/E19340-01\/820-6424\/aerbj\/index.html)\" \/><figcaption>(Fig. 1: Ilustra\u00e7\u00e3o de fila ponta \u00e0 ponta. <a href=\"https:\/\/docs.oracle.com\/cd\/E19340-01\/820-6424\/aerbj\/index.html\">https:\/\/docs.oracle.com\/cd\/E19340-01\/820-6424\/aerbj\/index.html<\/a>)<\/figcaption><\/figure>\n<h3><strong>Sistema de mensageria publish-subscribe<\/strong><\/h3>\n<p>No sistema de mensageria publish-subscribe assim como no de ponta \u00e0 ponta, as mensagens s\u00e3o persistidas em uma fila atrav\u00e9s de um produtor (publisher). Por\u00e9m, diferentemente do modelo anterior, os consumidores podem se inscrever\/assinar (subscribe) \u00e0 uma ou mais filas e consumir todas as mensagens destas filas. Neste modelo, todos os consumidores (subscribers) processam todas as mensagens de todas as filas no qual eles se inscreveram. Exemplos de sistemas neste modelo temos o RabbitMQ e o Apache\u00a0Kafka.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/395\/0*KxH9m3CA5A9EHi2Q\" alt=\"\" \/><figcaption>(Fig. 2: Ilustra\u00e7\u00e3o de fila pub-sub. <a href=\"https:\/\/docs.oracle.com\/cd\/E19340-01\/820-6424\/aerbk\/index.html\">https:\/\/docs.oracle.com\/cd\/E19340-01\/820-6424\/aerbk\/index.html<\/a>)<\/figcaption><\/figure>\n<h2><strong>Background<\/strong><\/h2>\n<h3><strong>Hist\u00f3ria<\/strong><\/h3>\n<p>Tudo come\u00e7ou em meados de 2010, com uma necessidade do LinkedIn: integra\u00e7\u00e3o massiva de dados. Um volume enorme de dados era gerado a todo tempo, por\u00e9m, com as ferramentas existentes na \u00e9poca, n\u00e3o era poss\u00edvel integrar e centralizar estes dados da forma que gostariam e com a escala que precisavam.<\/p>\n<p>Foi ent\u00e3o que <a href=\"https:\/\/twitter.com\/jaykreps\">Jay Kreps<\/a> e sua equipe surgiram com o conceito do\u00a0Kafka.<\/p>\n<h3><strong>Timeline<\/strong><\/h3>\n<p>Em 2011 tornou-se um projeto open-source, sendo absolvido pela Apache Foundation em\u00a02012.<\/p>\n<p>Em 2014, os engenheiros do LinkedIn respons\u00e1veis pelo desenvolvimento do Kafka fundaram a <a href=\"https:\/\/www.confluent.io\/\">Confluent<\/a>, empresa com foco em\u00a0Kafka.<\/p>\n<h3><strong>Fun fact<\/strong><\/h3>\n<p>Kafka \u00e9 desenvolvido em Scala e Java, e seu nome \u00e9 uma refer\u00eancia ao escritor alem\u00e3o <a href=\"https:\/\/pt.wikipedia.org\/wiki\/Franz_Kafka\">Franz Kafka<\/a>. Jay diz que a escolha do nome se deu ao fato de que, devido o Kafka ser um sistema otimizado para escrita, faria sentido ter o nome de um escritor. Al\u00e9m de achar que <a href=\"https:\/\/www.quora.com\/What-is-the-relation-between-Kafka-the-writer-and-Apache-Kafka-the-distributed-messaging-system\">soava bem para um projeto open\u00a0source<\/a>.<\/p>\n<h2><strong>Mas por que utilizar\u00a0Kafka?<\/strong><\/h2>\n<p>Dentre as principais vantagens do Kafka, podemos destacar:<\/p>\n<ul>\n<li><strong>Sistema de registros:<\/strong> ap\u00f3s persistido, um registro (mensagem) nunca mais \u00e9 mais removido do log (por padr\u00e3o). Desta forma, \u00e9 poss\u00edvel \u201cvoltar no tempo\u201d e reprocessar todas as mensagens a partir de uma data espec\u00edfica.<\/li>\n<li><strong>Ordenamento garantido<\/strong>: ao ser publicada a mensagem A (POST) e ent\u00e3o a B (PUT), sempre ser\u00e3o retornadas e lidas nesta mesma ordem\u00a0(FIFO).<\/li>\n<li><strong>Centraliza\u00e7\u00e3o<\/strong>: uma mesma mensagem pode servir de input para uma opera\u00e7\u00e3o SQL e para um registro em um Data\u00a0Lake.<\/li>\n<li><strong>Escalabilidade<\/strong>: Kafka \u00e9 totalmente pensado em clusteriza\u00e7\u00e3o e escalabilidade horizontal.<\/li>\n<li><strong>Pull over Push<\/strong>: diferentemente de outros sistemas de mensageria (e.g. RabbitMQ) e\/ou sistemas de service bus, o Kafka trabalha com um modelo de pulling ao inv\u00e9s de pushing, no qual o consumidor tem de solicitar ativamente a leitura de novas mensagens. Isto possibilita a exist\u00eancia de consumers com velocidades de processamento distintas entre\u00a0si.<\/li>\n<li><strong>Performance<\/strong>: possui um alto throughput, comportando centenas de milhares de mensagens\/seg at\u00e9 em hardwares mais modestos. Como citado anteriormente, possui persist\u00eancia de mensagens com estrutura de disco <a href=\"https:\/\/pt.wikipedia.org\/wiki\/Grande-O\">O(1)<\/a>, ou seja, n\u00e3o importa a quantidade de mensagens existentes, a velocidade de escrita sempre se mant\u00e9m a\u00a0mesma.<\/li>\n<\/ul>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/600\/0*Z4U-ueC2dpCSdLIh\" alt=\"\" \/><figcaption>(Fig 3: Ilustra\u00e7\u00e3o de representa\u00e7\u00e3o do\u00a0Kafka)<\/figcaption><\/figure>\n<h3><strong>Performance linear<\/strong><\/h3>\n<p>Devido a arquitetura de distribui\u00e7\u00e3o que o Kafka implementa, \u00e9 poss\u00edvel obtermos escalabilidade linear em nosso sistema. Desta forma, para cada n\u00f3 (broker) adicionado ao cluster, teremos um aumento linear de throughput suportado pelo\u00a0Kafka.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/600\/0*4htqnFHKombtAbFr\" alt=\"\" \/><figcaption>(Fig. 4: Gr\u00e1fico de aumento do throughput do Kafka para cada n\u00f3 adicionado no Cluster. <a href=\"https:\/\/www.slideshare.net\/r39132\/linkedin-data-infrastructure-qcon-london-2012\/38-Kafka_Performance_Linear_Incremental_Scalability\">https:\/\/www.slideshare.net\/r39132\/linkedin-data-infrastructure-qcon-london-2012\/38-Kafka_Performance_Linear_Incremental_Scalability<\/a>)<\/figcaption><\/figure>\n<h3><strong>Use cases<\/strong><\/h3>\n<p>Mesmo o Kafka sendo extremamente vers\u00e1til, existem alguns casos de uso no qual acaba se destacando. Tais\u00a0como:<\/p>\n<ul>\n<li><strong>Hub de eventos<\/strong>: Kafka pode servir de um hub centralizador dos eventos da sua aplica\u00e7\u00e3o, permitindo que inputs de diversas fontes de dados sejam concentrados em um \u00fanico ponto, para ent\u00e3o serem potencialmente filtrados, transformados e processados de formas distintas.<\/li>\n<li><strong>Data pipeline<\/strong>: um dado pode ser persistido no Kafka para ent\u00e3o ser replicado para outros reposit\u00f3rios, tais como banco de\u00a0dados.<\/li>\n<li><strong>Entry point de Big Data<\/strong>: em casos de utiliza\u00e7\u00e3o de data lakes baseados em storages na nuvem (e.g. AWS S3), Kafka costuma servir como um \u201cbuffer\u201d dos dados devido ao seu throughput, armazenando-os at\u00e9 serem transferidos para o storage\u00a0final.<\/li>\n<\/ul>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/851\/0*4LdPngQKdZbeRF1L\" alt=\"\" \/><figcaption>(Fig. 5: Ilustra\u00e7\u00e3o Kafka operando como um hub de eventos. <a href=\"https:\/\/www.confluent.io\/\">https:\/\/www.confluent.io\/<\/a>)<\/figcaption><\/figure>\n<h2><strong>Sem\u00e2nticas<\/strong><\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/481\/0*TfavmQXnGDlvnvva\" alt=\"\" \/><figcaption>(Fig. 6: Representa\u00e7\u00e3o visual dos fundamentos do Kafka. <a href=\"https:\/\/www.confluent.io\/\">https:\/\/www.confluent.io\/<\/a>)<\/figcaption><\/figure>\n<h3><strong>Registros<\/strong><\/h3>\n<p>Os registros (records) s\u00e3o as mensagens persistidas em uma fila (t\u00f3pico). Um registro \u00e9 composto de tr\u00eas componentes: chave, valor e timestamp.<\/p>\n<p>A chave (key) \u00e9 o que define em qual parti\u00e7\u00e3o este registro ser\u00e1 armazenado (mais detalhes sobre particionamento abaixo). A chave n\u00e3o \u00e9 obrigat\u00f3ria e, caso n\u00e3o seja fornecida, o Kafka se encarregar\u00e1 de definir a parti\u00e7\u00e3o correta para este registro.<\/p>\n<p>O valor (value) \u00e9 o conte\u00fado do registro, o equivalente ao corpo de uma mensagem. O valor pode conter qualquer dado, desde uma simples string at\u00e9 um objeto serializado em\u00a0JSON.<\/p>\n<p>O timestamp \u00e9 a data e hora no qual o registro foi persistido, sendo atribu\u00eddo automaticamente pelo Kafka no momento da cria\u00e7\u00e3o do registro.<\/p>\n<p>O registro \u00e9 sempre imut\u00e1vel e append-only, ou seja, somente \u00e9 poss\u00edvel incluir novos registros. Uma vez inclu\u00eddo n\u00e3o pode mais ser modificado ou removido.<\/p>\n<p>Os registros s\u00e3o sempre persistidos em disco, n\u00e3o havendo nenhum cache em mem\u00f3ria, tanto para escrita quanto para\u00a0leitura.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/600\/0*r1v6MYiYKT5H23IY\" alt=\"\" \/><figcaption>(Fig. 7: Registros do Kafka em um log (parti\u00e7\u00e3o de um t\u00f3pico). <a href=\"https:\/\/www.confluent.io\/\">https:\/\/www.confluent.io\/<\/a>)<\/figcaption><\/figure>\n<h3><strong>Producer e\u00a0Consumer<\/strong><\/h3>\n<p>O producer \u00e9 quem ser\u00e1 respons\u00e1vel por gerar registros em um t\u00f3pico e o consumer por ler estes registros. Em ambos os casos, a comunica\u00e7\u00e3o \u00e9 sempre feita com o broker (n\u00f3) l\u00edder do\u00a0cluster.<\/p>\n<p>Ao ler um registro, o consumer pode tanto solicitar o \u00faltimo n\u00e3o lido, quanto a partir de uma posi\u00e7\u00e3o espec\u00edfica.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/528\/0*qfGkKK_Yx2rlZ16K\" alt=\"\" \/><figcaption>(Fig. 8: Diagrama producer\/consumer de um cluster Kafka. <a href=\"https:\/\/www.confluent.io\/\">https:\/\/www.confluent.io\/<\/a>)<\/figcaption><\/figure>\n<h3><strong>T\u00f3picos<\/strong><\/h3>\n<p>O t\u00f3pico \u00e9 a nomenclatura l\u00f3gica para uma ou mais parti\u00e7\u00f5es. Basicamente \u00e9 onde os registros ficam armazenados, sendo equivalente \u00e0 uma fila, por\u00e9m considerando todas as parti\u00e7\u00f5es do\u00a0cluster.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/416\/0*4XODBKLqrQpMNOPx\" alt=\"\" \/><figcaption>(Fig. 9: Representa\u00e7\u00e3o de um t\u00f3pico do Kafka e suas parti\u00e7\u00f5es. <a href=\"https:\/\/www.confluent.io\/\">https:\/\/www.confluent.io\/<\/a>)<\/figcaption><\/figure>\n<h3><strong>Parti\u00e7\u00f5es<\/strong><\/h3>\n<p>As parti\u00e7\u00f5es s\u00e3o as divis\u00f5es \u201cf\u00edsicas\u201d de um t\u00f3pico. Cada parti\u00e7\u00e3o representar\u00e1 o conjunto de registros de um t\u00f3pico, em um broker (n\u00f3) no\u00a0cluster.<\/p>\n<p>As parti\u00e7\u00f5es seguem o modelo de l\u00edder\/seguidor (leader\/follower), onde sempre h\u00e1 ao menos um broker com uma parti\u00e7\u00e3o principal que recebe todas as opera\u00e7\u00f5es de leitura e escrita, sendo replicado posteriormente para os demais brokers seguidores em forma de\u00a0r\u00e9plica.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/600\/0*LaNpvKl7mb0oUwEA\" alt=\"\" \/><figcaption>(Fig. 10: Representa\u00e7\u00e3o de um cluster Kafka. <a href=\"https:\/\/www.confluent.io\/\">https:\/\/www.confluent.io\/<\/a>)<\/figcaption><\/figure>\n<p>No exemplo acima, temos quatro parti\u00e7\u00f5es com duas r\u00e9plicas cada. Cada parti\u00e7\u00e3o ficar\u00e1 respons\u00e1vel por um conjunto de dados daquele t\u00f3pico, onde estes mesmos dados ser\u00e3o replicados em cada um dos outros dois brokers seguidores.<\/p>\n<p>O particionamento pode ser feito manualmente ou baseado em uma chave. No primeiro cen\u00e1rio, quem estiver produzindo e\/ou consumindo as mensagens, fica respons\u00e1vel por indicar com qual parti\u00e7\u00e3o deseja interfacear. J\u00e1 no segundo caso, deve-se definir previamente qual o range de valores de uma chave que cada parti\u00e7\u00e3o ser\u00e1 respons\u00e1vel. Desta forma, ao publicar ou ler um registro, o Kafka ficar\u00e1 encarregado por atribuir a parti\u00e7\u00e3o correspondente, baseado nas configura\u00e7\u00f5es previamente estabelecidas.<\/p>\n<h3><strong>Grupos de\u00a0consumo<\/strong><\/h3>\n<p>Grupo de consumo (consumer group) \u00e9 o nome l\u00f3gico para um ou mais consumers. \u00c9 atrav\u00e9s dele que se d\u00e1 a escalabilidade do lado dos consumidores.<\/p>\n<p>Cada grupo l\u00ea todas as mensagens de um t\u00f3pico, dividindo as parti\u00e7\u00f5es deste t\u00f3pico por entre os integrantes do\u00a0grupo.<\/p>\n<p>Cada grupo vai representar um processamento espec\u00edfico (e distinto) dos registros de um t\u00f3pico em rela\u00e7\u00e3o ao outro grupo. J\u00e1 cada integrante de um mesmo grupo representar\u00e1 uma inst\u00e2ncia de processamento (um processo, uma thread, um container, etc.) id\u00eantica em rela\u00e7\u00e3o aos consumers deste mesmo\u00a0grupo.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/474\/0*RScgni6rLtyU_kF4\" alt=\"\" \/><figcaption>(Fig. 11: Representa\u00e7\u00e3o de um grupo de consumo. <a href=\"https:\/\/www.confluent.io\/\">https:\/\/www.confluent.io\/<\/a>)<\/figcaption><\/figure>\n<p>No exemplo acima, temos um t\u00f3pico dividido em quatro parti\u00e7\u00f5es, e dois grupos de consumo: grupo A com dois integrantes e B com\u00a0quatro.<\/p>\n<p>Desta forma, tanto o grupo A quanto o grupo B processar\u00e3o todas as mensagens de um determinado t\u00f3pico. Devido ao grupo A possuir dois integrantes, cada integrante ficar\u00e1 respons\u00e1vel pelos registros de duas parti\u00e7\u00f5es cada. J\u00e1 no grupo B por possuir quatro integrantes, cada integrante ficar\u00e1 respons\u00e1vel pelas mensagens provenientes de uma \u00fanica parti\u00e7\u00e3o\u00a0cada.<\/p>\n<p>Com isto, \u00e9 poss\u00edvel ter N processos distintos para um mesmo dado e paralelizar cada um destes processamentos em N inst\u00e2ncias conforme a necessidade, sem gerar concorr\u00eancia entre\u00a0si.<\/p>\n<h3><strong>Offsets<\/strong><\/h3>\n<p>Ao inserir um registro em um t\u00f3pico, o Kafka automaticamente atribui um identificador \u00fanico sequencial para ele, que consiste basicamente de um \u00edndice deste registro na parti\u00e7\u00e3o daquele\u00a0t\u00f3pico.<\/p>\n<p>O offset por sua vez, representa a posi\u00e7\u00e3o de leitura de um grupo de consumo, em rela\u00e7\u00e3o \u00e0 uma parti\u00e7\u00e3o de um\u00a0t\u00f3pico.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/753\/0*ArApyHIsCDJkXF3C\" alt=\"\" \/><figcaption>(Fig. 12: Demonstra\u00e7\u00e3o de um t\u00f3pico com suas parti\u00e7\u00f5es e respectivos offsets. <a href=\"https:\/\/www.confluent.io\/\">https:\/\/www.confluent.io\/<\/a>)<\/figcaption><\/figure>\n<p>No exemplo acima, temos um t\u00f3pico com tr\u00eas parti\u00e7\u00f5es. As setas representando um grupo de consumo e os n\u00fameros destacados os offsets daquele grupo nas respectivos parti\u00e7\u00f5es.<\/p>\n<p>O objetivo do offset \u00e9 definir qual foi o \u00faltimo registro lido por aquele grupo de consumo naquela parti\u00e7\u00e3o, para que assim possa prosseguir com a leitura de onde\u00a0parou.<\/p>\n<p>O Kafka mant\u00e9m o tracking dos offsets para que apenas retorne os registros ainda n\u00e3o lidos. Por\u00e9m, como citado anteriormente, um consumer pode solicitar um registro em uma posi\u00e7\u00e3o espec\u00edfica.<\/p>\n<h2><strong>Conclus\u00e3o<\/strong><\/h2>\n<p>Conforme pudemos ver, o Kafka \u00e9 uma excelente ferramenta para cria\u00e7\u00e3o de sistemas distribu\u00eddos, mas assim como qualquer tecnologia, nasceu para resolver problemas espec\u00edficos e n\u00e3o para ser uma \u201cbala de prata\u201d da persist\u00eancia de\u00a0dados.<\/p>\n<h2>Que tal fazer parte desse\u00a0time?<\/h2>\n<p>Estamos buscando pessoas que topem o desafio de transformar a sa\u00fade no Brasil atrav\u00e9s da tecnologia. <a href=\"https:\/\/www.alice.com.br\/carreiras\">Clica aqui<\/a> para saber mais das vagas que temos em\u00a0aberto!<\/p>\n","protected":false},"excerpt":{"rendered":"Na Alice, temos a cultura de tomada de decis\u00f5es em conjunto para assuntos que impactem a engenharia como um todo.","protected":false},"author":3,"featured_media":176,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-147","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software"],"acf":[],"_links":{"self":[{"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/posts\/147","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/comments?post=147"}],"version-history":[{"count":4,"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/posts\/147\/revisions"}],"predecessor-version":[{"id":260,"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/posts\/147\/revisions\/260"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/media\/176"}],"wp:attachment":[{"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/media?parent=147"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/categories?post=147"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alice.com.br\/tech\/wp-json\/wp\/v2\/tags?post=147"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}