Neste artigo, descreverei o uso do kit Go, um conjunto de ferramentas e bibliotecas para criar microsserviços no Go. Este artigo é uma introdução ao kit Go. A primeira parte do meu blog, o código fonte dos exemplos, está disponível aqui .
Go é cada vez mais escolhido para o desenvolvimento de sistemas distribuídos modernos. Ao desenvolver um sistema distribuído baseado em nuvem, pode ser necessário oferecer suporte a várias funcionalidades específicas em seus serviços, como: vários protocolos de transporte ( etc. trad. HTTP, gRPC, etc. ) e formatos de codificação de mensagens para eles, confiabilidade de RPC, registro em log , rastreamento, métricas e criação de perfil, interrompendo solicitações, limitando o número de solicitações, integração à infraestrutura e até descrevendo a arquitetura. O Go é uma linguagem popular devido à sua simplicidade e abordagens “sem mágica”, portanto, os pacotes Go, por exemplo, uma biblioteca padrão, já são mais adequados para o desenvolvimento de sistemas distribuídos do que o uso de uma estrutura completa com muita “mágica escondida”. Pessoalmente, eu [ aprox. trans. Shiju Varghese ] Eu não apoio o uso de estruturas completas, eu prefiro usar bibliotecas que dão mais liberdade ao desenvolvedor. O kit Go preencheu uma lacuna no ecossistema Go, possibilitando o uso de um conjunto de bibliotecas e pacotes ao criar microsserviços, o que, por sua vez, permite o uso de bons princípios para o design de serviços individuais em sistemas distribuídos.

Introdução ao kit Go
O kit Go é um conjunto de pacotes Go que facilitam a criação de microsserviços confiáveis e compatíveis. O kit Go fornece bibliotecas para implementar vários componentes de uma arquitetura de aplicativo transparente e confiável, usando camadas como: registro, métricas, rastreamento, limitação e interrupção de solicitações necessárias para executar microsserviços no produto. O kit Go é bom porque possui ferramentas bem implementadas para interagir com várias infra-estruturas, formatos de codificação de mensagens e várias camadas de transporte.
Além do conjunto de bibliotecas para o desenvolvimento de serviços mundiais, ele fornece e incentiva o uso de bons princípios para projetar a arquitetura de seus serviços. O kit Go ajuda a respeitar os princípios do SOLID, a abordagem orientada ao assunto (DDD) e a arquitetura hexagonal proposta por Alistair Cockburn ou qualquer outra abordagem de arquitetura conhecida como “ arquitetura de cebola ” por Jeffrey Palermo e “ arquitetura limpa ” por Robert C. Martin . Embora o kit Go tenha sido projetado como um conjunto de pacotes para o desenvolvimento de microsserviços, ele também é adequado para o desenvolvimento de monólitos elegantes.
Kit de arquitetura Go
Os três níveis principais na arquitetura de aplicativos desenvolvidos usando o kit Go são:
- nível de transporte
- nível do ponto final
- nível de serviço
Nível de transporte
Quando você escreve microsserviços para sistemas distribuídos, os serviços neles geralmente precisam se comunicar usando vários protocolos de transporte, como: HTTP ou gRPC, ou usam sistemas pub / subs, como NATS. A camada de transporte no kit Go está vinculada a um protocolo de transporte específico (a seguir designado transporte). O kit Go suporta vários transportes para o seu serviço, como: HTTP, gRPC, NATS, AMQP e Thirft ( aprox. Também é possível desenvolver seu próprio transporte para o seu protocolo ). Portanto, os serviços escritos usando o kit Go geralmente se concentram na implementação de uma lógica comercial específica que não sabe nada sobre o transporte usado; você pode usar transportes diferentes para o mesmo serviço. Como exemplo, um serviço escrito no kit Go pode fornecer acesso a ele simultaneamente via HTTP e gRPC.
Pontos finais
Um ponto final ou ponto final é o alicerce fundamental para serviços e clientes. No kit Go, o principal padrão de comunicação é o RPC. O terminal é apresentado como um método RPC separado. Cada método de serviço no kit Go é convertido em um terminal, permitindo a comunicação entre o servidor e o cliente no estilo RCP. Cada nó de extremidade expõe um método de serviço usando a camada Transporte, que por sua vez usa vários protocolos de transporte, como HTTP ou gRPC. Um terminal separado pode ser exposto fora do serviço simultaneamente usando vários transportes ( aprox. Por HTTP e gRPC em portas diferentes ).
Serviços
A lógica de negócios é implementada na camada de serviço. Os serviços escritos com o kit Go são projetados como interfaces. A lógica de negócios na camada de serviço contém o principal núcleo da lógica de negócios, que não precisa saber nada sobre os terminais usados ou um protocolo de transporte específico, como HTTP ou gRPC, ou sobre solicitações e respostas de codificação ou decodificação de vários tipos de mensagens. Isso permitirá que você adote uma arquitetura limpa nos serviços escritos usando o kit Go. Cada método de serviço é convertido no terminal usando um adaptador e exposto fora usando um transporte específico. Através do uso de arquitetura limpa, um único método pode ser definido usando vários transportes ao mesmo tempo.
Exemplos
E agora vamos ver as camadas descritas acima usando um exemplo de um aplicativo simples.
Lógica de negócios no serviço
A lógica de negócios no serviço é projetada usando interfaces. Vamos considerar o exemplo de um pedido no comércio eletrônico:
A interface do serviço de pedidos funciona com a entidade do domínio do pedido:
Aqui implementamos a interface do serviço de pedidos:
package implementation import ( "context" "database/sql" "time" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/gofrs/uuid" ordersvc "github.com/shijuvar/gokit-examples/services/order" )
Solicitações e respostas para terminais RPC
Os métodos de serviço são expostos como pontos de extremidade RPC. Portanto, precisamos determinar os tipos de mensagens ( aprox. Por DTO - objeto de transferência de dados ) que serão usadas para enviar e receber mensagens através dos pontos de extremidade RPC. Vamos agora definir estruturas para tipos de solicitação e resposta para terminais RPC no serviço de pedidos:
Terminais do kit Go para métodos de serviço como terminais RPC
O núcleo da nossa lógica de negócios é separado do restante do código e colocado na camada de serviço, que é exposta usando pontos de extremidade RPC, que usam a abstração do kit Go chamada Endpoint
.
É assim que o ponto de extremidade do kit Go se parece:
type Endpoint func(ctx context.Context, request interface{}) (response interface{}, err error)
Como dissemos acima, o terminal representa um método RPC separado. Cada método de serviço é convertido em endpoint.Endpoint
usando adaptadores. Vamos criar pontos de extremidade do kit Go para métodos de serviço Order:
import ( "context" "github.com/go-kit/kit/endpoint" "github.com/shijuvar/gokit-examples/services/order" )
O adaptador de nó de extremidade aceita a interface como um parâmetro para a entrada e a converte em uma abstração do endpoint.Enpoint
kit Go. Faça com que cada método de serviço individual seja um nó de extremidade. Essa função do adaptador faz comparação e digita conversões para solicitações, chama um método de serviço e retorna uma mensagem de resposta.
func makeCreateEndpoint(s order.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(CreateRequest) id, err := s.Create(ctx, req.Order) return CreateResponse{ID: id, Err: err}, nil } }
Expondo um serviço usando HTTP
Criamos nosso serviço e descrevemos os pontos de extremidade de RPC para expor nossos métodos de serviço. Agora precisamos publicar nosso serviço fora para que outros serviços possam chamar pontos de extremidade RCP. Para expor nosso serviço, precisamos determinar o protocolo de transporte para o nosso serviço, de acordo com o qual ele aceitará solicitações. O kit Go suporta vários transportes, como HTTP, gRPC, NATS, AMQP e Thrift, prontos para uso.
Por exemplo, usamos o transporte HTTP para o nosso serviço. O pacote go kit github.com/go-kit/kit/transport/http fornece a capacidade de atender solicitações HTTP. E a função NewServer
do pacote transport/http
criará um novo servidor http que implementará o http.Handler
e http.Handler
os pontos de extremidade fornecidos.
Abaixo está o código que converte os pontos de extremidade do kit Go em um transporte HTTP que atende a solicitações HTTP:
package http import ( "context" "encoding/json" "errors" "github.com/shijuvar/gokit-examples/services/order" "net/http" "github.com/go-kit/kit/log" kithttp "github.com/go-kit/kit/transport/http" "github.com/gorilla/mux" "github.com/shijuvar/gokit-examples/services/order/transport" ) var ( ErrBadRouting = errors.New("bad routing") )
Criamos http.Handler
usando a função http.Handler
do pacote transport/http
, que fornece pontos de extremidade e funções de decodificação de solicitação (retorna o valor do type DecodeRequestFunc func
) e codificação de resposta (por exemplo, type EncodeReponseFunc func
).
A seguir, exemplos de DecodeRequestFunc
e EncodeResponseFunc
:
Iniciando servidor HTTP
Finalmente, podemos executar nosso servidor HTTP para processar solicitações. A função NewService
descrita acima implementa a interface http.Handler
que nos permite executá-la como um servidor HTTP:
func main() { var ( httpAddr = flag.String("http.addr", ":8080", "HTTP listen address") ) flag.Parse() var logger log.Logger { logger = log.NewLogfmtLogger(os.Stderr) logger = log.NewSyncLogger(logger) logger = level.NewFilter(logger, level.AllowDebug()) logger = log.With(logger, "svc", "order", "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller, ) } level.Info(logger).Log("msg", "service started") defer level.Info(logger).Log("msg", "service ended") var db *sql.DB { var err error
Agora, nosso serviço é iniciado e usa o protocolo HTTP no nível de transporte. O mesmo serviço pode ser iniciado usando outro transporte, por exemplo, um serviço pode ser exposto usando gRPC ou Apache Thrift.
Para o artigo introdutório, já usamos o suficiente as primitivas do kit Go, mas também fornece mais funcionalidade para criar sistemas de padrões transparentes e confiáveis, descoberta de serviços, balanceamento de carga etc. Discutiremos essas e outras coisas no kit Go nos seguintes artigos.
Código fonte
O código fonte completo para os exemplos pode ser visualizado no GitHub aqui.
Middlewares no kit Go
O kit Go predispõe ao uso de bons princípios de design de sistema, como camadas. O isolamento de componentes de serviço e pontos de extremidade é possível usando Middlewares ( aprox. Padrão do mediador de faixa ). Os middlewares no kit Go fornecem um mecanismo poderoso pelo qual você pode agrupar serviços e terminais e adicionar funcionalidades (componentes isolados), como registro em log, interrupção de solicitação, limitação do número de solicitações, balanceamento de carga ou rastreamento distribuído.
Abaixo está uma foto do site do kit Go , que é representada como uma “arquitetura de cebola” típica usando Middlewares no kit Go:

Cuidado com a síndrome de microsserviços de inicialização por mola
Como o kit Go, o Spring Boot é um kit de ferramentas de microsserviço no mundo Java. Mas, diferentemente do kit Go, o Spring Boot é uma estrutura muito madura. Além disso, muitos desenvolvedores Java usam o Spring Boot para criar serviços mundiais usando a pilha Java com feedback positivo do uso, alguns deles acreditam que os microsserviços são apenas sobre o uso do Spring Boot. Vejo muitas equipes de desenvolvimento que interpretam mal o uso de microsserviços, que eles só podem ser desenvolvidos usando o Spring Boot e o Netflix OSS e não percebem os microsserviços como um padrão no desenvolvimento de sistemas distribuídos.
Portanto, lembre-se de que, com um conjunto de ferramentas, como um kit Go ou algum tipo de estrutura, você direciona seu desenvolvimento para microssensibilidades, como um padrão de design. Embora os microsserviços resolvam muitos problemas de dimensionamento de comandos e sistemas, eles também criam muitos problemas porque os dados nos sistemas de microsserviço estão espalhados por vários bancos de dados, o que às vezes cria muitos problemas ao criar consultas transacionais ou de dados. Tudo depende do problema da área de assunto e do contexto do seu sistema. O legal é que o kit Go, projetado como uma ferramenta para criar microsserviços, também foi adequado para criar monólitos elegantes criados com um bom design de arquitetura para seus sistemas.
E alguns recursos do kit Go, como interromper e restringir solicitações, também estão disponíveis em plataformas de malha de serviço, como o Istio. Portanto, se você usar algo como o Istio para iniciar suas microsseguranças, talvez não precise de algumas coisas do kit Go, mas nem todos terão largura de canal suficiente para usar a malha de serviço para criar comunicação entre serviços, pois isso adiciona mais um nível e complexidade extra.
PS
O autor da tradução não pode compartilhar a opinião do autor do texto original . Este artigo foi traduzido para fins educacionais apenas para a comunidade de idiomas russo Go.
UPD
Este também é o primeiro artigo na seção de tradução e eu ficaria grato por qualquer feedback sobre a tradução.