Microsserviços em PHP: da teoria à produção
A transição de um monólito para uma arquitetura de microsserviços em PHP não é apenas uma atualização tecnológica, mas uma mudança fundamental na mentalidade do desenvolvedor. No nível avançado, enfrentamos desafios reais: transações distribuídas, consistência de dados, latência de rede e complexidade de depuração. Neste artigo, analisaremos os principais padrões e técnicas práticas que ajudarão a construir um sistema confiável e escalável em PHP.
1. Comunicação entre serviços: síncrona vs assíncrona
A escolha do protocolo de comunicação é a primeira coisa que um arquiteto enfrenta. No ecossistema PHP, existem duas abordagens principais.
Comunicação síncrona via REST/gRPC
Ideal para operações que exigem resposta imediata (por exemplo, verificação de saldo do usuário). No entanto, cria dependências rígidas: se o serviço B falhar, o serviço A também falhará. Recomenda-se usar o padrão Circuit Breaker.
// Exemplo de Circuit Breaker em PHP usando a biblioteca Guzzleuse GuzzleHttp\\Client;use GuzzleHttp\\Exception\\ConnectException;
class CircuitBreaker { private int $failureCount = 0; private int $threshold = 3; private int $timeout = 30; // segundos private bool $open = false; private int $lastFailureTime = 0;
public function call(string $url): ?array { if ($this->isOpen()) { return null; // Fechamento rápido }
try { $client = new Client(['timeout' => 2.0]); $response = $client->get($url); $this->reset(); return json_decode($response->getBody(), true); } catch (ConnectException $e) { $this->recordFailure(); return null; } }
private function isOpen(): bool { if (!$this->open) return false; if (time() - $this->lastFailureTime > $this->timeout) { $this->open = false; // Estado semiaberto return false; } return true; }
private function recordFailure(): void { $this->failureCount++; $this->lastFailureTime = time(); if ($this->failureCount >= $this->threshold) { $this->open = true; } }
private function reset(): void { $this->failureCount = 0; $this->open = false; }}Comunicação assíncrona via filas (RabbitMQ, Kafka)
Para operações que não exigem resposta instantânea (envio de e-mail, geração de relatórios). Use a biblioteca php-amqplib.
// Publicação de evento no RabbitMQuse PhpAmqpLib\\Connection\\AMQPStreamConnection;use PhpAmqpLib\\Message\\AMQPMessage;
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');$channel = $connection->channel();
$channel->queue_declare('order_created', false, true, false, false);
$data = json_encode([ 'order_id' => 12345, 'user_id' => 678, 'total' => 1500.00]);$msg = new AMQPMessage($data, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);$channel->basic_publish($msg, '', 'order_created');
$channel->close();$connection->close();2. Gerenciamento de dados: CQRS e Event Sourcing
Em microsserviços, cada serviço deve ser dono dos seus próprios dados. Mas o que fazer quando é necessário combinar dados de diferentes serviços para um relatório? O padrão CQRS (Command Query Responsibility Segregation) vem em socorro.
Implementação de um CQRS simples em PHP
Separamos comandos (escrita) e consultas (leitura). Para escrita, usamos Doctrine ORM; para leitura, consultas SQL diretas ao modelo de leitura.
// Comando: criação de pedidoclass CreateOrderCommand { public function __construct( public readonly int $userId, public readonly array $items, public readonly float $total ) {}}
// Proc