Patrones de Comunicación
Síncrona vs. asíncrona: REST, gRPC y GraphQL para comunicación inmediata; colas y pub/sub para procesamiento diferido, con sus consecuencias en latencia, acoplamiento, consistencia y gestión de fallos.
Los componentes necesitan comunicarse. La primera decisión es si la comunicación será síncrona o asíncrona, y esto tiene consecuencias sobre la latencia, el acoplamiento, la consistencia y la gestión de fallos.
Síncrona
El cliente envía una request y espera la respuesta:
sequenceDiagram participant PS as Payment Service participant PP as Payment Provider PS->>PP: authorize() PP-->>PS: response
Características: respuesta inmediata, acoplamiento temporal, acoplamiento por latencia y dependencia de disponibilidad. Si el proveedor está lento, el cliente puede quedar bloqueado.
REST
HTTP + API orientada a recursos:
POST /payments
GET /payments/{id}
POST /payments/{id}/refund
Ventajas: familiar, interoperable, compatible con browsers, excelente para API públicas. Tecnologías: Spring Web, ASP.NET, Express, FastAPI, NestJS.
gRPC
RPC, normalmente basado en Protobuf:
PaymentService
└── AuthorizePayment()
Ventajas: tipado fuerte, generación de código, eficiente, streaming, excelente para comunicación entre servicios. Trade-offs: es menos cómodo de consumir directamente desde browsers, introduce tooling específico y obliga a coordinar los contratos con el deployment.
GraphQL
El cliente solicita exactamente la forma de los datos que necesita:
query {
order {
id
total
payment {
status
}
}
}
Es especialmente útil cuando existen múltiples clientes, las necesidades de datos varían mucho y se necesita una composición flexible. Trade-offs: caching más complejo, autorización granular, complejidad de las queries, riesgo de N+1 y observabilidad específica.
Asíncrona
El productor envía un mensaje o evento y el procesamiento puede ocurrir más tarde:
flowchart LR PS["Payment Service"] --> MB["Message Broker"] MB --> O["Orders"] MB --> E["Email"] MB --> A["Analytics"]
Ventajas: desacoplamiento temporal, buffering de carga, procesamiento en segundo plano, fan-out y consistencia eventual. Pero hay que lidiar con duplicados, ordenamiento, reintentos, semánticas de entrega, DLQ, idempotencia y evolución de esquemas.
Queue
flowchart LR P["Producer"] --> Q["Queue"] --> W["Worker"]
Útil para SendEmail, GenerateInvoice, ResizeImage, ProcessPaymentNotification. Normalmente cada mensaje lo procesa un consumer del grupo.
Pub/Sub
flowchart TD T["Topic"] --> CA["Consumer A"] T --> CB["Consumer B"] T --> CC["Consumer C"]
El mismo evento puede llegar a múltiples consumers.
Command vs. Event
Una distinción fundamental:
| Concepto | Significa |
|---|---|
| Command | Intención (CapturePayment) |
| Event | Hecho ocurrido (PaymentCaptured) |
Un command suele tener un destinatario claro. Un event puede tener múltiples consumers.
Síncrona vs. Asíncrona
| Característica | Síncrona | Asíncrona |
|---|---|---|
| Respuesta | Inmediata | Diferida |
| Acoplamiento temporal | Alto | Menor |
| Consistencia | Puede ser inmediata | Frecuentemente eventual |
| Modelo de fallos | Timeout | Delivery/retry |
| Latencia | Visible al caller | Desacoplada |
| Complejidad | Menor | Mayor |
| Buen caso de uso | Query/command inmediato | Events/background |
Regla práctica
flowchart TD Q["¿Necesito el resultado ahora?"] -->|Sí| S["Sync"] Q -->|No| A["Async"]
Pero después hay que analizar consistencia, ordenamiento, reintentos, idempotencia, throughput y semántica de fallos.
Tecnologías conocidas
- Síncrona: REST/HTTP, gRPC, GraphQL.
- Asíncrona: Apache Kafka, RabbitMQ, Amazon SQS, Amazon SNS, Google Pub/Sub, NATS.
La tecnología debería surgir del patrón requerido, no al revés.
