Назад к вопросам
Middle+
144
questionbank

Какие микросервисные паттерны вы знаете?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

  • Service Discovery: Позволяет сервисам находить друг друга. Реализуется через централизованный реестр (например, ZooKeeper, Consul, etcd).
  • API Gateway: Единая точка входа для клиентов, маршрутизирующая запросы к соответствующим сервисам. Обеспечивает аутентификацию, авторизацию, балансировку нагрузки.
  • Circuit Breaker (Автоматический выключатель): Предотвращает каскадные сбои, временно отключая вызовы к неисправным сервисам.
  • Bulkhead: Изолирует ресурсы разных сервисов, предотвращая их взаимное влияние при сбоях.
  • Saga: Управляет распределенными транзакциями, обеспечивая согласованность данных между несколькими сервисами с помощью последовательности локальных транзакций и компенсирующих действий.
  • Event Sourcing (Событийно-ориентированное хранилище): Хранит все изменения данных в виде последовательности событий, обеспечивая полную историю состояний.
  • CQRS (Command Query Responsibility Segregation): Разделяет логику чтения и записи данных на разные модели, оптимизируя производительность для каждого типа операций.
  • Database per Service (База данных на сервис): Каждому сервису выделяется собственная база данных для обеспечения независимости и децентрализации.
  • Strangler Fig: Постепенное замещение монолитного приложения микросервисами, перенаправляя части трафика.

Пример реализации Circuit Breaker в PHP (псевдокод):

<?php
// Класс Circuit Breaker
class CircuitBreaker
{
    private $threshold; // Порог количества сбоев
    private $timeout; // Время, в течение которого выключатель остается открытым
    private $failures = 0; // Текущее количество сбоев
    private $lastFailureTime = 0; // Время последнего сбоя
    private $state = 'CLOSED'; // Текущее состояние: CLOSED, OPEN, HALF_OPEN

    public function __construct(int $threshold, int $timeout)
    {
        $this->threshold = $threshold;
        $this->timeout = $timeout;
    }

    public function execute(callable $operation)
    {
        switch ($this->state) {
            case 'OPEN':
                if (time() - $this->lastFailureTime > $this->timeout) {
                    $this->state = 'HALF_OPEN';
                    // Попытка выполнить операцию в HALF-OPEN состоянии
                    try {
                        $result = $operation();
                        $this->reset(); // Успех, сброс
                        return $result;
                    } catch (\Exception $e) {
                        $this->recordFailure(); // Сбой в HALF-OPEN, возврат в OPEN
                        throw $e;
                    }
                } else {
                    throw new \Exception("Circuit breaker is open"); // Выключатель открыт
                }
                break;
            case 'HALF_OPEN':
                // Логика обработки в HALF_OPEN уже есть выше
                break;
            case 'CLOSED':
            default:
                try {
                    $result = $operation();
                    $this->reset(); // Успех, сброс
                    return $result;
                } catch (\Exception $e) {
                    $this->recordFailure(); // Сбой, увеличение счетчика
                    throw $e;
                }
                break;
        }
    }

    private function recordFailure(): void
    {
        $this->failures++;
        $this->lastFailureTime = time();
        if ($this->failures >= $this->threshold) {
            $this->state = 'OPEN'; // Переход в OPEN при достижении порога
        }
    }

    private function reset(): void
    {
        $this->failures = 0;
        $this->lastFailureTime = 0;
        $this->state = 'CLOSED'; // Переход в CLOSED при успехе
    }
}

// Использование
$breaker = new CircuitBreaker(3, 60); // Порог 3 сбоя, таймаут 60 секунд

try {
    $data = $breaker->execute(function() {
        // Код вызова внешнего сервиса
        if (rand(0, 1) == 0) { // Имитация сбоя
             throw new \Exception("Service unavailable");
        }
        return ['status' => 'ok'];
    });
    echo "Success: " . json_encode($data) . "\n";
} catch (\Exception $e) {
    echo "Failure: " . $e->getMessage() . "\n";
}