Микросервисные приложения на GoMicro

от автора

Go благодаря возможностям компиляции и встроенным механизмам конкурентной многозадачности очень хорошо подходит для создания сетевых приложений и активно используется в создании инструментов для DevOps и распределенных приложений. В этой статье мы рассмотрим некоторые возможности фреймворка GoMicro для реализации микросервисных приложений на Go.

В микросервисной архитектуре одним из наиболее важных аспектов является механизм передачи данных внутри распределенного приложения и GoMicro поддерживает как использование REST, так и возможность применения очередей сообщений для обмена данных как в подходе RPC, так и для реализации архитектуры реактивных приложений, основанных на событиях. GoMicro основан на использовании расширяемой архитектуры и представляет большое количество важных подсистем для реализации микросервисов:

  • Аутентификация и авторизация обеспечивают для каждого сервиса идентификатор и сертификаты и реализует управление доступом на основе правил.

  • Хранилище данных — простой интерфейс хранилища данных для чтения, записи и удаления записей. Данные могут быть сохранены как в память, так и во внешнее хранилище.

  • Динамическая конфигурация — загрузка и обновление в реальном времени динамической конфигурации из любого места. Интерфейс конфигурации предоставляет способ загрузки конфигурации уровня приложения из любого источника, такого как переменные окружения, файл и т. д. Источники могут быть объединены и можно определить способ отката на другой источник или указать значения по умолчанию.

  • Механизм обнаружения сервисов — автоматическая регистрация сервисов и разрешение имен (по умолчанию на основе mDNS).

  • Балансировка нагрузки — балансировка нагрузки на стороне клиента, основанная на обнаружении сервисов. Нагрузка распределяется равномерно между несколькими реализациями сервисами с автоматическим переключением при наличии ошибок.

  • Кодирование сообщений — возможность кодирования сообщений в JSON / Protobuf.

  • Клиент/сервер RPC — запрос/ответ на основе RPC с поддержкой двунаправленной потоковой передачи.

  • Асинхронный обмен сообщениями — PubSub является основой для распределенных приложений, управляемых событиями (на основе HTTP-запросов).

  • Потоковая передача событий реализует поддержку потоков NATS Jetstream и Redis.

  • Синхронизация. Поддерживается распределенная блокировка и протокол динамического выбора лидера среди доступного кворума.

  • Подключаемые интерфейсы — Go Micro использует интерфейсы Go для каждой абстракции распределенной системы и позволяет создавать собственные реализации для каждого компонента.

Для подключения GoMicro нужно установить и импортировать модуль из «go-micro.dev/v4» и дальше использовать его методы для управления создаваемым сервисом. Также в модулях в github.com/go-micro/plugins/v4/… доступны плагины, которых делятся на следующие категории:

  • broker — взаимодействие с брокерами сообщений для реализации потоковой передачи сообщений (NATS, RabbitMQ, Kafka)

  • client — клиенты для запросов к другим микросервисам (через RPC, gRPC или HTTP)

  • server — серверный компонент для обеспечения доступа к микросервису (RPC, gRPC, HTTP)

  • codec — кодирование сообщений в BSON, Mercury, Protobuf

  • config — управление распределенной конфигурацией

  • registry — регистрация и обнаружение сервисов (в том числе, может взаимодействовать с Kubernetes)

  • selector — балансировка нагрузки

  • transport — двухсторонняя передача данных через NATS или RabbitMQ

  • wrapper — дополнительные middleware (например, логирование, трассировка запросов, ограничение скорости запросов и т.д.)

Создание сервиса начинается с вызова NewService и дальнейшей инициализации созданной структуры. Также сразу может быть выполнена регистрация сервиса и настройка способов обнаружения других сервисов, подключены серверные и клиентские компоненты.

package main  import ( "go-micro.dev/v4"   "github.com/go-micro/plugins/v4/registry/kubernetes"   grpcc "github.com/go-micro/plugins/v4/client/grpc" grpcs "github.com/go-micro/plugins/v4/server/grpc" )  func main() {     registry := kubernetes.NewRegistry() service := micro.NewService( micro.Name("my.service"),         micro.Registry(registry),         micro.Server(grpcs.NewServer()), micro.Client(grpcc.NewClient()), )     service.Server().handle() service.Init()     service.Run() }

Далее для реализации обработчиков и вызовов удаленных методов могут использоваться механизмы кодогенерации для protobuf (protoc-gen-go), для доступа к зарегистрированным компонентам используются методы в service. Например, для получения доступа к объекту сервера можно обратиться к service.Server(), аналогично для подключения к сгенерированному клиенту service.Client() и т.д. При наличии proto-файла и сгенерированного описания методов и протокола взаимодействия с микросервисом, вызов может выглядеть следующим образом (в pb импортирован структура, сгенерированная protoc-gen-go)

if err := pb.RegisterPaymentServiceHandler(srv.Server(), new(handler.PaymentService)); err != nil { logger.Fatal(err) }

При этом сам proto-файл описывает все аспекты взаимодействия с микросервисом и определяет дополнительные типы данных (перечисления, структуры и др.), например:

syntax = "proto3";  package shop;  option go_package = "./proto;shop";  service Health {   rpc Check(HealthCheckRequest) returns (HealthCheckResponse) {}   rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse) {} }  message HealthCheckRequest {  string service = 1; }  message HealthCheckResponse {   enum ServingStatus {     UNKNOWN = 0;     SERVING = 1;     NOT_SERVING = 2;     SERVICE_UNKNOWN = 3;   }   ServingStatus status = 1; }

При использовании реестров сервисов можно делать дополнительные обработки (например, создавать реализации селекторов для поиска подходящих сервисов). Также достаточно просто интегрируются очереди сообщений:

package main  import ( "fmt"  "context" "go-micro.dev/v4" )  func pub(i int, p micro.Publisher) { msg := &Message{ Say: fmt.Sprintf("This is an async message %d", i), }  if err := p.Publish(context.TODO(), msg); err != nil { fmt.Println("pub err: ", err) return }  fmt.Printf("Published %d: %v\n", i, msg) }  func main() { service := micro.NewService() service.Init()  p := micro.NewPublisher("example", service.Client())  for i := 0; i < 10; i++ { pub(i, p) } }

Аналогично можно создавать распределенные конфигурации, обнаруживать сервисы (через registry), создавать клиентов RPC, подписываться на появление сообщений в очередях RabbitMQ/Kafka. Также доступны механизмы для конфигурирования heartbeat (для проверки доступности и корректного функционирования сервисов):

service := micro.NewService( micro.Name("payment"),   micro.RegisterInterval(time.Second*30), micro.RegisterTTL(time.Second*120), )

Дополнительно можно подключать собственные расширения с использованием micro.WrapHandler:

import (     "log" "go-micro.dev/v4" "go-micro.dev/v4/server" )  func logWrapper(fn server.HandlerFunc) server.HandlerFunc { return func(ctx context.Context, req server.Request, rsp interface{}) error { log.Printf("[request]: %v", req.Endpoint()) err := fn(ctx, req, rsp) return err } }  func main() { service := micro.NewService( micro.Name("greeter"), // wrap the handler micro.WrapHandler(logWrapper), )  service.Init()  proto.RegisterHandler(service.Server(), new(PaymentService))  if err := service.Run(); err != nil { fmt.Println(err) } }

Для мониторинга запущенных микросервисов может использоваться GoMicro Dashboard, который может быть установлен через go install github.com/go-micro/dashboard@latest.

Таким образом, MicroGo представляет легковесный и расширяемый фреймворк для разработки микросервисов, который обеспечивает разрабатываемые компоненты основными возможностями для безопасного доступа и обнаружения других микросервисов, хранением данных, взаимодействию через HTTP/gRPC или очереди сообщений и другими важными аспектами для реализации микросервисной архитектуры.

В завершение приглашаю на бесплатный урок, где мы рассмотрим плюсы и минусы монолитов и микросервисов, а также основные паттерны в микросервисной архитектуре.


ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/718388/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *