Implementando comunicação com API gRPC

Dando continuidade na implementação de serviços utilizando gRPC, nesse post vamos implementar o lado cliente da comunicação.

Se você ainda não leu o post anterior, onde implementamos a API em gRPC, peço que leia, pois os passos para definição do arquivo proto e geração do código utilizando protoc, foram feitos lá e não precisam ser repetidos.

Conexão com API

Vamos iniciar a implementação do client.go definindo as credenciais de conexão.

creds := grpc.WithTransportCredentials(insecure.NewCredentials())
Leia mais »

Como utilizar o framework Echo

Mesmo sem saber ainda se será uma série ou não, nesse post, trago uma visão geral sobre um dos frameworks mais populares do mundo Go, o Echo.

Em sua documentação, o framework Echo se autodenomina como de alta performance, extensível e minimalista. Além dessas características, podemos dizer também que é de fácil implementação. Veja o exemplo abaixo.

package main

import (
    "net/http"
    
    "github.com/labstack/echo/v4"
)

func main() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })
    e.Logger.Fatal(e.Start(":1323"))
}
Leia mais »

O que é e como configurar affinity e anti-affinity no Kubernetes

Embora o Kubernetes faça um ótimo trabalho em escalonar os pods de um cluster, algumas vezes, e SOMENTE algumas vezes (note o negrito, itálico e sublinhado), precisamos controlar como e onde os pods serão escalonados.

Para resolver esses casos, que são (ou pelo menos deveriam ser) raros de acontecer, utilizamos as funcionalidades de Affinity e Anti-Affinity do Kubernetes.

Ao utilizar essas funcionalidades, podemos decidir em quais tipos de nodes os pods serão escalonados, além de especificar que determinados pods sejam escalonados próximos ou distantes uns dos outros.

Também “dizemos” ao Kubernetes qual é a expectativa sobre as condições definidas no Affinity ou Anti-Affinity. Em outras palavras, precisamos dizer se as condições precisam ser atendidas (modo hard), ou se seria bom que elas fossem atendidas (modo soft).

Para o modo hard, utilizamos a chave requiredDuringSchedulingIgnoreDuringExecution. Já para o modo soft, a chave preferredDuringSchedulingIgnoreDuringExecution.

Leia mais »

Como injetar valores em variáveis com ldflags

Uma feature pouco conhecida para quem está iniciando na linguagem Go, é a capacidade de injetarmos valores em variáveis durante o processo de build. Embora possa parecer um tanto quanto estranho fazer isso, essa técnica nos possibilita adicionar informações como versão, data e commit do build, sem a necessidade de commitar essas informações. Embora possamos criar essas variáveis no mesmo arquivo onde estará a função main da aplicação, eu prefiro fazer algo que possa ser reutilizado.

Definindo as variáveis de build

Por isso, pensando em um repositório onde haverão várias aplicações, ou até mesmo em uma estrutura de monorepo, vamos criar um package dentro da pasta pkg chamado build. Dentro do package, vamos criar um arquivo chamado version.go com o seguinte conteúdo.

Leia mais »

Implementando uma API com protobuf e gRPC

Dando continuidade ao post o que é e como utilizar protobufs, nesse post, vamos colocar o conhecimento teórico em prática e fazer uma API utilizando protobuf e gRPC. Embora seja uma API simples, ela te dará uma ótima base para construir aplicações mais complexas.

Dependências

Mas antes de meter a mão na massa, precisamos instalar o protoc e os pluginsprotoc-gen-go e protoc-gen-go-grpc. Para instalar o protoc, independente do OS que você esteja utilizando, recomendo fazer download do binário direto da página de releases do projeto. Após o download, descompacte e mova o programa protoc, que está dentro da pasta bin, em alguma pasta que esteja referenciada ao seu $PATH, por exemplo, a pasta go/bin ou ~/.local/bin. Com o protoc instalado, agora precisamos instalar os dois plugins para gerar código Go. Partindo do princípio que você tem o Go instalado na sua máquina, execute os dois comandos abaixo para instalar os plugins.

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
Leia mais »

O que é arquitetura hexagonal

Nesse primeiro post sobre arquitetura de software, vamos falar um pouco sobre a arquitetura hexagonal. Proposta em 2005 por Alistair Cockburn, a arquitetura hexagonal visa um projeto com:

  • Separação de responsabilidades: cada componente tem sua responsabilidade bem definida.
  • Foco na regra de negócio: a separação de camadas e componentes, proporciona um melhor detalhamento e foco na regra de negócio da aplicação.
  • Paralelização de trabalho: como a arquitetura hexagonal define muito bem as responsabilidades de cada componente, é possível paralelizar trabalho facilmente.
  • Isolamento de testes: devido a baixa dependência entre componente, escrever testes de qualidade, se torna uma tarefa muito mais simples.
  • Mudança de infraestrutura: como existe uma separação entre a regra de negócio e a camada que se comunica com o mundo exterior, mudar do MySQL para Postgres é menos doloroso do que em aplicações que não seguem a arquitetura hexagonal.

Em outras palavras, utilizar a arquitetura hexagonal faz com que um projeto seja escalável, de fácil manutenção e produtivo na hora de ser implementado.

Agora vamos entender os termos e camadas da arquitetura hexagonal.

Leia mais »
Namespace Kubernetes

O que é e como criar Namespace no Kubernetes

Dando continuidade aos nossos posts sobre Kubernetes, vamos falar sobre Namespace.

Esse recurso do Kubernetes pode ser utilizado de diversas formas. Algumas pessoas criam namespaces para separar ambientes dentro de um mesmo cluster, enquanto outras preferem criar namespaces para cada time ou produto que a empresa tem.

Definindo Namespace

Independente do propósito, a finalidade dos namespaces sempre será a mesma, particionar o cluster em subdivisões lógicas.

Para ajudar com a imagem mental, imagine que namespaces são como pastas do seu computador, onde você pode definir qualquer divisão que quiser. No entanto, diferente de pastas, onde você consegue colocar uma dentro da outra, no caso dos namespaces, não existem “sub-namespaces”.

Leia mais »

O que é e como utilizar protocol buffers

Protocol buffers, protobuf ou simplesmente proto, é uma linguagem criada pela Google para serialização de dados. Para facilitar o entendimento, podemos comparar o protobuf com XML ou JSON. No entanto, dados serializados com proto, são MUITO menores quando comparados com as outras duas tecnologias.

Outro ponto importante é que, após escrever um arquivo proto, utilizamos um programa chamado protoc para gerar código em Go, Java, Python, C#, C, C++, entre outras linguagens. Código esse que contém todas as classes e métodos que estiverem declarados dentro dos arquivos proto.

Mas calma! Antes de falar mais sobre esse código gerado, vamos entender o que compõe e como criar um arquivo proto.

Syntax

A primeira coisa que precisamos fazer em um arquivo proto é definir sua syntax. Essa syntax nada mais é do que a versão do protobuf que iremos utilizar.

Leia mais »

Qual a diferença e quando utilizar Deployment, StatefulSet e DaemonSet

Hoje iniciamos uma nova série aqui no blog, a Kubernetes 101. Nessa série, vou escrever sobre o funcionamento e utilização do Kubernetes do ponto de vista dev. Em outras palavras, não vamos entrar nos detalhes e funcionamentos internos do orquestrador, mas sim como utilizá-lo para executar aplicações.

E para começar essa série, nada melhor do que explicar as diferenças e aplicabilidades dos objetos Deployment, StatefulSet e DaemonSet.

Deployments

Esse tipo de objeto do Kubernetes serve como uma espécie de supervisor. Seu papel principal é registrar algumas informações no Kubernetes, como por exemplo, os nomes das imagens que compõe um Pod e o número de réplicas a serem executadas.

A utilização de objetos do tipo Deployment é recomendada para aplicações que não dependem de um estado, ou seja, aplicações stateless. Se você não está familiarizado com o termo, uma aplicação stateless, basicamente, caso tenha sua execução interrompida, uma nova instância pode ser executada sem nenhuma dependência da execução anterior. Salvo algumas exceções, normalmente esse tipo de aplicação não precisa de um disco para ser executada.

Leia mais »

O que é e como aplicar Single Responsibility

Chegamos ao último post da série sobre SOLID. Nele, vamos abordar como implementar o S, ou seja, Single Responsibility Principle.

Para você que chegou agora e ainda não viu os outros posts da série, vou deixar os links aqui:

Definindo Single Responsibility

Em algumas literaturas, vamos encontrar a definição de Single Responsibility como: “uma classe só pode ter uma única função”.

Embora seja totalmente válida essa definição, infelizmente ela pode levar à alguns equívocos, como por exemplo, implementar uma classe para cada operação com o banco de dados.

Equívoco totalmente aceitável. Afinal, uma classe que salva e busca dados em um banco de dados, não estaria tendo duas funções?!

Leia mais »