Ответ
В микросервисной архитектуре используется множество паттернов для решения типичных проблем распределенных систем. Вот некоторые из ключевых:
-
API Gateway: Единая точка входа для всех клиентских запросов. Он маршрутизирует запросы к нужным сервисам, а также может выполнять аутентификацию, логирование, кэширование и rate limiting.
-
Service Discovery: Механизм для автоматического обнаружения сетевого местоположения (IP-адрес и порт) экземпляров сервисов. Позволяет сервисам находить друг друга без жестко прописанных адресов. Примеры: Consul, etcd, Zookeeper.
-
Circuit Breaker (Предохранитель): Защищает систему от каскадных сбоев. Если сервис-зависимость начинает возвращать ошибки, Circuit Breaker "размыкается" и перестает отправлять на него запросы на некоторое время, возвращая ошибку немедленно. Это дает сбойному сервису время на восстановление.
-
Database per Service: Каждый микросервис управляет своей собственной базой данных. Это обеспечивает слабую связанность (loose coupling), так как изменения в схеме данных одного сервиса не влияют на другие.
-
Saga Pattern: Паттерн для управления распределенными транзакциями. Вместо одной большой ACID-транзакции используется последовательность локальных транзакций в каждом сервисе. Если одна из них сбоит, выполняются компенсирующие транзакции для отката изменений.
-
CQRS (Command Query Responsibility Segregation): Разделение операций на команды (изменение данных) и запросы (чтение данных). Это позволяет независимо масштабировать и оптимизировать модели для чтения и записи.
Пример реализации Circuit Breaker в Go:
import (
"time"
"github.com/sony/gobreaker"
)
var cb *gobreaker.CircuitBreaker
func init() {
settings := gobreaker.Settings{
Name: "my-external-service",
MaxRequests: 1,
Timeout: 5 * time.Second,
ReadyToTrip: func(counts gobreaker.Counts) bool {
return counts.ConsecutiveFailures > 3
},
}
cb = gobreaker.NewCircuitBreaker(settings)
}
func CallMyService() (interface{}, error) {
body, err := cb.Execute(func() (interface{}, error) {
// Логика вызова внешнего сервиса
return externalAPI.GetData()
})
if err != nil {
return nil, err
}
return body, nil
}