Sobes.tech
Middle+

¿Qué patrones de microservicios conoces?

sobes.tech AI

Respuesta de la IA

  • Descubrimiento de servicios: Permite que los servicios se encuentren entre sí. Se implementa a través de un registro centralizado (por ejemplo, ZooKeeper, Consul, etcd).
  • API Gateway: Punto de entrada único para los clientes, que enruta las solicitudes a los servicios correspondientes. Proporciona autenticación, autorización y balanceo de carga.
  • Circuit Breaker (Interruptor automático): Previene fallos en cascada, desconectando temporalmente las llamadas a servicios defectuosos.
  • Bulkhead: Aísla los recursos de diferentes servicios, evitando su influencia mutua en caso de fallos.
  • Saga: Gestiona transacciones distribuidas, asegurando la coherencia de los datos entre varios servicios mediante una secuencia de transacciones locales y acciones compensatorias.
  • Event Sourcing (Almacenamiento orientado a eventos): Guarda todos los cambios de datos en forma de secuencia de eventos, proporcionando un historial completo de estados.
  • CQRS (Segregación de responsabilidades de comando y consulta): Divide la lógica de lectura y escritura de datos en modelos diferentes, optimizando el rendimiento para cada tipo de operación.
  • Base de datos por servicio: A cada servicio se le asigna su propia base de datos para garantizar independencia y descentralización.
  • Strangler Fig: Sustitución progresiva de una aplicación monolítica por microservicios, redirigiendo partes del tráfico.

Ejemplo de implementación de Circuit Breaker en PHP (pseudocódigo):

<?php
// Clase Circuit Breaker
class CircuitBreaker
{
    private $threshold; // Umbral de fallos
    private $timeout; // Tiempo que el interruptor permanece abierto
    private $failures = 0; // Número actual de fallos
    private $lastFailureTime = 0; // Tiempo del último fallo
    private $state = 'CLOSED'; // Estado actual: 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';
                    // Intento de ejecutar en estado HALF-OPEN
                    try {
                        $result = $operation();
                        $this->reset(); // Éxito, reiniciar
                        return $result;
                    } catch (\Exception $e) {
                        $this->recordFailure(); // Fallo en HALF-OPEN, volver a OPEN
                        throw $e;
                    }
                } else {
                    throw new \Exception("Circuit breaker is open"); // Interruptor abierto
                }
                break;
            case 'HALF_OPEN':
                // La lógica en HALF_OPEN ya está arriba
                break;
            case 'CLOSED':
            default:
                try {
                    $result = $operation();
                    $this->reset(); // Éxito, reiniciar
                    return $result;
                } catch (\Exception $e) {
                    $this->recordFailure(); // Fallo, incrementar contador
                    throw $e;
                }
                break;
        }
    }

    private function recordFailure(): void
    {
        $this->failures++;
        $this->lastFailureTime = time();
        if ($this->failures >= $this->threshold) {
            $this->state = 'OPEN'; // Cambio a OPEN al alcanzar el umbral
        }
    }

    private function reset(): void
    {
        $this->failures = 0;
        $this->lastFailureTime = 0;
        $this->state = 'CLOSED'; // Cambio a CLOSED en éxito
    }
}

// Uso
$breaker = new CircuitBreaker(3, 60); // Umbral 3 fallos, timeout 60 segundos

try {
    $data = $breaker->execute(function() {
        // Código para llamar a un servicio externo
        if (rand(0, 1) == 0) { // Simulación de fallo
             throw new \Exception("Service unavailable");
        }
        return ['status' => 'ok'];
    });
    echo "Success: " . json_encode($data) . "\n";
} catch (\Exception $e) {
    echo "Failure: " . $e->getMessage() . "\n";
}