El problema fundamental que aborda esta evolución de Cloudflare Workers es la necesidad de ejecutar servicios de red de baja latencia y estado, más allá del paradigma HTTP/S sin estado, en un entorno de edge computing. Tradicionalmente, las plataformas serverless como Workers se han centrado en funciones sin estado activadas por HTTP, lo que limita su aplicabilidad para protocolos persistentes o de streaming como TCP crudo o gRPC bidireccional.

La creciente demanda de aplicaciones en tiempo real, como asistentes de voz con IA o sistemas de colaboración, requiere una comunicación full-duplex y un control granular sobre las conexiones de red. Esto choca con las abstracciones de alto nivel de muchas plataformas serverless. Al exponer el socket TCP directamente y facilitar gRPC, Cloudflare permite a los desarrolladores desplegar arquitecturas distribuidas que requieren persistencia de conexión y un control de flujo más sofisticado, acercando la lógica de negocio a la fuente de los datos y los usuarios finales, un principio clave del edge computing.

Históricamente, la computación distribuida ha buscado equilibrar la flexibilidad del despliegue con el rendimiento de la red. Esta actualización representa un paso hacia la convergencia de la flexibilidad del serverless con las capacidades de red de infraestructuras más tradicionales, permitiendo patrones de diseño que antes requerían máquinas virtuales o contenedores dedicados en ubicaciones geográficamente dispersas.

Arquitectura del Sistema

La arquitectura se centra en la capacidad de Cloudflare Workers para aceptar y manipular conexiones TCP entrantes, y en la integración de gRPC. El componente clave es el nuevo handler connect(socket) en el runtime de Workers. Este handler permite a un Worker recibir un socket TCP directamente de Spectrum, el proxy de Cloudflare para tráfico no HTTP. Una vez que el Worker tiene el socket, puede leer y escribir directamente en él, o pasarlo a otros componentes.

Existen dos patrones principales para el manejo del socket: Primero, un Worker puede pasar el socket a un Durable Object. Los Durable Objects son primitivas de Cloudflare que proporcionan consistencia de estado global y aislamiento, actuando como singletons distribuidos. Esto permite que la lógica de negocio con estado maneje la conexión TCP. Segundo, un Durable Object puede, a su vez, pasar el socket a un contenedor en la plataforma de Cloudflare, exponiendo el socket TCP crudo a una aplicación arbitraria que se ejecute en el contenedor. Esto habilita la ejecución de cualquier servidor basado en TCP, en cualquier lenguaje.

Para gRPC, Cloudflare ofrece dos vías: la primera es el soporte completo para gRPC bidireccional en contenedores, aprovechando la capacidad de pasar sockets TCP. La segunda, más innovadora, es la traducción automática entre gRPC y gRPC-web. Cuando un Worker actúa como servidor o cliente gRPC, utiliza la API fetch() y bibliotecas como @connectrpc/connect para interactuar con gRPC-web. Cloudflare, en su capa de proxy inverso, intercepta estas solicitudes y las traduce a gRPC estándar (HTTP/2) para la comunicación externa, y viceversa. Esto permite a los Workers interactuar con ecosistemas gRPC existentes sin requerir cambios en los clientes o servidores externos, y sin la necesidad de un contenedor dedicado, aprovechando el multiplexado de HTTP/2 para streaming eficiente.

Flujo de Conexión TCP Inbound a Contenedor

  1. 1 Cliente Inicia conexión TCP
  2. 2 Cloudflare Spectrum Proxy de entrada, enruta a Worker configurado
  3. 3 Cloudflare Worker Recibe `socket` en handler `connect()`, lo pasa a Durable Object
  4. 4 Durable Object Recibe `socket`, lo pasa a Container en puerto específico
  5. 5 Contenedor Aplicación TCP (ej. gRPC server) maneja el socket directamente

Flujo de gRPC con Traducción gRPC-web en Worker

  1. 1 Cliente gRPC Envía solicitud gRPC (HTTP/2)
  2. 2 Cloudflare Edge Proxy inverso de Cloudflare
  3. 3 Cloudflare Edge Traduce gRPC (HTTP/2) a gRPC-web (HTTP/1.1 o HTTP/2 con fetch)
  4. 4 Cloudflare Worker Recibe solicitud gRPC-web vía `fetch()`, procesa con `@connectrpc/connect`
  5. 5 Cloudflare Worker Envía respuesta gRPC-web vía `fetch()`
  6. 6 Cloudflare Edge Traduce gRPC-web a gRPC (HTTP/2)
  7. 7 Cliente gRPC Recibe respuesta gRPC
CapaTecnologíaJustificación
networking TCP Protocolo de transporte fundamental para la comunicación full-duplex y gRPC. La nueva funcionalidad permite a los Workers manipular directamente sockets TCP entrantes.
networking gRPC Framework RPC de alto rendimiento basado en HTTP/2, utilizado para comunicación entre microservicios y aplicaciones de baja latencia. Ahora soportado directamente en Workers y Contenedores. vs REST (HTTP/1.1), Cap'n Proto (interno de Cloudflare)
compute Cloudflare Workers Plataforma serverless de edge computing que ahora puede aceptar conexiones TCP entrantes y actuar como servidor/cliente gRPC, extendiendo sus capacidades más allá de HTTP. `connect(socket)` handler, `fetch()` API
compute Cloudflare Durable Objects Primitiva de estado distribuido que puede mantener conexiones TCP persistentes y enrutar sockets a contenedores, habilitando servicios con estado en el edge. `stub.connect()`, `ctx.container!.getTcpPort().connect()`
networking Cloudflare Spectrum Proxy de entrada de Cloudflare para tráfico no HTTP, utilizado para enrutar conexiones TCP entrantes a Workers. Configuración de aplicación Spectrum para Worker
networking gRPC-web Versión de gRPC compatible con navegadores web, utilizada internamente por Workers para la comunicación gRPC que luego es traducida a gRPC estándar por el proxy de Cloudflare. vs WebSockets
data-processing Protocol Buffers (protobuf) Lenguaje de definición de interfaz y formato de serialización de datos utilizado por gRPC para definir servicios y mensajes. vs JSON, XML
export default {
  async connect(socket): Promise<void> {
    const writer = socket.writable.getWriter();
    await writer.write(new TextEncoder().encode("Hello, world!\n"));
    await writer.close();
  },
} satisfies ExportedHandler;
Un Worker que acepta una conexión TCP y envía un mensaje de 'Hello, world!' antes de cerrar la conexión.
import { DurableObject } from "cloudflare:workers";
export class SocketDurableObject extends DurableObject<Env> {
  async connect(socket: Socket): Promise<void> {
    await socket.readable.pipeTo(socket.writable);
  }
}
export default {
  async connect(socket, env): Promise<void> {
    const stub = env.SOCKET_DO.getByName("my-server");
    const durableObjectSocket = stub.connect("host:port");
    await Promise.all([
      socket.readable.pipeTo(durableObjectSocket.writable),
      durableObjectSocket.readable.pipeTo(socket.writable),
    ]);
  },
} satisfies ExportedHandler<Env>;
Un Worker que obtiene un stub de Durable Object y le pasa un socket TCP entrante para que el Durable Object lo maneje, estableciendo un pipe bidireccional.
import { createConnectRouter } from "@connectrpc/connect";
import {
  universalServerRequestFromFetch,
  universalServerResponseToFetch,
} from "@connectrpc/connect/protocol";
import { Greeter } from "./gen/hello_pb";
const router = createConnectRouter();
router.service(Greeter, {
  sayHello: ({ name }) => ({ message: `Hello, ${name}!` }),
});
const handlers = new Map(
  router.handlers.map((handler) => [handler.requestPath, handler]),
);
export default {
  async fetch(request: Request): Promise<Response> {
    const handler = handlers.get(new URL(request.url).pathname);
    return universalServerResponseToFetch(
      await handler(universalServerRequestFromFetch(request, {})),
    );
  },
} satisfies ExportedHandler;
Un Worker que implementa un servicio gRPC 'Greeter' utilizando `@connectrpc/connect`, traduciendo automáticamente gRPC-web a gRPC.

Fundamentos Teóricos

La capacidad de enrutar y manipular conexiones TCP a nivel de aplicación en un entorno distribuido se relaciona con los principios de los proxies de aplicación y los sistemas de enrutamiento de capa 7. Conceptos como el 'Application-Layer Framing' (ALF) de Clark y Tennenhouse (1990) son relevantes, ya que esta funcionalidad permite a los Workers inspeccionar y modificar el tráfico a un nivel más profundo que el simple reenvío de paquetes, aplicando lógica de negocio antes de pasar la conexión. La manipulación de sockets y la capacidad de 'pipe' streams de datos entre componentes (Worker a Durable Object, Durable Object a Contenedor) se alinea con el modelo de 'streams' y 'pipes' que se encuentra en sistemas operativos Unix y en paradigmas de programación reactiva.

La integración de gRPC, un framework RPC basado en HTTP/2, se conecta con la evolución de los protocolos de comunicación distribuida. gRPC utiliza HTTP/2 para multiplexar múltiples flujos bidireccionales sobre una única conexión TCP, un concepto que tiene sus raíces en los trabajos sobre 'Remote Procedure Call' (RPC) de Birrell y Nelson (1984) y la necesidad de abstracciones de comunicación de alto nivel en sistemas distribuidos. La traducción de gRPC a gRPC-web aborda las limitaciones de las APIs de navegador para HTTP/2, un problema que también llevó al desarrollo de WebSockets para comunicación full-duplex en la web, y que refleja la tensión entre la seguridad y las capacidades de bajo nivel en el diseño de protocolos web.