Создание микросервиса с Golang, Kafka и DynamoDB — часть I
Как заставить Голанг и Кафку работать вместе
В этих двух сериях постов я хочу в основном рассказать о своем начальном опыте создания микросервиса для отслеживания транспортных средств с использованием Golang, Kafka и DynamoDB. Я пришел из мира Python, создаю веб-приложения и серверные системы, используя Django, Flask, Postgres и RabbitMQ в качестве брокера сообщений. В первом посте будет рассказано о том, как объединить эти технологии для создания скелета микросервиса, а в следующем будет рассказано об интеграции с DynamoDB, простых оптимизациях и улучшениях для масштабирования. Почему? Потому что мне потребовалось не только некоторое время, чтобы понять это и найти четкое и лаконичное решение, но и найти довольно интересные технологии для работы.
Краткое введение в микросервисы
В традиционном монолитном приложении все функции организации записываются в одно приложение или группируются на основе требуемого бизнес-продукта. Иногда они группируются по типу, например контроллеры, модели, фабрики и т. д. В других случаях, возможно, в более крупном приложении, функции разделяются по проблемам (SOC), по функциям или доменам. Таким образом, у вас может быть пакет авторизации, пакет пользователей и пакет статей. Которые могут содержать свой собственный набор фабрик, сервисов, репозиториев, моделей и т. д. Но в конечном итоге они сгруппированы в рамках единой кодовой базы.
Микросервис — это концепция дальнейшего развития второго подхода и разделения этих проблем на мелкие независимые исполняемые кодовые базы.
Почему микросервисы?
Сложность. Разделение функций на микросервисы позволяет разделить код на более мелкие фрагменты. Это восходит к старой пословице Unix о том, что нужно «делать одно дело хорошо». У монолитов есть тенденция позволять доменам становиться тесно связанными друг с другом, а задачи становиться размытыми. Это приводит к более рискованным, более сложным обновлениям, потенциально большему количеству ошибок и более сложным интеграциям.
Масштаб — в монолите одни области кода могут использоваться чаще, чем другие. С монолитом вы можете масштабировать только всю кодовую базу. Поэтому, если ваша служба аутентификации постоянно работает, вам нужно масштабировать всю кодовую базу, чтобы справиться с нагрузкой только для вашей службы аутентификации.
С микросервисами все становится более детализированным, включая масштабируемость и управление скачками спроса. Спрос на один компонент приложения или определенное подмножество данных может резко возрасти, а архитектура микросервисов позволяет масштабировать только затронутые компоненты приложения, а не все приложение и базовую инфраструктуру. Наряду с преимуществами MSA (микросервисной архитектуры) есть несколько недостатков, таких как поддержка микросервисов, увеличение использования сети, работа с распределенными системами, сложность развертывания и т. д.
Зачем Golang создавать микросервисы?
Микросервисы поддерживаются практически всеми языками, в конце концов, микросервисы — это концепция, а не конкретная структура или инструмент. При этом некоторые языки лучше подходят и лучше поддерживают микросервисы, чем другие. Одним из языков с отличной поддержкой является Golang.
Golang очень легкий, очень быстрый и имеет фантастическую поддержку параллелизма, которая является мощной возможностью при работе на нескольких машинах и ядрах.
Golang также содержит очень мощные стандартные библиотеки для написания веб-сервисов. Наконец, для Go доступен фантастический микросервисный фреймворк под названием го-микро который мы будем использовать в этой серии.
Мартин Фаулер опубликовал отличный обзор Микросервисы. Когда дело доходит до Голанга, концепции остаются прежними; небольшие службы с единой ответственностью, которые взаимодействуют через HTTP, TCP или очередь сообщений.
При публикации API для общего пользования HTTP и JSON стали стандартом. Тем не менее, я предпочитаю межсервисную связь. гугл/протобуф библиотека.
Буферы протоколов — это способ кодирования структурированных данных в эффективном, но расширяемом формате. Google использует протокольные буферы почти для всех своих внутренних протоколов RPC и форматов файлов.
Буферы протоколов позволяют службам обмениваться данными друг с другом с помощью определенного контракта (и без всех накладных расходов на сериализацию JSON). Служба API, которая принимает запрос HTTP/JSON, а затем использует RPC/Protobuf для связи между внутренними службами RPC. В следующем примере оказание услуг это собственное автономное приложение Golang.
Ниже показано, как location.proto файл выглядит как
// declare proto syntax
syntax = "proto3";
// declare package name
package service.location;
// declare RPC services
service LocationService {
rpc GetLocation(LocationRequest) returns (LocationResponse) {}
}
// declare request and response messages
message LocationRequest {
int32 user_id = 1;
}
message LocationResponse {
string timestamp = 1;
double latitude = 2;
double longitude = 3;
int32 user_id = 4;
}
Служба API будет сбрасывать данные о местоположении в теме Kafka. Но перед этим нам нужно создать производителя Kafka, написанного с использованием ритмкоторая представляет собой библиотеку Go для Apache Kafka и сарама-кластеркоторая является библиотекой Go для расширений Cluster для Sarama.
Конфигурация производителя Kafka
Ознакомьтесь с дополнительными параметрами конфигурации производителя..
Опубликуйте сообщение, используя реализацию интерфейса ниже.
type LocationTrackingProducer interface {
PublishMessage(messageValue sarama.ByteEncoder, partitionHashKey string) error
}
А потом на сервис.местоположение Сначала мы написали, что потребитель получает данные из темы Kafka и сохраняет их в DynamoDB.
Кафка потребитель
В сервис.местоположение мы также будем реализовывать ПолучитьРасположение чтобы предоставить это как метод RPC другим службам/API. Ниже показано, как обработчик.go будет выглядеть
type LocationServiceHandler struct {
repo repository.Repository
}
func NewLocationServiceHandler(repo repository.Repository) *LocationServiceHandler {
return &LocationServiceHandler{repo: repo}
}
func (d *LocationServiceHandler) GetLocation(ctx context.Context, request *locationProto.LocationsRequest, response *locationProto.LocationsResponse) error {
if request.UserId == 0 {
return errors.New("Received an invalid user ID")
}
// get location data from dynamoDB
locationData, err := d.repo.GetLocation(request.UserId)
if err != nil {
return err
}
response = locationData
return nil
}
и мы зарегистрируем обработчик выше с помощью сервиса go-micro, ниже показано, как будет выглядеть main.go.
func main() {
locationRepo := &LocationRepository{} // Create a new service.
srv := micro.NewService(
micro.Name("service.location"),
micro.Version("latest"),
)
locationClient := locationProto.NewLocationServiceClient("service.location", srv.Client())
// Init will parse the command line flags.
srv.Init()
// Register handler
locationProto.RegisterLocationServiceHandler(srv.Server(), handler.NewLocationServiceHandler(locationRepo))
// Run the server
if err := srv.Run(); err != nil {
fmt.Println(err)
}
}
Вот и все. В следующей части этой серии мы попытаемся оптимизировать производительность реализованных выше сервисов. Любые ошибки, ошибки или отзывы об этой статье или что-либо, что вы считаете полезным, пожалуйста, оставьте комментарий.
дальнейшее чтение
https://www.nginx.com/blog/introduction-to-microservices/
https://martinfowler.com/articles/microservices.html
https://medium.facilelogin.com/ten-talks-on-microservices-you-cannot-miss-at-any-cost-7bbe5ab7f43f
https://ewanvalentine.io/microservices-in-golang-part-1/
http://microservices.io/patterns/monolithic.html
https://www.quora.com/How-is-Go-programming-language-used-in-microservice-architecture
Это обертка.
Надеюсь, вам понравится, и вы извлечете из этого уроки. Спасибо._
Счастливого обучения.