<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Odilon Jonathan Kröger</title>
    <description>The latest articles on Forem by Odilon Jonathan Kröger (@odilonjk).</description>
    <link>https://forem.com/odilonjk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F335345%2Ff702d3b6-764b-463a-84db-bbbb892ffe3a.jpeg</url>
      <title>Forem: Odilon Jonathan Kröger</title>
      <link>https://forem.com/odilonjk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/odilonjk"/>
    <language>en</language>
    <item>
      <title>Primeiros passos com Kafka - Parte 2</title>
      <dc:creator>Odilon Jonathan Kröger</dc:creator>
      <pubDate>Mon, 08 Mar 2021 00:15:48 +0000</pubDate>
      <link>https://forem.com/odilonjk/primeiros-passos-com-kafka-parte-2-496l</link>
      <guid>https://forem.com/odilonjk/primeiros-passos-com-kafka-parte-2-496l</guid>
      <description>&lt;p&gt;Créditos da foto de capa: &lt;a href="https://www.freeimages.com/photographer/marganz-55286"&gt;Margan Zajdowicz&lt;/a&gt; from &lt;a href="https://freeimages.com/"&gt;FreeImages&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E lá vamos nós para a continuação do papo sobre Kafka!&lt;/p&gt;

&lt;p&gt;Hoje em dia é muito comum o uso do formato JSON quando estamos enviando ou recebendo dados em nossos serviços.&lt;br&gt;
Embora não seja o mais comum, você também pode utilizar JSON quando for trabalhar com Kafka.&lt;br&gt;
Dependendo do tipo de linguagem que você for utilizar para seus serviços, outros formatos mais indicados seriam Protocol Buffers ou Avro. Como Protocol Buffer possúi gerador de código para diversas linguagens e também passou recentemente a ser suportado pela plataforma da Confluent, eu indico que você considere o uso de Protocol Buffers em vez de Avro. Mas isso é papo para outra publicação.&lt;/p&gt;

&lt;p&gt;Hoje vamos ver quais comandos podemos utilizar para enviar mensagens JSON no Kafka.&lt;br&gt;
Eu gosto muito de poder mostrar um exemplo como estes em JSON, porque fica mais fácil para entender como as coisas funcionam e se você for em algum momento utilizar a plataforma da Confluent, fica mais fácil para realizar os testes iniciais.&lt;/p&gt;
&lt;h3&gt;
  
  
  Do que vamos precisar?
&lt;/h3&gt;

&lt;p&gt;Conforme vimos na Parte 1, vamos precisar de pelo menos um nó do Kafka rodando.&lt;/p&gt;

&lt;p&gt;Que tal utilizarmos como exemplo plantas?&lt;br&gt;
Vamos iniciar criando um tópico.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose exec broker kafka-topics --create \
    --bootstrap-server broker:9092 \
    --topic plantas \
    --partitions 3 \
    --replication-factor 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Imagine que estamos utilizando o Kafka para controle lotes de plantas que são vendidos.&lt;br&gt;
Cada lote possui um código identificador, o valor do lote, de qual planta é composto o lote, e estufa onde está localizado o lote para a retirada.&lt;/p&gt;

&lt;p&gt;Poderíamos pensar no seguinte modelo para as mensagens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "lote": "abc-123",
   "valor": 123.45,
   "planta": "abcde",
   "estufa": "estufa-a"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enviando mensagens JSON para o Kafka
&lt;/h3&gt;

&lt;p&gt;Agora que temos um contexto, vamos criar algumas mensagens nesse tópico.&lt;/p&gt;

&lt;p&gt;Uma forma seria utilizando o comando &lt;strong&gt;kafka-console-producer&lt;/strong&gt; como vimos na publicação anterior. Porém, não é exatamente prático quando queremos enviar algo no formato JSON.&lt;/p&gt;

&lt;p&gt;Recentemente eu descobri o &lt;a href="https://github.com/edenhill/kafkacat"&gt;kafkacat&lt;/a&gt;.&lt;br&gt;
Para utilizar o kafkacat podemos instalar a ferramenta, ou da forma que eu costumo utilizar, através de um container no Docker.&lt;br&gt;
Abaixo temos um exemplo de como podemos utilizar esta ferramenta para enviar mensagens no formato JSON, sem precisar instalar o kafkacat.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -i --rm --network cp-all-in-one_default edenhill/kafkacat:1.6.0 -P -b broker:29092 -t plantas \
&amp;lt;&amp;lt;EOF

{"lote":"abc-123","valor":1500.57,"planta":"orquidea phalaenopsis","estufa":"orq-1"}
{"lote":"efg-432","valor":430.00,"planta":"bromelia ruby","estufa":"brm-4"}
{"lote":"xyz-987","valor":235.00,"planta":"bromelia fasciata","estufa":"brm-1"}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto! Não tem segredo!&lt;br&gt;
Vou explicar um pouco sobre os parâmetros acima.&lt;br&gt;
Repare que foi necessário passar o &lt;code&gt;--network&lt;/code&gt; do Docker. Isso é necessário para que o container consiga acessar os demais containers que estão rodando no Docker, ou seja, aquele que subimos ao executar o &lt;code&gt;docker-compose&lt;/code&gt; da primeira publicação.&lt;br&gt;
Quando executamos o comando, passamos o argumento &lt;code&gt;-P&lt;/code&gt; para informar que estamos produzindo mensagens. O &lt;code&gt;-b&lt;/code&gt; é onde informamos em qual nó do Kafka vamos produzir as mensagens.&lt;br&gt;
Já o &lt;code&gt;-t&lt;/code&gt; serve para informarmos em qual tópico as mensagens serão escritas. &lt;br&gt;
Em seguida, utilizo o bom e velho comando &lt;a href="https://linuxhint.com/what-is-cat-eof-bash-script/"&gt;EOF&lt;/a&gt; que você pode executar em qualquer sistema Unix.&lt;/p&gt;
&lt;h3&gt;
  
  
  E para consumir essas mensagens?
&lt;/h3&gt;

&lt;p&gt;Para conseguir consumir essas mensagens no terminal, você pode fazer exatamente como na publicação anterior, utilizando o comando &lt;strong&gt;kafka-console-consumer&lt;/strong&gt;.&lt;br&gt;
Por outro lado, se você estiver consumindo mensagens JSON em alguma aplicação, será necessário mapear corretamente o modelo da mensagem.&lt;/p&gt;

&lt;p&gt;Mas você também pode usar o kafkacat para ler as mensagens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -i --rm --network cp-all-in-one_default edenhill/kafkacat:1.6.0 -G meu-grupo -b broker:29092 plantas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui nós temos de diferente apenas o &lt;code&gt;-G&lt;/code&gt;, que serve para informar qual é o nome do grupo consumidor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ah, mais uma coisa sobre o kafkacat
&lt;/h3&gt;

&lt;p&gt;Se você quiser, pode enviar mensagens com uma chave utilizando esta ferramenta. &lt;br&gt;
Pensando no mesmo exemplo de plantas, poderiamos apenas adicionar o parâmetro &lt;code&gt;-K:&lt;/code&gt; e a chave antes de cada mensagem, como no comando abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -i --rm --network cp-all-in-one_default edenhill/kafkacat:1.6.0 -P -b broker:29092 -t plantas -K: \
&amp;lt;&amp;lt;EOF

1:{"lote":"foo-466","valor":60.50,"planta":"cactus enxertado","estufa":"cac-1"}
2:{"lote":"bar-311","valor":430.00,"planta":"bromelia ruby","estufa":"brm-3"}
3:{"lote":"usd-560","valor":440.00,"planta":"bromelia lingulata","estufa":"brm-3"}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  E é isso!
&lt;/h3&gt;

&lt;p&gt;Bastante simples, não é mesmo?&lt;/p&gt;

&lt;p&gt;Agora você já conhece a parte básica de como enviar e consumir mensagens de texto e também JSON no Kafka.&lt;/p&gt;

&lt;p&gt;Espero que estas duas publicações tenham sido de alguma ajuda! Até a próxima!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Primeiros passos com Kafka - Parte 1</title>
      <dc:creator>Odilon Jonathan Kröger</dc:creator>
      <pubDate>Sun, 28 Feb 2021 00:08:23 +0000</pubDate>
      <link>https://forem.com/odilonjk/primeiros-passos-com-kafka-parte-1-o4e</link>
      <guid>https://forem.com/odilonjk/primeiros-passos-com-kafka-parte-1-o4e</guid>
      <description>&lt;p&gt;Imagem de capa feita por &lt;a href="https://unsplash.com/@kaitlynbaker"&gt;Kaitlyn Baker&lt;/a&gt;. Disponível na plataforma &lt;a href="https://unsplash.com"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Beleza? &lt;/p&gt;

&lt;p&gt;Nesta publicação vou apresentar alguns comandos do Kafka.&lt;br&gt;
Vou tentar apresentar os comandos da forma mais fácil, sem precisar ficar instalando a plataforma inteira - isso é possível graças ao Docker.&lt;/p&gt;

&lt;p&gt;Então prepara o café ou chá, abre o editor de texto para fazer suas anotações e vamos nessa, publicar e consumir mensagens no Kafka.&lt;/p&gt;
&lt;h3&gt;
  
  
  O que vamos ver nesta publicação?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Como subir as imagens necessárias para ter um nó do Kafka rodando na sua máquina.&lt;/li&gt;
&lt;li&gt;Como criar, alterar e deletar tópicos.&lt;/li&gt;
&lt;li&gt;Como produzir mensagens nos tópicos.&lt;/li&gt;
&lt;li&gt;Como podemos ler as mensagens que estão armazenadas em um tópico.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ah, tem um detalhe! Os comandos que vou mostrar estou executando num terminal do Linux. &lt;/p&gt;
&lt;h3&gt;
  
  
  E o que não vamos ver nesta publicação?
&lt;/h3&gt;

&lt;p&gt;Não vou entrar nos detalhes de funcionamento do Kafka.&lt;br&gt;
Se você não conhece absolutamente nada de Kafka e chegou até esta publicação, sugiro fortemente que antes de qualquer coisa você leia o artigo &lt;a href="https://www.infoq.com/br/articles/apache-kafka-licoes/"&gt;Uma introdução ao Apache Kafka&lt;/a&gt;. Lá você vai encontrar todas as informações teóricas necessárias para entender como que o Kafka funciona.&lt;/p&gt;

&lt;p&gt;Também não vou mostrar como instalar, nem os detalhes de funcionamento do Docker. &lt;br&gt;
Sabendo o básico de Docker já é o suficiente para conseguir executar tudo oque será explicado abaixo.&lt;br&gt;
De qualquer forma, para executar os comandos abaixo é esperado que você tenha funcionando na sua máquina o Docker e o docker-compose.&lt;/p&gt;
&lt;h2&gt;
  
  
  Como subir o Kafka na minha máquina?
&lt;/h2&gt;

&lt;p&gt;Algumas pessoas curtem instalar tudo na máquina. Eu não sou uma dessas pessoas! :)&lt;br&gt;
Minha sugestão é utilizar o Docker para subir o ambiente.&lt;br&gt;
Para deixar a coisa ainda mais fácil, a Confluent disponibiliza arquivos &lt;code&gt;docker-compose.yml&lt;/code&gt; com toda configuração necessária já pronta.&lt;/p&gt;

&lt;p&gt;Primeiro vamos precisar baixar o repositório contendo esses arquivos: &lt;a href="https://github.com/confluentinc/cp-all-in-one"&gt;https://github.com/confluentinc/cp-all-in-one&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora acesse a pasta &lt;code&gt;cp-all-in-one/cp-all-in-one&lt;/code&gt;. Você verá que ali está o arquivo &lt;code&gt;docker-compose.yml&lt;/code&gt; necessário para rodar o Kafka localmente.&lt;br&gt;
Recomendo que você dê uma olhada no arquivo para entender quantas configurações teríamos que fazer na mão se não fosse por esta facilidade.&lt;/p&gt;

&lt;p&gt;Se você quiser, pode comentar todos os serviços com excessão do &lt;strong&gt;zookeeper&lt;/strong&gt; e do &lt;strong&gt;broker&lt;/strong&gt;. Nestes exemplos serão os únicos dois serviços utilizados.&lt;/p&gt;

&lt;p&gt;Nesse mesmo diretório do arquivo, vamos executar o comando necessário para subir todo o ambiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na primeira vez vai demorar um pouco, pois o Docker terá que baixar diversas imagens (cada uma daquelas que estão no &lt;code&gt;docker-compose.yml&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Quando o comando acima estiver concluído, você pode seguir para os próximos passos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quero criar um tópico!!!
&lt;/h2&gt;

&lt;p&gt;Como eu quero facilitar a coisa nessa publicação, eu não vou ficar entrando nos containers para executar os comandos. Como o docker-compose deixa que a gente execute através dele, vamos fazer uso dessa funcionalidade.&lt;br&gt;
Repare que vamos sempre utilizar o &lt;code&gt;kafka-topics&lt;/code&gt; nos comandos abaixo.&lt;/p&gt;

&lt;p&gt;Execute o comando abaixo para criar o primeiro tópico. Vamos chamar ele de &lt;em&gt;topico_teste&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose exec broker kafka-topics --create \
    --bootstrap-server broker:9092 \
    --topic topico_teste \
    --partitions 3 \
    --replication-factor 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que é isso aí tudo?&lt;br&gt;
Estamos pendindo para o docker-compose executar dentro do container &lt;em&gt;broker&lt;/em&gt; o comando &lt;em&gt;kafka-topics&lt;/em&gt; e seus argumentos.&lt;br&gt;
&lt;code&gt;--create&lt;/code&gt; para dizer que queremos criar um tópico.&lt;br&gt;
&lt;code&gt;--bootstrap-server&lt;/code&gt; é onde informamos o endereço do Kafka onde queremos criar o tópico. Este endereço que utilizamos é baseado no arquivo &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;--topic&lt;/code&gt; é onde informamos o nome do tópico.&lt;br&gt;
&lt;code&gt;--partitions&lt;/code&gt; serve para dizermos quantas partições o tópico vai ter.&lt;br&gt;
&lt;code&gt;--replication-factor&lt;/code&gt; é utilizado para dizer em quantos nós este tópico deverá ser replicado. Para o nosso exemplo é necessário deixar &lt;code&gt;1&lt;/code&gt;, senão não vai funcionar, pois só temos um nó rodando. Mas em um cluster "pra valer", com toda certeza você vai precisar replicar mais do que em apenas 1 nó.&lt;/p&gt;

&lt;p&gt;Se você quiser, pode executar o comando abaixo listar todos os tópicos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose exec broker kafka-topics --list \
    --bootstrap-server broker:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para modificar um tópico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose exec broker kafka-topics --alter \
    --bootstrap-server broker:9092 \
    --topic topico_teste \
    --partitions 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se você quiser saber detalhes de como está o seu tópico, é possível utilizar o comando &lt;code&gt;--describe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose exec broker kafka-topics  --describe \
    --bootstrap-server broker:9092 \
    --topic topico_teste
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Vamos iniciar um consumidor.
&lt;/h2&gt;

&lt;p&gt;Antes de começar a produzir mensagens, eu acho legal iniciar um consumidor para o tópico, assim podemos ver em tempo real a coisa funcionando!&lt;/p&gt;

&lt;p&gt;Para iniciar um consumidor, vamos usar o &lt;code&gt;kafka-console-consumer&lt;/code&gt;.&lt;br&gt;
Basta executar o comando abaixo para iniciar o consumo de mensagens do seu tópico &lt;code&gt;topico_teste&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose exec broker kafka-console-consumer \
    --bootstrap-server broker:9092 \
    --topic topico_teste
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Agora quero mandar mensagens para este tópico!
&lt;/h2&gt;

&lt;p&gt;Legal! Para deixar ainda mais legal a experiência, deixe o consumidor rodando em uma outra aba do terminal, ou outro terminal, ou qualquer coisa assim para poder ver a coisa acontecendo ao mesmo tempo.&lt;/p&gt;

&lt;p&gt;Vamos agora utilizar o &lt;code&gt;kafka-console-producer&lt;/code&gt;. O comando para iniciar o producer está logo abaixo. Quando você executar, ele ficara ativamente enviando tudo que você digitar para o tópico. Para parar o producer basta pressionar &lt;code&gt;Ctrl+C&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose exec broker kafka-console-producer \
    --bootstrap-server broker:9092 \
    --topic topico_teste
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  E se eu quiser deletar o tópico?
&lt;/h2&gt;

&lt;p&gt;Primeiro você precisa parar o seu consumidor e também o produtor de mensagens.&lt;br&gt;
Em seguida, basta utilizar o &lt;code&gt;kafka-topics&lt;/code&gt; passando por parâmetro &lt;code&gt;--delete&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose exec broker kafka-topics  --delete \
    --bootstrap-server broker:9092 \
    --topic topico_teste
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  É isso aí!
&lt;/h2&gt;

&lt;p&gt;Kafka é uma ferramenta bastante poderosa, cheia de funcionalidades e configurações para conseguir ser uma ferramenta eficaz em diversos cenários diferentes.&lt;br&gt;
Mas isso não dignifica que precisa ser difícil!&lt;/p&gt;

&lt;p&gt;A ferramenta tem evoluído nesse sentido e após você "brincar" algumas vezes produzindo e consumindo mensagens, acaba se tornando cada vez mais fácil o entendimento de como cada uma das coisas funciona no Kafka.&lt;/p&gt;

&lt;p&gt;Para não deixar o texto gigante, vou fechar por aqui. Mas numa próxima vou mostrar como podemos enviar mensagens no formato JSON!!!&lt;/p&gt;

&lt;p&gt;Até lá! \o&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AWS Elastic Beanstalk + Go</title>
      <dc:creator>Odilon Jonathan Kröger</dc:creator>
      <pubDate>Wed, 06 Jan 2021 01:44:04 +0000</pubDate>
      <link>https://forem.com/odilonjk/aws-elastic-beanstalk-go-2kaf</link>
      <guid>https://forem.com/odilonjk/aws-elastic-beanstalk-go-2kaf</guid>
      <description>&lt;p&gt;Foto de capa: &lt;a href="https://www.pexels.com/pt-br/@gelgas"&gt;Gelgas Airlangga&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos lá para um pequeno tutorial ensinando o passo-a-passo de como subir uma aplicação Go no serviço Elastic Beanstalk da AWS.&lt;br&gt;
Vou utilizar o &lt;a href="https://github.com/aws/aws-cli"&gt;AWS CLI&lt;/a&gt; porque acho legal para a pessoa que está iniciando saber exatamente todas as coisas que acontecem. Até porque se você em algum momento quiser utilizar Terraform, já tem uma boa idéia do que você vai precisar utilizar da AWS.&lt;/p&gt;

&lt;p&gt;Antes de começarmos a ver código e comandos, quero pontuar aqui algumas coisas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estou escrevendo este tutorial considerando que você já tem uma conta na aws. Para resumir, aqui não estou ensinando a criar uma conta.&lt;/li&gt;
&lt;li&gt;Também considero que você já tem instalado o AWS CLI. Se não tiver, basta seguir a &lt;a href="https://docs.aws.amazon.com/pt_br/cli/latest/userguide/cli-chap-install.html"&gt;documentação oficial em português&lt;/a&gt; que não tem mistério.&lt;/li&gt;
&lt;li&gt;Por fim considero que você está ciente que &lt;strong&gt;a execução destes serviços na AWS podem resultar em custos&lt;/strong&gt;. No meu caso, só para rodar os comandos desse tutorial para validar que está tudo funcionando me custou U$0.10 e eu terminei tudo logo em seguida para não gerar mais custos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hoje a trilha sonora é &lt;em&gt;Anti-Flag - Turncoat&lt;/em&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Escrevendo a aplicação para usar de exemplo
&lt;/h2&gt;

&lt;p&gt;O código do exemplo é uma coisa bastante simples, apenas 2 endpoints: um de health check e outro para hello world.&lt;br&gt;
Vamos criar um arquivo chamado &lt;code&gt;application.go&lt;/code&gt; e escrever o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello-world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/health"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":5000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso você ainda não conheça muito de Go, o código dentro da função &lt;em&gt;main&lt;/em&gt; está mapeando 2 endereços, no caso &lt;code&gt;/hello-world&lt;/code&gt; e &lt;code&gt;/health&lt;/code&gt;. As linhas com &lt;code&gt;fmt.Fprintf&lt;/code&gt; são responsáveis pela mensagem que será exibida na tela.&lt;br&gt;
Logo depois do mapeamento estamos dizendo que a aplicação vai ficar ouvindo a porta 5000.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Atençãããão!!! Tem alguns detalhes até aqui.&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Por que o arquivo se chama &lt;code&gt;application.go&lt;/code&gt; e não &lt;code&gt;maldicao.go&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;A documentação da AWS diz que existem algumas formas de fazer deploy da aplicação. &lt;br&gt;
A que eu escolhi para este exemplo eu achei ser a mais simples de todas, que é dar o nome de &lt;code&gt;application.go&lt;/code&gt; para o arquivo principal. Isso porque quando o Elastic Beanstalk for construir (&lt;em&gt;"buildar"&lt;/em&gt;) a aplicação, ele vai rodar por padrão esse comando aqui: &lt;code&gt;go build -o bin/application application.go&lt;/code&gt;, ou seja, o Elastic Beanstalk já ta lá esperando encontrar esse arquivo com esse nome.&lt;/p&gt;
&lt;h4&gt;
  
  
  E a porta, por que é 5000 e não 8123?
&lt;/h4&gt;

&lt;p&gt;Mesma situação que o nome do arquivo. Por padrão o Elastic Beanstalk inicia a aplicação na porta 5000.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/go-environment.html"&gt;Clique aqui&lt;/a&gt; caso queira ler a documentação oficial da AWS sobre isso que expliquei acima. &lt;br&gt;
Aliás, eu recomendo pare para ler a documentação sempre que estiver estudando algo. Ás vezes a pessoa que está escrevendo o tutorial, tipo eu agora, acaba deixando algo passar, ou entendeu algo errado ou ainda o tutorial pode estar desatualizado, então crie o hábito de validar na documentação. Isso vai agregar um conhecimento legal para você! :)&lt;/p&gt;

&lt;p&gt;Ah, antes de irmos para os comandos AWS CLI, também vamos precisar criar um arquivo chamado &lt;code&gt;options.json&lt;/code&gt;. Ele é necessário para informar qual profile IAM nossa aplicação vai utilizar. Se você não sabe o que é IAM, não se preocupe, isto é assunto para outro tutorial.&lt;br&gt;
Coloque isto dentro do arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws:autoscaling:launchconfiguration"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"OptionName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IamInstanceProfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws-elasticbeanstalk-ec2-role"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Utilizando Elastic Beanstalk
&lt;/h2&gt;

&lt;p&gt;Beleza! Código feito, vamos para a parte tão aguardada: como fazer deploy desse código no Elastic Beanstalk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 1&lt;/strong&gt;: gerar um &lt;code&gt;.zip&lt;/code&gt; com o nosso código fonte. Este &lt;code&gt;.zip&lt;/code&gt; será enviado para a AWS e pode ter o nome que você preferir. &lt;br&gt;
No caso do meu exemplo eu só tenho dois arquivos para colocar no &lt;code&gt;.zip&lt;/code&gt;: &lt;code&gt;application.go&lt;/code&gt; e &lt;code&gt;go.mod&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No terminal, navege até a raiz do projeto e execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zip &lt;span class="nt"&gt;-r&lt;/span&gt; application.zip &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Passo 2&lt;/strong&gt;: criar um S3 Bucket para enviar o arquivo &lt;code&gt;.zip&lt;/code&gt;. Você pode criar com o nome que você quiser, eu fiz uma mistura de nome legível + o final de um UUID que gerei no Google e ficou assim: beanstalk-app-660390121deb.&lt;br&gt;
O comando para criar o Bucket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3api create-bucket &lt;span class="nt"&gt;--bucket&lt;/span&gt; beanstalk-app-660390121deb &lt;span class="nt"&gt;--create-bucket-configuration&lt;/span&gt; &lt;span class="nv"&gt;LocationConstraint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-west-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No caso &lt;code&gt;--bucket&lt;/code&gt; serve para dizer qual é o nome desejado. Caso você esteja utilizando alguma região diferente de &lt;em&gt;us-east-1&lt;/em&gt;, é necessário também adicionar o &lt;code&gt;--create-bucket-configuration LocationConstraint=AQUI_A_SUA_REGIAO&lt;/code&gt; para indicar a região correta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 3&lt;/strong&gt;: enviar o &lt;code&gt;.zip&lt;/code&gt; para o Bucket.&lt;br&gt;
Esse passo é muito fácil, só executar aí:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 &lt;span class="nb"&gt;cp &lt;/span&gt;application.zip s3://beanstalk-app-660390121deb/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Passo 4&lt;/strong&gt;: chegou a hora de criar uma aplicação dentro do Elastic Beanstalk. Esse passo também é bastante simples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws elasticbeanstalk create-application &lt;span class="nt"&gt;--application-name&lt;/span&gt; minha-app-muito-legal &lt;span class="nt"&gt;--region&lt;/span&gt; us-west-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Passo 5&lt;/strong&gt;: criar uma versão da aplicação no Elastic Beanstalk, apontando para o arquivo &lt;code&gt;.zip&lt;/code&gt; no S3 Bucket.&lt;br&gt;
Na real, isso significa que você está falando que a &lt;strong&gt;v1&lt;/strong&gt; por exemplo, utiliza o arquivo &lt;code&gt;minha_app_v1.zip&lt;/code&gt; por exemplo. Aí depois se você for mexer no seu código e quiser subir uma v2, você poderia subir no Bucket um arquivo &lt;code&gt;minha_app_v2.zip&lt;/code&gt; e fazer esse "link" com este comando aqui gerando uma &lt;strong&gt;v2&lt;/strong&gt;, só precisaria alterar aqui no comando o parâmetro passado em &lt;code&gt;--version-label&lt;/code&gt;.&lt;br&gt;
O comando para criar a versão v1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws elasticbeanstalk create-application-version &lt;span class="nt"&gt;--application-name&lt;/span&gt; minha-app-muito-legal &lt;span class="nt"&gt;--version-label&lt;/span&gt; v1 &lt;span class="nt"&gt;--source-bundle&lt;/span&gt; &lt;span class="nv"&gt;S3Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;beanstalk-app-660390121deb,S3Key&lt;span class="o"&gt;=&lt;/span&gt;application.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Passo 6&lt;/strong&gt;: chegou a hora de criar um environment no Elastic Beanstalk. O comando é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws elasticbeanstalk create-environment &lt;span class="nt"&gt;--application-name&lt;/span&gt; minha-app-muito-legal &lt;span class="nt"&gt;--environment-name&lt;/span&gt; staging &lt;span class="nt"&gt;--option-settings&lt;/span&gt; file://options.json &lt;span class="nt"&gt;--version-label&lt;/span&gt; v1 &lt;span class="nt"&gt;--solution-stack-name&lt;/span&gt; &lt;span class="s2"&gt;"64bit Amazon Linux 2 v3.1.4 running Go 1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explicando melhor: estamos passando por parâmetro o nome da aplicação que estamos ligando neste novo environment. No &lt;code&gt;--application-name&lt;/code&gt; eu digo qual é a aplicação que eu quero rodar, no &lt;code&gt;--environment-name&lt;/code&gt; eu posso colocar o nome que eu quiser para o meu ambiente, no caso chamei de &lt;em&gt;staging&lt;/em&gt;. Agora o &lt;code&gt;--solution-stack-name&lt;/code&gt; é que requer um pouco mais de atenção. Este é o nome da stack que será utilizada no ambiente e deve ter um valor conhecido pelo Elastic Beanstalk. Você pode encontrar todas as opções disponíveis &lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html"&gt;nesta documentação&lt;/a&gt;. Basta clicar na linguagem que você tiver curiosidade que a doc vai mostrar as opções válidas.&lt;br&gt;
Aqui também foi utilizado o arquivo &lt;code&gt;options.json&lt;/code&gt; que criamos anteriormente e passamos no comando &lt;code&gt;--version-label v1&lt;/code&gt; para dizer que o ambiente vai utilizar aquela versão que criamos no Passo 5. Se você deu um nome diferente de &lt;em&gt;v1&lt;/em&gt;, vai precisar alterar aqui também.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PRONTO!&lt;/strong&gt; Agora você já tem a aplicação rodando no Elastic Beanstalk.&lt;br&gt;
Para o deploy acontecer (ou terminar os serviços), ás vezes demora um pouco. Você pode conferir o status pelo terminal com o comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws elasticbeanstalk describe-environments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou se preferir, basta acessar o serviço Elastic Beanstalk no Console da AWS.&lt;/p&gt;

&lt;p&gt;Na imagem abaixo que mostra o Console da AWS, fica fácil de obter diversas informações.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cH9YyS0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/byeca62ium5ue40406xn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cH9YyS0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/byeca62ium5ue40406xn.png" alt="Console da AWS mostrando Elastic Beanstalk"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quando &lt;em&gt;health&lt;/em&gt;  mudar para OK, sabemos que acabou o deploy e podemos testar a aplicação.&lt;br&gt;
Já na coluna &lt;em&gt;URL&lt;/em&gt; temos o endereço da aplicação que vamos usar para testar.&lt;/p&gt;

&lt;p&gt;Assim que a coluna &lt;em&gt;health&lt;/em&gt; ficar OK (talvez seja necessário recarregar a página), você já pode testar. É só copiar a URL ali da tabela e adicionar no final &lt;code&gt;/health&lt;/code&gt; ou &lt;code&gt;/hello-world&lt;/code&gt; que são os 2 endpoints disponíveis na aplicação.&lt;/p&gt;

&lt;p&gt;Se deu tudo certo, você vai ver algo parecido com a imagem a seguir:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C14SXFZi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g5acgczdnp8irn5mvxek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C14SXFZi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g5acgczdnp8irn5mvxek.png" alt="Browser com tela mostrando Hello world!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora digamos que você queira adicionar um novo endpoint, ou remover. Vai precisar criar uma nova versão. Para isso você vai precisar repetir o Passo 1, criando um novo arquivo &lt;code&gt;.zip&lt;/code&gt;, em seguida vai precisar executar o Passo 3 para enviar esse arquivo para o S3 Bucket. Em seguida vai precisar executar novamente o Passo 5 alterando o nome da versão no &lt;code&gt;--version-label&lt;/code&gt;. E finalmente será necessário fazer a atualização da versão no environment com o comando abaixo, alterando &lt;code&gt;--version-label&lt;/code&gt; para a versão desejada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws elasticbeanstalk update-environment &lt;span class="nt"&gt;--application-name&lt;/span&gt; minha-app-muito-legal &lt;span class="nt"&gt;--environment-name&lt;/span&gt; staging &lt;span class="nt"&gt;--version-label&lt;/span&gt; v2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NAO ESQUEÇA DE TERMINAR A APLICAÇÃO!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para evitar custos desnecessários, nunca esqueça de parar suas aplicações na AWS.&lt;br&gt;
No nosso caso podemos fazer isso da seguinte forma para remover o environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws elasticbeanstalk terminate-environment &lt;span class="nt"&gt;--environment-name&lt;/span&gt; staging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos remover a aplicação do Elastic Beanstalk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws elasticbeanstalk delete-application &lt;span class="nt"&gt;--application-name&lt;/span&gt; minha-app-muito-legal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E por fim para remover o S3 Bucket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 rb s3://beanstalk-app-660390121deb &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse caso é necessário utilizar &lt;code&gt;--force&lt;/code&gt; para remover o Bucket e deletar os arquivos existentes. Sem este parâmetro é necessário primeiro esvaziar o Bucket para depois remover ele.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oqCm5X6J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/59ubznd5w3h8h33ss1d8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oqCm5X6J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/59ubznd5w3h8h33ss1d8.gif" alt="The horns"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora você já conhece todos comandos necessários para realizar o deploy utilizando AWS CLI.&lt;br&gt;
Este foi um exemplo bastante simples. Agora você pode expandir conforme a necessidade, adicionando na aplicação um banco de dados ou fila SQS, por exemplo.&lt;/p&gt;

&lt;p&gt;Outra possibilidade de continuação dos estudos seria transformar todos estes comandos em "receitinhas" no &lt;a href="https://www.terraform.io/"&gt;Terraform&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Espero que você tenha curtido essa experiência! Tudo de bom para você! :)&lt;/p&gt;

</description>
      <category>aws</category>
      <category>go</category>
      <category>awscli</category>
      <category>elasticbeanstalk</category>
    </item>
    <item>
      <title>Processamento assíncrono utilizando Go e RabbitMQ. Parte 2</title>
      <dc:creator>Odilon Jonathan Kröger</dc:creator>
      <pubDate>Sun, 28 Jun 2020 21:14:17 +0000</pubDate>
      <link>https://forem.com/odilonjk/processamento-assincrono-utilizando-go-e-rabbitmq-parte-2-3oen</link>
      <guid>https://forem.com/odilonjk/processamento-assincrono-utilizando-go-e-rabbitmq-parte-2-3oen</guid>
      <description>&lt;p&gt;Foto de capa: &lt;a href="https://unsplash.com/@mbaumi?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Mika Baumeister&lt;/a&gt; no site &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Chegou a hora de ver código!!!&lt;/p&gt;

&lt;p&gt;O código fonte se encontra em um &lt;a href="https://github.com/odilonjk/golang-examples/tree/master/processamento-assincrono"&gt;monorepo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dentro do repositório você pode encontrar o &lt;em&gt;Dockerfile&lt;/em&gt; e também o &lt;em&gt;Makefile&lt;/em&gt; para conseguir buildar e rodar o projeto. As informações necessárias de como rodar se encontram no &lt;em&gt;README&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Apenas para deixar claro, a intensão deste projeto é apenas exemplificar uma forma de processamento assíncrono. O código não foi feito pensando na melhor forma de reutilização de código, nem considera as configurações pensando em ambiente produtivo.&lt;br&gt;
A ideia é passar o conceito (publicação anterior) e um exemplo de como começar a brincar com processamento assíncrono em sua casa! :)&lt;/p&gt;


&lt;h1&gt;
  
  
  Exemplo de microsserviço Estoque
&lt;/h1&gt;

&lt;p&gt;Nesta publicação vou abordar a explicação sobre o Estoque.&lt;br&gt;
Para facilitar o entendimento, sugiro deixar aberto em uma aba ao lado ou em seu editor o código fonte que está &lt;a href="https://github.com/odilonjk/golang-examples/tree/master/processamento-assincrono/estoque"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;O exemplo está dividido de forma bastante simples. Um arquivo &lt;code&gt;main.go&lt;/code&gt; na raiz e outro pacote &lt;code&gt;rabbit.go&lt;/code&gt; dentro do diretório &lt;code&gt;pkg&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Pacote rabbit.go 🐰
&lt;/h1&gt;

&lt;p&gt;Este pacote é bastante simples. Nele fica a implementação que faz comunicação com a API do RabbitMQ.&lt;br&gt;
A implementação é baseada nos exemplos contidos na &lt;a href="https://www.rabbitmq.com/tutorials/tutorial-one-go.html"&gt;documentação&lt;/a&gt; oficial do RabbitMQ.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewDefaultChannel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"amqp://guest:guest@localhost:5672/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;failOnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Failed to connect to RabbitMQ"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;failOnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Failed to open channel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta função inicia uma conexão com o RabbitMQ, utilizando o usuário &lt;code&gt;guest&lt;/code&gt;, no host/port &lt;code&gt;localhost:5272&lt;/code&gt;.&lt;br&gt;
É feita a validação se retornou algum erro, em seguida é aberto um canal de comunicação com o RabbitMQ, chamando &lt;code&gt;conn.Channel()&lt;/code&gt;.&lt;br&gt;
Após nova verificação para ver se houve falha, é retornado o canal de comunicação com o RabbitMQ.&lt;/p&gt;

&lt;p&gt;As próximas funções são bastante simples. Elas são utilizadas no arquivo &lt;code&gt;main.go&lt;/code&gt; para declarar &lt;code&gt;exchange&lt;/code&gt; e &lt;code&gt;queue&lt;/code&gt;.&lt;br&gt;
Elas recebem por parâmetro informações como nome, tipo e argumentos de configuração.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;DeclareExchange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExchangeDeclare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;failOnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Failed to declare exchange "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;DeclareQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueueDeclare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;failOnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Failed to declare queue "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A próxima função é utilizada quando queremos criar a ligação entre uma &lt;code&gt;exchange&lt;/code&gt; e uma &lt;code&gt;queue&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BindQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueueBind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;failOnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Failed to bind "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;" with "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesta função recebemos o nome da &lt;code&gt;exchange&lt;/code&gt;, o nome da &lt;code&gt;queue&lt;/code&gt; a uma chave de roteamento &lt;code&gt;k&lt;/code&gt;.&lt;br&gt;
Essa chave de roteamento é que faz a &lt;code&gt;exhange&lt;/code&gt; saber direcionar uma mensagem para a &lt;code&gt;queue&lt;/code&gt; correta.&lt;br&gt;
O RabbitMQ permite configurar de diversas formas essa ligação entre &lt;code&gt;exhanges&lt;/code&gt;, &lt;code&gt;queues&lt;/code&gt; e &lt;code&gt;routingKeys&lt;/code&gt;.&lt;br&gt;
Mais detalhes você pode encontrar na &lt;a href="https://www.rabbitmq.com/tutorials/tutorial-four-go.html"&gt;documentação de roteamento&lt;/a&gt; do RabbitMQ.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Publishing&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;failOnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Failed to publish on exchange "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finalmente temos a função que envia uma mensagem para o RabbitMQ.&lt;br&gt;
O parâmetro &lt;code&gt;m&lt;/code&gt; é uma mensagem no formato JSON, &lt;code&gt;e&lt;/code&gt; é o nome da &lt;code&gt;exchange&lt;/code&gt; que receberá a mensagem e &lt;code&gt;k&lt;/code&gt; é a chave de roteamento.&lt;/p&gt;
&lt;h1&gt;
  
  
  Agora vamos ver o arquivo main.go
&lt;/h1&gt;

&lt;p&gt;A primeira coisa que vamos olhar é a declaração de constantes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;productionOrderExchange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"productionorder"&lt;/span&gt;
    &lt;span class="n"&gt;deadLetterExchange&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"productionorder.dlx"&lt;/span&gt;
    &lt;span class="n"&gt;createQueue&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"create.productionorder"&lt;/span&gt;
    &lt;span class="n"&gt;deadLetterQueue&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"create.productionorder.dlx"&lt;/span&gt;
    &lt;span class="n"&gt;routingKey&lt;/span&gt;              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"create"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui temos declarados os nomes de todas &lt;code&gt;exchanges&lt;/code&gt;, &lt;code&gt;queues&lt;/code&gt; e &lt;code&gt;routingKey&lt;/code&gt; utilizados no microsserviço.&lt;br&gt;
Para deixar mais fácil de encotrar as coisas no Management do RabbitMQ, deixei &lt;code&gt;dlx&lt;/code&gt; como sufixo para a &lt;code&gt;exchange&lt;/code&gt; e &lt;code&gt;queue&lt;/code&gt; de dead-letter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;RefCode&lt;/span&gt;   &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;
    &lt;span class="n"&gt;ColorCode&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;
    &lt;span class="n"&gt;Quantity&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta é a estrutura da mensagem enviada para o RabbitMQ. Temos um &lt;code&gt;RefCode&lt;/code&gt; que é o código do pedido.&lt;br&gt;
O atributo &lt;code&gt;ColorCode&lt;/code&gt; é utilizado para identificação da cor que deve ser produzida e &lt;code&gt;quantity&lt;/code&gt; é simplesmente a quantidade de esmaltes que deve ser produzida.&lt;/p&gt;
&lt;h2&gt;
  
  
  Entendendo a função main()
&lt;/h2&gt;

&lt;p&gt;Antes de mais nada estou criando um canal de comunicação com o RabbitMQ, fazendo uso do pacote declarado em &lt;code&gt;rabbit.go&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDefaultChannel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida eu trato da declaração das &lt;code&gt;exchanges&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="n"&gt;exchangeArgs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;exchangeArgs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"x-delayed-type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"direct"&lt;/span&gt;

    &lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeclareExchange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;productionOrderExchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"x-delayed-message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exchangeArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeclareExchange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deadLetterExchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"direct"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eu crio um mapa de argumentos em &lt;code&gt;make(amqp.Table)&lt;/code&gt;.&lt;br&gt;
Para conseguir utilizar o plugin Delayed Message, é preciso adicionar o argumento &lt;code&gt;x-delayed-type&lt;/code&gt; com o valor &lt;code&gt;direct&lt;/code&gt;.&lt;br&gt;
Seria basicamente como criar uma &lt;code&gt;exchange&lt;/code&gt; do tipo &lt;code&gt;direct&lt;/code&gt;, mas que saiba trabalhar com delay nas mensagens.&lt;/p&gt;

&lt;p&gt;Depois eu declaro as duas &lt;code&gt;exchanges&lt;/code&gt; necessárias para esse projeto. Uma contendo os argumentos para trabalhar com delay, outra para tratar as dead-letters.&lt;br&gt;
Na &lt;code&gt;deadLetterExchange&lt;/code&gt; eu não adiciono a configuração de delay, porque não quero esse comportamento sendo executado para a DLQ.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="n"&gt;queueArgs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amqp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;queueArgs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"x-max-length"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;queueArgs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"x-dead-letter-exchange"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deadLetterExchange&lt;/span&gt;

    &lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeclareQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;createQueue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queueArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeclareQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deadLetterQueue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora eu crio os argumentos de configuração para fila. O argumento &lt;code&gt;x-max-length&lt;/code&gt; configura qual o tamanho da fila. Nesse exemplo, caso a fila já tenha 3 mensagens aguardando processamento, novas mensagens recebidas são automaticamente direcionadas para a DLQ.&lt;br&gt;
O argumento &lt;code&gt;x-dead-letter-exchange&lt;/code&gt; é que informa qual é a &lt;code&gt;exchange&lt;/code&gt; responsável pela DLQ.&lt;/p&gt;

&lt;p&gt;Em seguida, eu faço a declaração das duas &lt;code&gt;queues&lt;/code&gt;: a normal, com os argumentos de configuração, e a &lt;code&gt;deadLetterQueue&lt;/code&gt;, que é a DLQ do projeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BindQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;productionOrderExchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;createQueue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BindQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deadLetterExchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deadLetterQueue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este é o código responsável por criar a ligação entre as &lt;code&gt;exchanges&lt;/code&gt;, &lt;code&gt;queues&lt;/code&gt; e &lt;code&gt;routingKey&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;E finalmente, vamos para a publicação da mensagem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;createMsgAsJSON&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;productionOrderExchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eu crio uma mensagem com a função &lt;code&gt;createMsgAsJSON()&lt;/code&gt;, que cria dados aleatórios e retorna a estrutura &lt;code&gt;message&lt;/code&gt; no formato JSON.&lt;br&gt;
Essa mensagem então é enviada para o RabbitMQ. A função &lt;code&gt;rabbit.Publish&lt;/code&gt; recebe a mensagem, a &lt;code&gt;exchange&lt;/code&gt; que deve tratar a mensagem e também a &lt;code&gt;routingKey&lt;/code&gt;.&lt;br&gt;
Aqui neste exemplo estamos apenas tratando da criação de pedidos, mas poderíamos ter outras chaves de roteamento, como &lt;code&gt;delete&lt;/code&gt; e &lt;code&gt;update&lt;/code&gt;. Assim como o caso das &lt;code&gt;exchanges&lt;/code&gt; e &lt;code&gt;queues&lt;/code&gt;, o nome das chaves de roteamento é você que escolhe conforme sua necessidade. :)&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;A solução ficou maior do que utilizar uma simples requisição HTTP, mas acaba não sendo um bicho de sete cabeças.&lt;br&gt;
Poder trabalhar com o &lt;code&gt;Estoque&lt;/code&gt;, sem sofrer impacto negativo no caso da &lt;code&gt;OrdemDeProducao&lt;/code&gt; estar fora do ar, é um grande ganho!&lt;/p&gt;

&lt;p&gt;Ao rodar o &lt;code&gt;Estoque&lt;/code&gt;, é possível ver na prática que podemos disparar N mensagens sem nos preocuparmos com a &lt;code&gt;OrdemDeProducao&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Na próxima publicação da série vou comentar sobre a implementação da &lt;code&gt;OrdemDeProducao&lt;/code&gt;. Até lá! o/&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Processamento assíncrono utilizando Go e RabbitMQ. Parte 1</title>
      <dc:creator>Odilon Jonathan Kröger</dc:creator>
      <pubDate>Mon, 15 Jun 2020 02:31:16 +0000</pubDate>
      <link>https://forem.com/odilonjk/processamento-assincrono-parte-1-31pn</link>
      <guid>https://forem.com/odilonjk/processamento-assincrono-parte-1-31pn</guid>
      <description>&lt;p&gt;Crédito da imagem de capa: &lt;a href="https://unsplash.com/@joannakosinska?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Joanna Kosinska&lt;/a&gt; no &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algum tempo atrás compartilhei uns artigos falando sobre reprocessamento de mensagens.&lt;br&gt;
Como é algo que acabo utilizando bastante, achei bacana criar um artigo cobrindo a ideia de como e, porque considerar o reprocessamento de mensagens na comunicação entre microsserviços.&lt;br&gt;
Como acabou ficando bastante grande o texto, o conceito da solução será abordado neste texto e a implementação será analisada no próximo artigo.&lt;/p&gt;

&lt;p&gt;Escolhi o RabbitMQ para este exemplo por ser um broker de mensageria bastante adotado no mercado, fácil de conseguir rodar localmente e também é uma ferramenta bastante completa.&lt;br&gt;
De qualquer forma, não se prenda a linguagem ou ao broker de mensageria escolhido. Absorva o conceito!&lt;br&gt;
Ao compreender como, quando e, porque utilizar uma determinada solução, você pode replicar com facilidade em praticamente qualquer linguagem de mercado e com algumas variações de ferramentas utilizadas. Por exemplo, poderia ser utilizado ZeroMQ, ActiveMQ, NATS ou até mesmo Kafka no lugar do RabbitMQ.&lt;br&gt;
Embora eu explore algumas poucas features do RabbitMQ, não é intensão deste artigo mostrar o RabbitMQ no detalhe, nem ensinar como configurá-lo para ambiente de produção.&lt;/p&gt;

&lt;h1&gt;
  
  
  Entendendo o problema
&lt;/h1&gt;

&lt;p&gt;Vamos imaginar um sistema que foi desenvolvido para uma fábrica de esmaltes que está investindo pesado em automação. Nossa tarefa é melhorar uma parte específica do sistema, entre o controle do estoque de esmaltes e a geração de novas ordens de produção.&lt;br&gt;
O sistema é distribuído entre diversos microsserviços, mas para nossa tarefa, apenas nos interessam dois microsserviços: &lt;strong&gt;Estoque&lt;/strong&gt; e &lt;strong&gt;OrdemDeProducao&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l6IliFxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/grlcez1fasb8pjca69pj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l6IliFxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/grlcez1fasb8pjca69pj.png" alt="Imagem mostrando requisição HTTP entre serviço Estoque e OrdemDeProducao"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quando o estoque de uma determinada cor da coleção vigente está abaixo de 30%, o microsserviço de Estoque automaticamente dispara uma mensagem para o microsserviço OrdemDeProducao, gerando uma ordem de produção para o esmalte em questão.&lt;br&gt;
O serviço se comunica de forma síncrona utilizando requisições HTTP.&lt;br&gt;
E o que acontece se no momento que o Estoque precisar gerar uma ordem de produção, e o microsserviço OrdemDeProducao estiver fora do ar? E se apresentar muita lentidão por algum motivo qualquer, retornando timeout para o microsserviço Estoque?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IuCMjgn4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lvy1q2h3by9lwqwt5n8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IuCMjgn4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lvy1q2h3by9lwqwt5n8c.png" alt="Imagem mostrando falha na chamada para OrdemDeProducao"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Resolvendo o impacto no lado do microsserviço Estoque
&lt;/h1&gt;

&lt;p&gt;Algo que podemos observar é que esta funcionalidade de gerar uma ordem de produção, não precisa de um retorno imediato. O serviço Estoque apenas precisa gerar a ordem de produção, não faz diferença se isto vai acontecer agora, em 10 minutos ou 30 minutos.&lt;br&gt;
Então podemos entender que esta comunicação não precisa ser síncrona! Podemos resolver esta comunicação utilizando uma fila de mensagens. Dessa forma, o serviço Estoque pode enviar quantas mensagens quiser para a fila, que conforme o serviço OrdemDeServico estiver disponível, ele irá consumir as mensagens da fila para processamento.&lt;br&gt;
Vamos utilizar o RabbitMQ como broker de mensagens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jA-7y600--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8b6y2yzl3ykfptjbaca0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jA-7y600--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8b6y2yzl3ykfptjbaca0.png" alt="Imagem mostrando fila do RabbitMQ controlando chamadas entre os serviços"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pronto! Primeiro problema resolvido. Agora caso o microsserviço OrdemDeProducao esteja fora do ar ou com muita lentidão, não irá causar impacto para o microsserviço Estoque.&lt;br&gt;
A imagem abaixo mostra que mesmo que o serviço OrdemDeProducao nao consiga processar nada, o Estoque pode continuar disparando mensagens sem qualquer problema.&lt;br&gt;
Quando a OrdemDeProducao voltar a funcionar, as mensagens que estão na fila voltam a ser processadas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jKXnZ-1W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dmwvc3lvva1agdf5uacn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jKXnZ-1W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dmwvc3lvva1agdf5uacn.png" alt="Imagem mostrando que falhas na OrdemDeProducao não impacta no servico de Estoque"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mas ainda temos outro problema! &lt;br&gt;
Imagine que o serviço OrdemDeProducao está falhando, porque algum outro serviço está fora do ar. Digamos que seja o banco de dados que não está respondendo.&lt;br&gt;
O que acontece com a mensagem que estamos tentando processar?&lt;/p&gt;

&lt;p&gt;Poderíamos jogar novamente a mensagem na fila, para continuar tentando reprocessar!!!&lt;br&gt;
Na verdade, não é bem assim.&lt;/p&gt;

&lt;p&gt;Se jogarmos novamente a mensagem para a fila, imediatamente o serviço OrdemDeProducao irá consumir a mensagem e tentar processá-la. Em um cenário que temos muitas mensagens na fila, estaríamos apenas executando à toa repetida e rapidamente sem necessidade.&lt;/p&gt;

&lt;p&gt;Aí que entra uma feature bacana do RabbitMQ, chamada &lt;a href="https://www.rabbitmq.com/blog/2015/04/16/scheduling-messages-with-rabbitmq/"&gt;Delayed Messages&lt;/a&gt;.&lt;br&gt;
Caso o processamento da mensagem falhe, podemos jogá-la novamente na fila, mas informando que ela deve ser processada novamente apenas daqui a alguns minutos.&lt;br&gt;
Dessa forma, antes de tentar reprocessar a mensagem, existe um tempo que podemos aguardar esperando que a falha seja resolvida.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_BvkWuPq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ymobg8vaj8823hbumo5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_BvkWuPq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ymobg8vaj8823hbumo5o.png" alt="Imagem mostrando a mensagem com propriedade de delay sendo devolvida para a fila"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Dead Letter Queue (DLQ)
&lt;/h1&gt;

&lt;p&gt;O que acontece se ocorrer de muitas mensagens acumularem na fila?&lt;br&gt;
As mensagens excedentes que forem chegando, podem ser diretamente desviadas para uma fila chamada dead-letter-queue (DLQ).&lt;/p&gt;

&lt;p&gt;Inclusive, podemos fazer uso de mais outra feature, chamada &lt;a href="https://www.rabbitmq.com/dlx.html#effects"&gt;Dead-Lettered Effects&lt;/a&gt;. Assim podemos melhorar ainda mais nosso processo de retentativas, adicionando uma quantidade máxima de retentativas no header da mensagem. Caso o número máximo de retentativas seja ultrapassado, podemos desviar a mensagem com falha para aí sim ocorrer a análise manual da situação.&lt;br&gt;
Podemos por exemplo, definir que a quantidade máxima de retentativas será 3 vezes e após estas falhas, a mensagem será desviada para outra DLQ para armazenamento e disparar um alerta para a pessoa responsável analisar manualmente a situação.&lt;/p&gt;

&lt;p&gt;Caso o problema tenha sido apenas indisponibilidade de algum serviço e a solução seja apenas reprocessar as mensagens, exite um plugin chamado &lt;a href="https://www.rabbitmq.com/shovel.html"&gt;Shovel&lt;/a&gt; que permite jogar todas mensagens de uma fila para outra.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9vPhDJLx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jgu5qrvfug1k0v4cacsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9vPhDJLx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jgu5qrvfug1k0v4cacsw.png" alt="Solução final utilizando uma fila normal, delayed messages e uma fila DLQ"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resumo da solução
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A comunicação era síncrona (HTTP). Ao identificar que ela pode ser assíncrona, passamos a realizar a comunicação utilizando mensageria. &lt;/li&gt;
&lt;li&gt;Em caso de falha no processamento da mensagem, ela será enviada novamente para a fila com um tempo de delay até a próxima retentativa.&lt;/li&gt;
&lt;li&gt;Definimos uma quantidade máxima de retentativas. Caso seja atingida a quantidade máxima, a mensagem é desviada para uma DLQ, onde aguardará por tratamento manual.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A solução é bem mais complexa do que uma simples requisição HTTP, mas agora conseguimos garantir que mesmo que o serviço OrdemDeProducao esteja com algum problema, ele não irá impactar o Estoque. &lt;br&gt;
O isolamento de um problema é algo bastante importante que deve ser lembrado ao desenhar uma solução.&lt;br&gt;
Também estamos evitando a análise manual por qualquer tipo de falha, dando a oportunidade para o sistema se recuperar e dar vazão no processamento das mensagens sem intervenção humana.&lt;br&gt;
Neste exemplo do artigo, a intervenção humana só é necessária em casos graves de falha onde a OrdemDeProducao não consegue de forma alguma voltar a processar as mensagens.&lt;/p&gt;

&lt;p&gt;Ah, mais uma coisa! Embora o exemplo acima esteja mostrando microsserviços separados para Estoque e OrdemDeProducao, essa solução também pode ser adaptada para processamento assíncrono em projetos monolíticos.&lt;/p&gt;

&lt;p&gt;No próxima parte eu irei mostrar a implementação da solução.&lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>go</category>
      <category>rabbitmq</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Socorro! Como posso organizar os pacotes em Go?</title>
      <dc:creator>Odilon Jonathan Kröger</dc:creator>
      <pubDate>Sun, 23 Feb 2020 20:34:56 +0000</pubDate>
      <link>https://forem.com/odilonjk/socorro-como-posso-organizar-os-pacotes-em-go-km0</link>
      <guid>https://forem.com/odilonjk/socorro-como-posso-organizar-os-pacotes-em-go-km0</guid>
      <description>&lt;p&gt;Hoje vou falar a respeito de algo que tive certa dificuldade quando comecei a mexer com Go, que é a organização de pacotes.&lt;br&gt;
Para falar a verdade, esse assunto não tem uma resposta rígida. Por quê? Simples, se você navegar pelo GitHub, encontrará projetos Go com diferentes tipos de estruturação. Por exemplo, a biblioteca &lt;a href="https://github.com/segmentio/kafka-go"&gt;kafka-go&lt;/a&gt; da &lt;a href="https://segment.com/"&gt;Segment&lt;/a&gt; utiliza uma estrutura completamente diferente da biblioteca &lt;a href="https://github.com/confluentinc/confluent-kafka-go"&gt;confluent-kafka-go&lt;/a&gt; da &lt;a href="https://www.confluent.io/"&gt;Confluent&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que a documentação oficial tem a dizer sobre pacotes?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Programas Go são organizados em pacotes. Um pacote é uma coleção de arquivos fonte dentro de um mesmo diretório e que são compilados em conjunto. Funções, tipos, variáveis e constantes definidos em um arquivo fonte são visíveis para todos outros arquivos fonte dentro de um mesmo pacote. (Tradução minha).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vou resumir aqui um pouco a &lt;a href="https://golang.org/doc/code.html#Organization"&gt;documentação oficial&lt;/a&gt;, sem entrar nos detalhes do uso de módulos. O código é bastante similar ao da documentação oficial, com pequenas alterações e alguma tradução.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y3-kR03L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ntmb2wp60lbty5x9gr3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y3-kR03L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ntmb2wp60lbty5x9gr3t.png" alt="Base"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como podemos ver, existe o diretório raiz chamado &lt;code&gt;estrutura-de-pacotes&lt;/code&gt; com dois arquivos dentro, &lt;code&gt;ola_mundo.go&lt;/code&gt; e &lt;code&gt;ola_mundo_test.go&lt;/code&gt;.&lt;br&gt;
Até aqui nenhum mistério.&lt;br&gt;
Se observar na imagem, estamos no &lt;code&gt;package main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mas considerando que eu vou criar um pacote novo, chamado &lt;code&gt;strutil&lt;/code&gt;, todo arquivo que existir dentro dele, é visível para ele mesmo, mas não para o pacote raíz. Em outras palavras, para utilizar o código que está dentro do arquivo &lt;code&gt;strutil.go&lt;/code&gt; em outros pacotes, no meu caso o pacote raíz, é necessário importar o pacote no arquivo &lt;code&gt;ola_mundo.go&lt;/code&gt; e &lt;code&gt;ola_mundo_test.go&lt;/code&gt;, conforme a imagem abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Lcy_yKf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/otujj8qfgagb19uo2muu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Lcy_yKf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/otujj8qfgagb19uo2muu.png" alt="Pacote main e strutil"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ah, um detalhe! Para que a função consiga ser exportada para outros pacotes como no caso acima, o nome da função precisa iniciar com letra maiúscula. Se eu tivesse utilizado o nome &lt;code&gt;reverter()&lt;/code&gt; em vez de &lt;code&gt;Reverter()&lt;/code&gt;, não seria possível utilizar a função dentro do arquivo &lt;code&gt;ola_mundo.go&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xTLAY8Lj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nuzhuszv91x7if5ncuzl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xTLAY8Lj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nuzhuszv91x7if5ncuzl.png" alt="Arquivo strutil.go"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No mundo Go é uma boa prática comentar as funções que podem ser exportadas, pois gerando o &lt;code&gt;godoc&lt;/code&gt;, o comentário aparece na documentação.&lt;br&gt;
Algumas pessoas podem dizer que um bom código não precisa de comentários, mas quando o código será exposto por uma documentação &lt;code&gt;godoc&lt;/code&gt; para alguém fazer uso da nossa API por exemplo, simples comentários podem ajudar muito nosso cliente.&lt;br&gt;
O artigo &lt;a href="https://rakyll.org/style-packages/"&gt;Style guideline for Go packages&lt;/a&gt; inclusive fala que é um bom exercício ficar de olho no &lt;code&gt;godoc&lt;/code&gt; no início do projeto, para ler e validar se realmente faz sentido a separação de pacotes que está sendo utilizada.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HJ-9PM8T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cn33e1w81pgwhx5qte2r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HJ-9PM8T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cn33e1w81pgwhx5qte2r.png" alt="godoc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com a leitura acima, podemos entender que um pacote fica contido dentro de um diretório e caso eu necessite utilizar em outros pacotes, preciso importar o pacote com o código desejado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como eu devo nomear os pacotes?
&lt;/h2&gt;

&lt;p&gt;Existe uma &lt;a href="https://blog.golang.org/package-names"&gt;publicação&lt;/a&gt; feita pelo &lt;a href="https://twitter.com/sajma"&gt;Sameer Ajmani&lt;/a&gt;, com detalhes sobre essa questão. Mas existem alguns pontos básicos que vou explicar aqui.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O nome de um pacote deve ser curto e fácil de entender, mas sem comprometer a sua "intenção". Por exemplo, se eu quero escrever um pacote com utilidades relacionadas ao banco de dados, meu pacote poderia se chamar &lt;code&gt;dbutil&lt;/code&gt;. Alguém pode pensar em chamar de &lt;code&gt;util&lt;/code&gt;, mas como o nome é genérico demais, acaba prejudicando o entendimento do que tudo pode existir dentro do pacote.&lt;/li&gt;
&lt;li&gt;O uso de sublinhado &lt;code&gt;_&lt;/code&gt;, hífen &lt;code&gt;-&lt;/code&gt; ou letras maiúsculas é desencorajado. Por exemplo, posso chamar um pacote de &lt;code&gt;validacaologin&lt;/code&gt;, mas eu não deveria chama-lo de &lt;code&gt;validacaoLogin&lt;/code&gt;, &lt;code&gt;validacao-login&lt;/code&gt; ou ainda &lt;code&gt;validacao_login&lt;/code&gt;. Porém, como eu disse no início da publicação, diferentes empresas podem seguir seus próprios padrões, como pode ser observado no repositório do &lt;a href="https://github.com/kubernetes/kubernetes"&gt;kubernetes&lt;/a&gt;. Eu percebi que é difícil encontrar repositórios com pacotes cujo nome contém mais de uma palavra. Acredito ser boa abordagem se esforçar para utilizar apenas uma palavra como nome de pacote.&lt;/li&gt;
&lt;li&gt;Abreviação é permitida, mas eu particularmente prefiro utiliza-la com cuidado. Exemplos de pacotes com nome abreviado: &lt;code&gt;cmd&lt;/code&gt;, &lt;code&gt;fmt&lt;/code&gt;, &lt;code&gt;bufio&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pacotes dentro de diretórios diferentes podem ter o mesmo nome. Por exemplo, posso ter &lt;code&gt;cobranca/lancamento&lt;/code&gt; e também &lt;code&gt;investimento/lancamento&lt;/code&gt;. Mas atenção! Se esses pacotes forem importados com frequência no mesmo lugar, o ideal é que um deles seja renomeado se possível, evitando problemas de entendimento.&lt;/li&gt;
&lt;li&gt;Os diretórios dos pacotes podem ser criados da melhor forma que você encontrar para organizar o código. Você pode criar um diretório onde colocará um determinado domínio, ou ainda um diretório onde ficará concentrado todo código relacionado à algum tipo de computação específica.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://twitter.com/rakyll"&gt;Jaana Dogan-Dalgaard&lt;/a&gt; chama atenção para algo que nós que viemos de outras linguagens acabamos estranhando. O nome do pacote deveria ser no singular e &lt;a href="https://rakyll.org/style-packages/#no-plurals"&gt;não no plural&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Afinal, existe algum padrão adotado?
&lt;/h2&gt;

&lt;p&gt;Como mencionei acima, é possível encontrar diversos tipos de estruturas pelo GitHub. Mas existe um repositório com a sugestão de um padrão bem genérico que você pode ter como base, chamado &lt;a href="https://github.com/golang-standards/project-layout"&gt;golang-standards/project-layout&lt;/a&gt;.&lt;br&gt;
Esse layout não é oficial e dependendo do tamanho do seu projeto, utiliza-lo seria complicar demais as coisas. Comece sempre da forma mais simples possível e vá adicionando novos pacotes conforme a necessidade for surgindo.&lt;/p&gt;

&lt;p&gt;Alguns pacotes que são encontrados com frequência em projetos Go e que são explicados no README deste repositório. De forma resumida:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cmd&lt;/code&gt; é o pacote onde você concetra os seus arquivos &lt;code&gt;main.go&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;internal&lt;/code&gt; é o pacote onde fica o código que você não quer expor para fora da aplicação ou biblioteca. Conforme vimos acima, é possível ter vários pacotes &lt;code&gt;internal&lt;/code&gt; dentro de diferentes diretórios.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pkg&lt;/code&gt; é o pacote onde fica o código que pretendo expor para ser utilizado em outras aplicações. O código exposto aqui será utilizado por outras pessoas, portanto escolha com cuidado o código que ficará dentro deste pacote. Você pode encontrar &lt;a href="https://github.com/golang-standards/project-layout/blob/master/pkg/README.md"&gt;aqui&lt;/a&gt; uma lista de repositórios que usa este padrão.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vendor&lt;/code&gt; é o pacote onde você pode adicionar suas dependências.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;api&lt;/code&gt; é onde você pode colocar schemas de JSON, Swagger, etc.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configs&lt;/code&gt; é onde ficam arquivos comuns de configuração. Observe que o nome é no plural!&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scripts&lt;/code&gt; é utilizado para concentrar os scripts utilizados pela aplicação. Existe um ótimo exemplo no &lt;a href="https://github.com/hashicorp/terraform/tree/master/scripts"&gt;repositório&lt;/a&gt; do Terraform.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deployments&lt;/code&gt; é utilizado para os arquivos docker-compose, de Terraform, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Atenção para quem vem do Java como eu vim! É muito comum que a gente pense logo em criar um pacote chamado &lt;code&gt;src&lt;/code&gt;, porém essa prática é desencorajada, conforme a &lt;a href="https://github.com/golang-standards/project-layout#src"&gt;documentação&lt;/a&gt; do layout que citei acima. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You really don't want your Go code or Go projects to look like Java :-)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Como posso amadurecer a estrutura do meu projeto? Posso usar DDD?
&lt;/h2&gt;

&lt;p&gt;Existe uma palestra, da &lt;a href="https://twitter.com/kasiazien"&gt;Kat Zień&lt;/a&gt; que mostra como estruturar um projeto, utilizado apenas um diretório e ir evoluindo conforme a necessidade até atingir uma estrutura baseada em DDD.&lt;br&gt;
Vou deixar &lt;a href="https://youtu.be/VQym87o91f8"&gt;aqui&lt;/a&gt; para a palestra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluindo...
&lt;/h2&gt;

&lt;p&gt;No fim das contas, como Go é uma linguagem nova e bastante versátil, por mais que existam alguns padrões surgindo, dependendo do projeto faz mais sentido seguir um ou outro caminho. Pra mim essa é uma característica que amo em Go, a flexibilidade.&lt;br&gt;
Quando for estruturar o projeto, siga as boas práticas de comentar pacotes e funções que serão expostas, validando no &lt;code&gt;godoc&lt;/code&gt; se faz sentido. Converse com sua equipe e com pessoas de outros lugares, como no &lt;a href="https://invite.slack.golangbridge.org/"&gt;Slack do Gophers&lt;/a&gt; para entender como outros projetos estão sendo feitos e quais prós e contras foram encontrados.&lt;br&gt;
Considere também aquilo que fica mais confortável para sua equipe. De nada adianta criar uma guerra interna por causa da nomenclatura de pacotes e não ter o projeto entregue!&lt;/p&gt;

&lt;p&gt;Por favor, não esqueça de cobrir o seu código com testes. ; )&lt;/p&gt;




&lt;p&gt;Todos artigos que utilizei para estudar e criar esta publicação foram citados acima com seus respectivos links.&lt;/p&gt;

&lt;p&gt;Foto de de capa feita por &lt;a href="https://www.pexels.com/pt-br/@apasaric"&gt;Aleksandar Pasaric&lt;/a&gt; no &lt;a href="https://www.pexels.com/pt-br/foto/amontoado-cartao-cartolina-castanho-1555199/?utm_content=attributionCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=pexels"&gt;Pexels&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Seu primeiro serviço Go na Google Cloud App Engine.</title>
      <dc:creator>Odilon Jonathan Kröger</dc:creator>
      <pubDate>Tue, 18 Feb 2020 21:33:45 +0000</pubDate>
      <link>https://forem.com/odilonjk/seu-primeiro-servico-go-na-google-cloud-app-engine-310a</link>
      <guid>https://forem.com/odilonjk/seu-primeiro-servico-go-na-google-cloud-app-engine-310a</guid>
      <description>&lt;p&gt;Você já pensou em subir um serviço na &lt;strong&gt;Google Cloud&lt;/strong&gt; (GCP) mas não sabe por onde começar?&lt;br&gt;
Então acompanhe essa publicação onde mostrarei como subir um serviço simples utilizando a &lt;strong&gt;GCP App Engine&lt;/strong&gt;. É mais fácil o que parece! :)&lt;br&gt;
Ah, sabe aquelas playlists de LoFi Hip Hop (tem no Youtube, Spotify, etc.)? É uma boa pedida para acompanhar a leitura. ;D&lt;/p&gt;
&lt;h2&gt;
  
  
  Primeiros passos
&lt;/h2&gt;

&lt;p&gt;Antes de mais nada, e necessário criar uma conta na &lt;a href="https://cloud.google.com/"&gt;Google Cloud&lt;/a&gt;.&lt;br&gt;
Você irá receber um valor de bônus para testar a plataforma. Não precisa se preocupar, esse exemplo não chega nem perto de causar algum gasto para você. Mas é importante &lt;strong&gt;SEMPRE&lt;/strong&gt; que for parar de realizar testes, parar os serviços para evitar surpresas no futuro. &lt;/p&gt;

&lt;p&gt;Feita a conta, agora vamos acessar o &lt;a href="https://console.cloud.google.com/"&gt;console&lt;/a&gt; da plataforma.&lt;br&gt;
No canto direito, é possível ir em preferências e escolher o idioma que você prefere, seja português, inglês ou outro.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OF-4eMsE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/t6m84y0yj7u86jkqtgvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OF-4eMsE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/t6m84y0yj7u86jkqtgvp.png" alt="Preferências"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beleza, agora no canto esquerdo, é possível selecionar um projeto ou criar um novo. Clique ali nessa opção, pois iremos criar um projeto novo! :D&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9foSAf53--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sb07wz8u04qhu3h93hhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9foSAf53--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sb07wz8u04qhu3h93hhb.png" alt="Selecionar projeto"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesta nova tela, clique em &lt;strong&gt;novo projeto&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nQR0xpfE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5pv94whq9w08z7vbytbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nQR0xpfE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5pv94whq9w08z7vbytbr.png" alt="Novo projeto"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A tela a seguir é bastante intuitiva, como podemos ver abaixo. Eu coloquei no nome do projeto como sendo &lt;em&gt;primeiro-servico-gcp&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aEl428SI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cp22ryuzgx6dngjjw0aa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aEl428SI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cp22ryuzgx6dngjjw0aa.png" alt="Meu primeiro serviço GCP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pronto! Agora que já temos um projeto criado na GCP, podemos seguir para os próximos passos. ^^&lt;/p&gt;
&lt;h2&gt;
  
  
  Criando o primeiro serviço
&lt;/h2&gt;

&lt;p&gt;Vamos abrir o &lt;strong&gt;Menu de navegação&lt;/strong&gt; no canto esquerdo superior. Basta acessar o menu e em seguida &lt;strong&gt;App Engine -&amp;gt; Painel&lt;/strong&gt;.&lt;br&gt;
Se tudo der certo, provavelmente você verá a tela abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pSt3IO1w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jfwf3qtj7zm1bhdyclt5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pSt3IO1w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jfwf3qtj7zm1bhdyclt5.png" alt="Criar aplicativo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basta clicar em &lt;strong&gt;Criar aplicativo&lt;/strong&gt;. No próximo passo você deve escolher a partir de qual região você quer que seu código fique rodando. Pode manter como &lt;strong&gt;US Central&lt;/strong&gt;. Cada região tem uma tabela de preços e também uma gama diferente de serviços disponíveis, mas para nosso exemplo isso não faz diferença, então não precisa se preocupar com isso.&lt;/p&gt;

&lt;p&gt;Após selecionar a região, chegou o momento de escolher qual linguagem vamos utilizar. Para esse exemplo a linguagem escolhida foi Go ❤️.&lt;br&gt;
Para o campo &lt;strong&gt;Environment&lt;/strong&gt;, pode deixar &lt;strong&gt;Padrão&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7HGucucf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0euzvxk71q60f2mjdoy0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7HGucucf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0euzvxk71q60f2mjdoy0.png" alt="Aplicativo em Go"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mais uma etapa concluída! Agora falta pouco.&lt;/p&gt;
&lt;h2&gt;
  
  
  Utilizando Cloud Shell
&lt;/h2&gt;

&lt;p&gt;Uma das formas de criar a aplicação e realizar o deploy, é criando o código com seu editor favorito (Atom, VS Code, Sublime, etc.), baixando a &lt;strong&gt;SDK&lt;/strong&gt; da GCP e realizando o deploy pelo seu terminal.&lt;br&gt;
Outra forma, é utilizar o próprio terminal, chamado de &lt;strong&gt;Cloud Shell&lt;/strong&gt; que a GCP nos oferece. Essa é a forma que vamos utilizar hoje. &lt;br&gt;
Caso você já queira baixar a SDK para utilizar no futuro, basta acessar o &lt;a href="https://cloud.google.com/sdk/docs/quickstarts/?hl=pt_BR"&gt;Quickstart&lt;/a&gt; e selecionar de acordo com o seu sistema operacional. Se vocês quiserem, posso escrever uma publicação falando sobre isso! :D&lt;/p&gt;

&lt;p&gt;Bom, vamos voltar ao assunto de hoje!&lt;br&gt;
No canto superior direito, conseguimos acessar o Cloud Shell que utilizaremos. Pense no Cloud Shell como sendo um terminal rodando na plataforma da Google Cloud, que já tem a SDK deles instalada e mais algumas outras coisinhas, como o &lt;a href="https://www.vim.org/"&gt;Vim&lt;/a&gt; e &lt;a href="https://www.nano-editor.org/"&gt;nano&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UIOJDSMq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s8cq00rv6mmljcf8oqhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UIOJDSMq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s8cq00rv6mmljcf8oqhw.png" alt="Menu Cloud Shell"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicando nesse botão acima, você irá acessar o Cloud Shell, que aparecerá na parte inferior da tela. Se for da sua preferência, você pode expandir o Cloud Shell para cima, de forma que ocupe praticamente o browser inteiro. Eu gosto de utilizar o terminal assim, então fica assim a tela:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rOhSJlGK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7bezjmb9v1u7ijiq4c85.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rOhSJlGK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7bezjmb9v1u7ijiq4c85.png" alt="Cloud Shell aberto"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você quiser, pode rodar o comando &lt;code&gt;go version&lt;/code&gt;, que verá a versão atual instalada no seu ambiente.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quero código! Cadê?
&lt;/h2&gt;

&lt;p&gt;Lá vamos nós! Código!!!&lt;br&gt;
Primeiro vamos acessar o diretório &lt;code&gt;gopath&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;cd gopath&lt;/code&gt;&lt;br&gt;
Em seguida, vamos criar o diretório do nosso serviço. Você pode, por exemplo, executar o comando abaixo.&lt;br&gt;
&lt;code&gt;mkdir meu_primeiro_servico &amp;amp;&amp;amp; cd $_&lt;/code&gt;&lt;br&gt;
Esse comando cria o diretório &lt;strong&gt;meu_primeiro_servico&lt;/strong&gt; e logo em seguida usa o comando &lt;code&gt;$_&lt;/code&gt; para entrar no diretório recém criado.&lt;/p&gt;

&lt;p&gt;A primeira coisa que vamos criar, é um arquivo de configuração, necessário para rodar o serviço. Vamos utilizar o editor &lt;strong&gt;nano&lt;/strong&gt; para codificar, ou se você preferir o &lt;strong&gt;Vim&lt;/strong&gt;, também pode ser utilizado. &lt;br&gt;
Execute o comando abaixo para criar o arquivo &lt;code&gt;app.yaml&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;nano app.yaml&lt;/code&gt;&lt;br&gt;
Agora com o editor aberto no arquivo, basta adicionar a linha: &lt;code&gt;runtime: go113&lt;/code&gt;. Como na imagem abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ICC00taj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wigh9fsygt1opekn79w4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ICC00taj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wigh9fsygt1opekn79w4.png" alt="app.yaml"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora basta pressionar Ctrl+o e em seguida Enter para salvar o arquivo. Para sair do nano, pressione Ctrl+x.&lt;/p&gt;

&lt;p&gt;E finalmente, vamos o código Go. É possível criar um projeto modularizado, mas para esta publicação, vou seguir o caminho mais simples. Crie o arquivo com o comando abaixo.&lt;br&gt;
&lt;code&gt;nano main.go&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dentro do arquivo, vamos iniciar informando que é o pacote main. Em seguida adicionamos os imports necessários:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos também criar a função &lt;strong&gt;main&lt;/strong&gt;, conforme abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imprimirOlaMundo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PORT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"8080"&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Utilizando porta padrão %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta função está utilizando o client HTTP nativo da linguagem Go. Nele estamos monitorando chamadas para o caminho raiz &lt;code&gt;/&lt;/code&gt;. Também tem uma condição, para caso não tenha sido setada uma porta no ambiente, seja utilizada a porta &lt;code&gt;8080&lt;/code&gt;. Mas você não precisa se preocupar com isso agora.&lt;br&gt;
Também foram adicionados alguns logs, apenas para informar qual porta está sendo utilizada.&lt;/p&gt;

&lt;p&gt;Repare que no mapeamento do caminho &lt;code&gt;/&lt;/code&gt;, estamos chamando a função &lt;strong&gt;imprimirOlaMundo&lt;/strong&gt;. Bora lá implementar essa função!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;imprimirOlaMundo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Olá mundo! Eu consegui!!! :D"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa função recebe por parâmetro o &lt;code&gt;http.ResponseWriter&lt;/code&gt; e o ponteiro &lt;code&gt;*http.Request&lt;/code&gt;. É o padrão do client HTTP que mencionei acima.&lt;br&gt;
Dentro da função basta imprimir a mensagem desejada, que no nosso caso é um Olá mundo.&lt;/p&gt;

&lt;p&gt;Seu arquivo deve estar parecido como o da imagem abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--84nN_FaE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lqfsuersvi834wfuq5tc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--84nN_FaE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lqfsuersvi834wfuq5tc.png" alt="main.go"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para salvar o arquivo, novamente utilize Ctrl+o e em seguida Enter. Para sair pressione Ctrl+x.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chegou a hora do deploy!
&lt;/h2&gt;

&lt;p&gt;Agora que temos os arquivos &lt;code&gt;app.yaml&lt;/code&gt; e &lt;code&gt;main.go&lt;/code&gt; criados, vamos realizar o deploy do serviço. É muito simples! Basta executar o comando abaixo.&lt;br&gt;
&lt;code&gt;gcloud app deploy&lt;/code&gt;&lt;br&gt;
Ele vai pedir para continuar, basta responder com &lt;code&gt;y&lt;/code&gt;.&lt;br&gt;
Pronto! Seu serviço já está disponível na nuvem!!! \o/&lt;br&gt;
Provavelmente no seu Cloud Shell, você deve estar vendo algo similar ao que existe na imagem abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u_twpY2u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7whck0dr571sj3mjd6eb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u_twpY2u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7whck0dr571sj3mjd6eb.png" alt="Deploy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note que os logs inclusive nos informam o endereço onde o serviço está disponível. Basta copiar o endereço e abrir em uma nova aba do seu browser para testar o seu serviço.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yPXkjW8B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f2voahk2a630opbb557y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yPXkjW8B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f2voahk2a630opbb557y.png" alt="Olá mundo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Meus parabéns!!! Você acabou de disponibilizar seu primeiro serviço utilizando App Engine da GCP!&lt;/p&gt;

&lt;p&gt;Ah, agora você já pode fechar o Cloud Shell. O botão de fechar fica na parte superior do Cloud Shell, no canto direito.&lt;/p&gt;

&lt;h2&gt;
  
  
  E agora?
&lt;/h2&gt;

&lt;p&gt;Se você quiser ver dados sobre suas chamadas do serviço, pode ir no &lt;strong&gt;Menu de navegação&lt;/strong&gt; no canto superior esquerdo, &lt;strong&gt;App Engine -&amp;gt; Painel&lt;/strong&gt;. Nessa tela existem dados como quantas chamadas foram realizadas e até mesmo o custo.&lt;/p&gt;

&lt;p&gt;Como eu mencionei no início da publicação, após realizarmos nossos testes, é sempre bom desligar os serviços, apenas para evitar ficar no esquecimento e daqui um ano receber uma conta indesejada. Acredite, já vi isso acontecer mais de uma vez com colegas de trabalho.&lt;br&gt;
Para desligar o serviço, vamos acessar o &lt;strong&gt;Menu de navegação&lt;/strong&gt; no canto superior esquerdo e ir em &lt;strong&gt;IAM e Admin -&amp;gt; Configurações&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2mqk8dim--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kjn0ynpl0ozdesn04xvi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2mqk8dim--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kjn0ynpl0ozdesn04xvi.png" alt="Menu IAM e Admin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em seguida, com o projeto que acabos de criar selecionado, basta clicar em encerrar e na tela que for abrir, para permitir o encerramento do projeto, preencher o campo com o nome do projeto e confirmar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Y2AOV5k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9a5ejwqkc3shxkrmow22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Y2AOV5k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9a5ejwqkc3shxkrmow22.png" alt="Encerrar projeto"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Prontinho! Agora não precisa se preocupar em receber uma conta por causa de algum serviço que ficou de pé. &lt;/p&gt;

&lt;h2&gt;
  
  
  Curtiu?
&lt;/h2&gt;

&lt;p&gt;E aí, curtiu a experiência de criar um serviço na nuvem utilizando GCP? Achou complicado, achou fácil? Deixe seu comentário abaixo. :)&lt;/p&gt;

</description>
      <category>go</category>
      <category>gcp</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
