Puertas de enlace de API y descubrimiento de servicios
Enrute, agregue y localice servicios dinámicamente
Puertas de enlace de API y descubrimiento de servicios es una lección gratuita de PHP Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de PHP Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de PHP Academy incluye 4 lecciones en total.
Puertas de enlace y descubrimiento
Cuando tenga una docena de servicios, aparecen dos problemas. Los clientes no deberían tener que conocer la dirección de cada servicio ni llamar a cinco de ellos para renderizar una pantalla: esa es la función de la puerta de enlace de API. Además, los servicios que aumentan o reducen su escala y cambian de IP necesitan una forma de encontrarse entre sí: eso es el descubrimiento de servicios.
En esta lección se abordan ambos temas, con PHP en el extremo de la puerta de enlace.
Qué hace una puerta de enlace de API
Una puerta de enlace de API es un único punto de entrada situado delante de sus servicios. Sus responsabilidades habituales son:
- Enrutamiento de las solicitudes al backend correcto.
- Aspectos transversales: autenticación, limitación de velocidad, CORS y terminación de TLS.
- Agregación: combinar varias llamadas a backends en una sola respuesta para el cliente.
- Traducción de protocolos: recibe REST externo y envía gRPC interno.
Mantiene la sencillez de los clientes y centraliza políticas que, de otro modo, tendría que duplicar en cada servicio.
Enrutamiento en el extremo
En esencia, una puerta de enlace asigna una ruta entrante a un servicio upstream. Las puertas de enlace de producción (Kong, Traefik, Nginx, AWS API Gateway) hacen esto de forma declarativa, pero la lógica es lo bastante sencilla como para ilustrarla en PHP.
<?php
$routes = [
'#^/api/orders#' => 'http://orders-svc',
'#^/api/customers#' => 'http://customers-svc',
'#^/api/catalog#' => 'http://catalog-svc',
];
function resolveUpstream(string $path, array $routes): ?string {
foreach ($routes as $pattern => $upstream) {
if (preg_match($pattern, $path)) {
return $upstream . $path;
}
}
return null; // 404 at the gateway
}
echo resolveUpstream('/api/orders/42', $routes), "\n";Centralización de la autenticación
Valide al cliente una sola vez en la puerta de enlace y, después, reenvíe una identidad de confianza a los servicios posteriores para que cada servicio no tenga que volver a verificar el token sin procesar. La puerta de enlace comprueba la firma y la caducidad del JWT e inyecta encabezados como X-User-Id en la solicitud interna (a través de una red de confianza).
<?php
function authenticate(string $authHeader): ?array {
if (!str_starts_with($authHeader, 'Bearer ')) return null;
$jwt = substr($authHeader, 7);
$claims = verifyJwt($jwt); // signature + exp check
if ($claims === null) return null;
// Forward minimal trusted identity to internal services
return ['X-User-Id' => $claims['sub'], 'X-Scopes' => implode(',', $claims['scopes'])];
}
function verifyJwt(string $j): ?array { return ['sub' => 'u-7', 'scopes' => ['orders:read']]; }
print_r(authenticate('Bearer abc.def.ghi'));Agregación de respuestas
Una pantalla móvil puede necesitar datos de pedidos, clientes y catálogo. En lugar de hacer que el cliente realice tres llamadas, la puerta de enlace distribuye las solicitudes, espera y combina los resultados. Para mantener la rapidez, realice las llamadas upstream de forma concurrente (promesas de Guzzle / curl_multi) en lugar de secuencialmente.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Promise\Utils;
$http = new Client(['timeout' => 2.0]);
$promises = [
'order' => $http->getAsync('http://orders-svc/orders/42'),
'customer' => $http->getAsync('http://customers-svc/customers/7'),
'catalog' => $http->getAsync('http://catalog-svc/items?order=42'),
];
$results = Utils::settle($promises)->wait(); // run in parallel
// merge the fulfilled bodies into one response for the clientBackends para Frontends
Una puerta de enlace genérica a menudo no puede atender igual de bien a una aplicación web, una aplicación móvil y los partners: cada cliente necesita agregaciones y estructuras de payload diferentes. El patrón Backend para Frontend (BFF) proporciona a cada tipo de cliente su propia puerta de enlace ligera, adaptada a sus necesidades, mientras los servicios compartidos siguen siendo genéricos.
Así se evita una puerta de enlace monolítica y cada equipo de cliente puede trabajar de forma independiente.
El problema del descubrimiento
En un entorno dinámico, las instancias aparecen y desaparecen, y sus IP cambian. Codificar http://10.0.3.14:8080 directamente es frágil. El descubrimiento de servicios mantiene un registro actualizado de «qué instancias en buen estado del servicio X existen en este momento», para que los clientes resuelvan un nombre lógico a una dirección real en el momento de realizar la llamada.
Descubrimiento del lado del cliente frente al del servidor
Hay dos modelos:
- Del lado del cliente: el cliente consulta un registro (Consul, etcd), elige una instancia por su cuenta y realiza su propio balanceo de carga.
- Del lado del servidor: el cliente accede a una dirección virtual estable (un balanceador de carga o un Service de Kubernetes) que resuelve la instancia y distribuye la carga.
En Kubernetes normalmente obtiene el descubrimiento del lado del servidor de forma gratuita: llame a http://customers-svc y el DNS del clúster y el Service se encargan del resto. Fuera de k8s, son habituales los registros al estilo de Consul.
Consulta de un registro
Con el descubrimiento del lado del cliente, el cliente PHP solicita al registro las instancias en buen estado y elige una. El registro solo devuelve las instancias que superan las comprobaciones de salud, por lo que los nodos inactivos quedan excluidos automáticamente.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
function discover(Client $http, string $service): string {
// Consul: only passing-health instances
$res = $http->get("http://consul:8500/v1/health/service/$service?passing=true");
$nodes = json_decode((string) $res->getBody(), true);
if (!$nodes) throw new \RuntimeException("No healthy $service");
$pick = $nodes[array_rand($nodes)]['Service']; // simple LB
return "http://{$pick['Address']}:{$pick['Port']}";
}Comprobaciones de salud y registro
El descubrimiento solo es tan fiable como los datos de salud en los que se basa. Cada servicio expone un endpoint /health que comprueba sus dependencias reales (base de datos, caché) y se registra al iniciarse (o la plataforma lo registra). El registro sondea ese endpoint y elimina las instancias que fallan.
Haga que la comprobación de salud sea significativa: devolver 200 mientras la base de datos está caída es peor que no servir de nada: dirige el tráfico a un nodo defectuoso.
<?php
// GET /health
function health(PDO $db, Redis $cache): array {
$checks = [
'db' => safe(fn() => $db->query('SELECT 1') !== false),
'cache' => safe(fn() => $cache->ping() === '+PONG'),
];
$ok = !in_array(false, $checks, true);
http_response_code($ok ? 200 : 503);
return ['status' => $ok ? 'pass' : 'fail', 'checks' => $checks];
}
function safe(callable $c): bool { try { return (bool) $c(); } catch (\Throwable) { return false; } }Liveness frente a Readiness
Un único endpoint de salud no es suficiente: distinga entre dos preguntas:
- Liveness: «¿el proceso está activo?». Si falla, el orquestador reinicia el contenedor. Manténgala económica y sin dependencias; de lo contrario, una base de datos inestable provocará reinicios innecesarios.
- Readiness: «¿puede atender tráfico ahora mismo?». Si falla, se retira el tráfico, pero el proceso sigue ejecutándose (por ejemplo, mientras calienta una caché o la base de datos no está disponible temporalmente).
Confundirlas provoca ciclos de reinicio o dirige tráfico a nodos que todavía no están listos.
<?php
// GET /livez - is the process itself healthy? (no external deps)
function livez(): void { http_response_code(200); echo 'alive'; }
// GET /readyz - should we receive traffic? (checks dependencies)
function readyz(PDO $db): void {
try { $db->query('SELECT 1'); http_response_code(200); echo 'ready'; }
catch (\Throwable) { http_response_code(503); echo 'not ready'; }
}Comprobación rápida
Reducir los viajes de ida y vuelta del cliente.
Resumen
Enrutamiento y localización de servicios:
- Una puerta de enlace de API centraliza el enrutamiento, la autenticación, la limitación de velocidad, TLS y la agregación.
- Agregue de forma concurrente y use BFF cuando las necesidades de los clientes diverjan.
- El descubrimiento de servicios resuelve nombres lógicos en instancias activas y saludables.
- Descubrimiento del lado del cliente (consulta de un registro) frente a del lado del servidor (balanceador de carga estable o Service de k8s).
- Las comprobaciones de salud significativas mantienen el tráfico alejado de los nodos defectuosos.
A continuación: cómo mantener la resiliencia de todas estas llamadas cuando algunas partes fallen inevitablemente.
Preguntas frecuentes
¿La lección «Puertas de enlace de API y descubrimiento de servicios» es gratis?
Sí — el texto completo de «Puertas de enlace de API y descubrimiento de servicios» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de PHP Academy, actualiza a CoddyKit PRO. El curso de PHP Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Puertas de enlace de API y descubrimiento de servicios»?
Enrute, agregue y localice servicios dinámicamente Practicas PHP Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar PHP Academy?
No se requiere experiencia previa. PHP Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Puertas de enlace de API y descubrimiento de servicios»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de PHP Academy?
Sí. Cada lección de PHP Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Del monolito a los microservicios
- Comunicación entre servicios: REST y gRPC
- Puertas de enlace de API y descubrimiento de servicios
- Resiliencia: circuit breakers y reintentos