Construyendo Aplicaciones Multijugador con Cloudflare Workers y Durable Objects

Spanish audio is available in the player settings
Rate this content
Bookmark

Durable Objects, parte de la plataforma Cloudflare Workers, son la solución para el almacenamiento y coordinación fuertemente consistentes en el borde. En esta charla, aprenderás sobre Durable Objects, por qué son adecuados para casos de uso colaborativos y cómo construir aplicaciones multijugador con ellos!

28 min
14 Apr, 2023

Video Summary and Transcription

Durable Objects son parte del objetivo a largo plazo de CloudFlare de expandir las posibilidades de aplicación en los workers, permitiendo la construcción de aplicaciones colaborativas escalables. Durable Objects proporcionan una forma de almacenar el estado global y coordinar aplicaciones multi-cliente. Se pueden crear lo más cerca posible del usuario y tienen identificadores únicos para enrutamiento de solicitudes. Durable Objects tienen una API de almacenamiento persistente con semántica fuertemente consistente y puertas de E/S para prevenir errores de corrección. Son adecuados para aplicaciones colaborativas y se pueden usar con WebSockets. El impacto en el rendimiento y las réplicas de lectura son consideraciones para acceder a Durable Objects a nivel global.

Available in English

1. Introducción a los Objetos Duraderos

Short description:

Soy Matt Alonzo, un ingeniero de software en CloudFlare. Trabajo en el equipo de datos distribuidos de workers y tengo una amplia experiencia con objetos duraderos. Los objetos duraderos son parte del objetivo a largo plazo de CloudFlare de expandir las posibilidades de aplicaciones en workers. No son solo un producto de almacenamiento, sino también ideales para construir aplicaciones colaborativas escalables como editores de documentos, servidores de juegos y salas de chat.

Soy Matt Alonzo y soy un ingeniero de software en CloudFlare. Trabajo en el equipo de datos distribuidos de workers que mantiene los objetos duraderos. He trabajado en CloudFlare durante casi tres años y he pasado casi todo el tiempo trabajando en objetos duraderos. Estoy muy familiarizado con ellos. Y los objetos duraderos son parte de un objetivo a largo plazo para CloudFlare donde estamos tratando de expandir los tipos de aplicaciones que los clientes pueden construir sobre workers. Y los objetos duraderos se han considerado como un producto de almacenamiento que se suma a esto. Puedes almacenar objetos duraderos con estado en el borde, pero hay mucho más en ellos que eso. Los objetos duraderos también son muy adecuados para construir aplicaciones colaborativas infinitamente escalables como editores de documentos, servidores de juegos y salas de chat, y esta charla trata sobre analizar por qué.

2. Descripción general de Workers y Objetos Duraderos

Short description:

Voy a hablar sobre workers, dar una visión general rápida. Hablaré sobre objetos duraderos, su API y coordinación. Tengo un estudio de caso y una demostración. Workers es la plataforma de JavaScript sin servidor de Cloudflare. Utiliza su propio tiempo de ejecución y se ejecuta a nivel mundial. Está implementado con aislamientos de V8, lo que permite una ejecución eficiente del código. Así es como los workers pueden existir hoy en día.

Si tienen alguna pregunta después de la charla, no duden en enviarme un correo electrónico o contactarme en mis redes sociales. Y así, voy a hablar de algunos temas hoy. Voy a hablar sobre workers, dar una visión general rápida de ellos. Voy a hablar sobre objetos duraderos, qué son, cómo se ve la API y y luego voy a hablar sobre coordinación. ¿Por qué los objetos duraderos son útiles para la coordinación? ¿Por qué querrías usarlos? Y luego tengo un estudio de caso, una aplicación que construí sobre objetos duraderos, y si todo va bien, haré una demostración de ello.

Y así, workers es la plataforma serverless de Cloudflare. La idea es que escribas un controlador de búsqueda como este de arriba, que reciba un objeto de solicitud, realice algún trabajo y devuelva una respuesta. Y así tomas tu código de worker, lo subes a Cloudflare y nosotros nos encargamos del resto. Esto es bastante similar a muchas otras plataformas serverless, pero hay algunas diferencias importantes con workers. Workers utiliza su propio tiempo de ejecución y los workers no se ejecutan en regiones. Solo hay una, en realidad, una región con workers. Es la Tierra. Despliegas una vez y tu código se ejecuta en cualquiera de las ubicaciones de la red de Cloudflare en todo el mundo. Cuando usas workers, tu dominio también utiliza los productos de CDN de Cloudflare, por lo que las consultas DNS a tu dominio devuelven una IP de Cloudflare Anycast. Cuando envías tráfico a una IP Anycast en uno de los centros de datos de Cloudflare, se dirigirá al centro de datos de Cloudflare más cercano, sin importar dónde te encuentres en el mundo. Y esto significa que cuando haces una solicitud a un worker de Cloudflare, se ejecutará cerca de ti en el centro de datos de Cloudflare más cercano, independientemente de dónde hagas la solicitud desde. Y este mapa aquí es un mapa del último que pude encontrar de todas las ubicaciones de Cloudflare en todo el mundo. Como puedes ver, es bastante difícil estar lejos de una ubicación donde se pueden ejecutar workers, a menos que estés en medio de la selva o algo así.

Y así, una parte fundamental para poder ejecutar código como este en el borde de Cloudflare es la forma en que se implementa workers, que es muy diferente de otras plataformas serverless. Tenemos nuestro propio tiempo de ejecución de JavaScript construido sobre V8. Y este es el mismo motor de JavaScript utilizado por Node.js y Chromium. Y en lugar de implementar la multiarrendamiento iniciando múltiples instancias de tiempo de ejecución como funcionan otras plataformas serverless, lo que hace workers es implementar la multiarrendamiento con aislamientos de V8. Esta es una característica de V8 que te permite ejecutar código separado, todo en el mismo proceso. Y así ejecutamos el código de múltiples clientes en el mismo proceso del sistema operativo, todos se ejecutan en aislamientos diferentes y están completamente aislados entre sí, no pueden interferir entre sí, cambiar el estado global o algo así. Y así los aislamientos son mucho más baratos de iniciar que un proceso completo del sistema operativo. Y así, cuando una solicitud para un worker iniciado en frío llega al tiempo de ejecución del worker, creamos un nuevo aislamiento. Y esto solo lleva unos pocos milisegundos, en comparación con cientos de milisegundos para iniciar en frío todo el tiempo de ejecución. Y esto es realmente importante para workers. No sería posible para nosotros ejecutar un tiempo de ejecución completo por cliente en el borde. Esta idea es cómo workers realmente pueden existir hoy en día.

3. Introducción a los Objetos Duraderos Continuado

Short description:

Antes de los Objetos Duraderos, los workers eran sin estado y carecían de una forma de almacenar estado global. Los Objetos Duraderos se introdujeron para abordar la necesidad de coordinación en aplicaciones multi-cliente. Los Objetos Duraderos aplican la filosofía serverless de estado al permitir la división del cómputo en piezas de granularidad fina. Cada instancia de una clase de Objeto Duradero tiene un ID único, asegurando que las solicitudes desde diferentes ubicaciones llamen al mismo FetchMethod en la misma instancia de objeto.

Y así quiero volver a este ejemplo de cómo se ve un worker normal. Así puedo ver el todo que construyeron los Objetos Duraderos. Antes de que los Objetos Duraderos existieran, los workers eran completamente sin estado. Si observas este fragmento de código, no hay ningún lugar para almacenar estado global. Puedes colocar cosas en el ámbito global, pero el 99% del tiempo, no es lo que quieres. Debido a que los workers se ejecutan en tantas ubicaciones alrededor del mundo, y cada una de estas ubicaciones tiene cientos de servidores.

Cuando tu worker está ejecutándose, está recibiendo tráfico desde muchos lugares, tienes toneladas y toneladas de instancias de tu worker. Y todas ellas tendrán ámbitos globales completamente separados. Por lo tanto, almacenar data en el ámbito global no es una solución para realizar coordinación. Pero todas estas diferentes instancias son cosas realmente buenas para escalar. Y en conjunto, pueden manejar una gran cantidad de rendimiento. Y así los Objetos Duraderos fueron una solución para poder ejecutar cargas de trabajo que necesitan realizar coordinación.

¿Y qué quiero decir cuando hablo de coordinación? La coordinación es lo que hace que las aplicaciones multijugador sean útiles. Y las aplicaciones multijugador son aplicaciones que tienen múltiples clientes conectándose a la aplicación para realizar una tarea juntos. Piensa en personas colaborando en un documento, jugando un juego juntos o chateando en una sala de chat. Y todas estas aplicaciones, lo que tienen en común es que todas se tratan de estado. Todos los clientes están enviando actualizaciones de estado a la aplicación, y la aplicación es responsable de asegurarse de que esas actualizaciones de estado sean reflejadas por otros clientes y este estado es de larga duración y necesita ser procesado en múltiples solicitudes.

Entonces, ¿qué son los Objetos Duraderos? Diría que un Nokia 3310 antes de mi tiempo, pero definitivamente parece bastante duradero aquí. Pero en realidad, lo que son es aplicar la filosofía serverless de estado. El cómputo serverless se trata de dividir el cómputo en piezas de granularidad fina que son fáciles de iniciar según sea necesario, como en cada solicitud entrante. Los Objetos Duraderos toman este concepto y lo aplican al estado y la coordinación. Con los workers normales, escribes tu FetchHandler y el runtime lo invoca por solicitud, y implementa alguna lógica sin estado.

Con los Objetos Duraderos, escribes una clase Javascript con el método FetchHandler, y este FetchHandler se invoca en instancias de esa clase, en lugar de un método Fetch que se llama en este objeto Handler, como con un worker normal. Con los Objetos Duraderos, todavía hablan HTTP como lo hacen los workers normales, y el FetchHandler todavía se invoca en cada solicitud entrante, pero no son enrutables desde Internet público. En su lugar, cada instancia de una clase de Objeto Duradero tiene un ID asociado. Esto permite que los workers que conocen el ID de la instancia de Objeto Duradero envíen solicitudes a ella. La plataforma garantiza que este ID identifica una única instancia en todo el mundo. Cuando esta instancia es única, no obtendrás diferentes instancias con el mismo ID. Si varios workers envían una solicitud al mismo ID de Objeto Duradero desde diferentes ubicaciones en el mundo, todas esas solicitudes terminan llamando al mismo FetchMethod en la misma instancia de objeto.

Aquí tienes un ejemplo de cómo se ve esta API para los Objetos Duraderos.

4. Asociación de Workers y Colocación de Objetos Duraderos

Short description:

Para que un worker envíe una solicitud a un Objeto Duradero, necesita una asociación con él. El tiempo de ejecución enruta la solicitud al Objeto Duradero según su ubicación. Los Objetos Duraderos se pueden crear lo más cerca posible del usuario. Hay dos tipos de IDs para los Objetos Duraderos: IDs únicos e IDs con nombre. Los IDs únicos son fáciles de manejar, mientras que los IDs con nombre requieren un proceso más complejo. El proceso implica el hash del ID con nombre para determinar la ubicación del Objeto Duradero y enrutar la solicitud en consecuencia. El punto de coordinación almacena la ubicación, lo que permite que las solicitudes posteriores se dirijan directamente al objeto.

Para que un worker envíe una solicitud a un Objeto Duradero específico, debe tener una asociación con él. Esta asociación aparece en el objeto env que se pasa a cada solicitud entrante a un worker. Este objeto env se utiliza para crear un ID. Puedes crear un subobjeto utilizando ese ID, y así es como envías solicitudes a un Objeto Duradero.

Cuando haces eso, el runtime enruta la solicitud al Objeto Duradero, dependiendo de dónde se encuentre en el mundo, y se encarga de encontrar esa ubicación y todo el enrutamiento. Por lo tanto, una parte importante de los Objetos Duraderos es que cuando creas uno por primera vez, en realidad se crean lo más cerca posible de ti. Así que hay un subconjunto de centros de datos de Cloudflare que admiten la ejecución de Objetos Duraderos. Y cuando tenemos una solicitud para un nuevo objeto, necesitamos averiguar en qué de estos centros de datos vamos a ejecutar ese Objeto Duradero. Y la respuesta a eso es que depende de cómo lo hagamos.

Y la razón de esto es que hay dos tipos de IDs para los Objetos Duraderos. Puedes crear un ID único, que es una cadena generada al azar, o puedes crear un ID basado en una cadena, como en este ejemplo aquí. Y con los IDs únicos, determinar la ubicación del objeto es muy simple. No puedes generar dos números aleatorios que sean idénticos si tienen una longitud suficiente, por lo que simplemente puedes agregar metadatos adicionales al ID y hacer que estos metadatos codifiquen dónde se encuentra originalmente el objeto. Pero para los IDs con nombre, no puedes hacer esto porque quieres que varias personas puedan usar el mismo ID y obtener el mismo objeto. Y así hacemos algo un poco más complejo.

Esta es una imagen de cómo se ve el proceso si varios workers intentan crear el mismo Objeto Duradero con el mismo ID al mismo tiempo. Utilizo códigos de aeropuertos para nombrar todas estas ubicaciones porque soy un nerd de la infraestructura, pero están ejecutándose en Virginia, Nueva Jersey, Ámsterdam y Francia. Y todos estos workers, intentan crear un Objeto Duradero con el ID Bob. Y Bob, este ID con nombre, en realidad tiene un... Se hash a una ubicación. Y esta ubicación en particular se utiliza como punto de coordinación para determinar dónde vamos a colocar ese Objeto Duradero. Y en este caso, Bob se hash a DFW, Dallas-Fort Worth. Y así, todos los tiempos de ejecución involucrados aquí saben que Bob se hash a Dallas-Fort Worth, y necesitan tomar esta solicitud de Objeto Duradero y enviarla a Dallas-Fort Worth. La primera solicitud que llegue allí se utilizará para tomar la decisión de colocación. En este caso, probablemente sea la de Virginia porque Virginia está más cerca de Dallas. Y así, el punto de coordinación almacena que Bob estará en Virginia y lo coloca en el centro de datos IAD en Virginia. Y así, este punto de coordinación realmente debe ser verificado para solicitudes posteriores a Bob en algunos casos. Pero la gran mayoría del tiempo, almacenaremos en caché la ubicación de un objeto. Y así, si estás utilizando un objeto más de una vez, la caché estará activa y no tendrás que verificar el punto de coordinación adicional y tu solicitud puede proceder directamente a donde se encuentra el objeto DERVL. Y así, ahora tenemos este concepto de una instancia de objeto que es globalmente direccionable y es única, y podemos enviar solicitudes a ella.

5. Uso de Objetos DERVL y API de Almacenamiento

Short description:

Y esto es una distracción realmente, realmente útil. Cuando escribes un objeto en Objetos DERVL, tomas el estado de tu aplicación y encuentras la unidad lógica más pequeña. Implementa una clase de objeto DERVL que defina el comportamiento común. Cada instancia de objeto tiene acceso a una API de almacenamiento persistente específica para ella. La API de almacenamiento tiene una semántica fuertemente consistente y está colocada junto a cada instancia de objeto. El backend de almacenamiento tiene una capa de caché en proceso, lo que hace que las lecturas sean muy rápidas. La API de almacenamiento y los objetos DERVL tienen una característica llamada IO Gates que evita errores de corrección. Hay puertas de entrada y puertas de salida, que evitan que se entreguen nuevos eventos al objeto mientras espera en el almacenamiento.

Y esto es una distracción realmente, realmente útil. Y la forma en que lo usas es cuando escribes un objeto en Objetos DERVL, tomas el estado de tu aplicación y encuentras la unidad lógica más pequeña. Piensa en salas de chat en una aplicación de mensajería o documentos en un editor colaborativo. Y una vez que tienes una idea de cómo deberían ser tus objetos, implementas una clase de objeto DERVL que define el comportamiento común. Y como creamos una instancia real de JavaScript usando tu clase de objeto DERVL, puedes almacenar un estado transitorio como miembros de esa clase. Y con el ID asignado a cada instancia de objeto, puedes enviar eficazmente solicitudes a un subconjunto particular de tus datos y realizar operaciones en él localmente.

Entonces, esta instancia de objeto que creamos por ID tiene una vida útil hasta cierto punto. Si tu instancia de objeto recibe solicitudes regularmente o tiene una conexión activa de WebSocket, se mantendrá activa. Una vez que deja de recibir solicitudes o no hay conexiones de WebSocket activas, entrará en modo de suspensión. Y así también necesitamos una solución para almacenar datos una vez que el objeto entra en modo de suspensión. Por lo tanto, necesitamos admitir eso. Hay una API de almacenamiento persistente como parte de los objetos DERVL. Y cada instancia de objeto tiene acceso a esta API. Y el almacenamiento dentro de ella es específico para cada instancia de objeto. Y la API de almacenamiento se parece a una API de clave-valor. Tiene una semántica fuertemente consistente. Y el almacenamiento está colocado junto a cada instancia de objeto. Y hay una capa de caché en proceso frente a nuestro backend de almacenamiento. Por lo tanto, las lecturas de almacenamiento generalmente se almacenan en caché, y son muy, muy rápidas.

Y así, este fragmento es un ejemplo de cómo usar esa API para implementar un contador atómico. Y las personas que han estado leyendo el fragmento probablemente tengan alarmas sonando en su cabeza. Esto es arriesgado. No estoy esperando mis operaciones de escritura. Esto parece muy, muy incorrecto. Y en los objetos DERVL, este código es en realidad completamente correcto. La API de almacenamiento y los objetos DERVL tienen una característica llamada IO Gates. Y lo que hacen las IO Gates es evitar errores de corrección que son muy fáciles de cometer en aplicaciones actuales. Y lo hacen con dos tipos de puertas. Hay puertas de entrada y puertas de salida. La puerta de entrada se cierra cuando un evento nuevo y evita la entrega de nuevos eventos entrantes al objeto siempre que el objeto esté esperando en el almacenamiento.

6. Puertas de Entrada y Salida en Objetos DERVL

Short description:

En este ejemplo, las puertas de entrada y salida evitan problemas de concurrencia y garantizan un almacenamiento de datos consistente. La API de almacenamiento no es el enfoque de esta charla, pero hay un artículo de blog disponible para obtener más información.

Entonces, en este ejemplo aquí, cuando hacemos este get, es imposible que se entregue un nuevo evento al objeto y que otro evento pase y haga ese get al mismo tiempo, evitando que dos gets se ejecuten simultáneamente y obtengan el mismo valor y luego escriban los mismos incrementos de valor en el almacenamiento. Eso haría que este contador atómico solo se incremente una vez en lugar de dos veces para dos solicitudes. Entonces, las puertas de entrada evitan ese problema. Las puertas de salida hacen algo diferente. Evitan que se envíen mensajes de red salientes desde los objetos DERVL cuando el objeto duradero está esperando a que se completen sus escrituras de almacenamiento. Por lo tanto, evitan que los clientes de su objeto duradero tomen decisiones basadas en información desactualizada que no se ha o en información no confirmada que no se ha persistido en el almacenamiento. No voy a profundizar demasiado en la API de almacenamiento ya que tenemos un artículo de blog realmente excelente al respecto y no es el enfoque de la charla. Pero las personas pueden buscarlo y preguntarme el nombre del artículo de blog después de la charla si están interesados.

7. Objetos Duraderos para Aplicaciones Colaborativas

Short description:

Los Objetos Duraderos son adecuados para aplicaciones colaborativas, proporcionando un único punto de coordinación entre múltiples clientes. Esto elimina la necesidad de implementar despliegues y enrutamiento complejos en varias regiones. Tomemos como ejemplo un editor de documentos colaborativo donde varios clientes envían ediciones. Los Objetos Duraderos manejan la coordinación para este tipo de aplicaciones, permitiendo una arquitectura simple y fácil de entender. Otro ejemplo es una versión multijugador del Juego de la Vida de Conway implementada utilizando Objetos Duraderos.

He estado hablando un poco sobre los objetos duraderos, cuál es la superficie de la API y las características, pero aún no he explicado por qué son tan adecuados para aplicaciones colaborativas. Y esta abstracción de una instancia de objeto que se puede crear bajo demanda es realmente útil para crear puntos únicos de coordinación entre múltiples clientes y para crear ese punto de coordinación cerca de esos clientes. ¿Y cómo se ve esto en la práctica? Imagina que estás construyendo un editor de documentos colaborativo y tienes varios clientes que envían ediciones, pulsaciones de teclas a la aplicación y la aplicación necesita decidir a dónde van a ir estas pulsaciones de teclas, especialmente si estás editando la misma oración, necesitas coordinar entre los dos clientes qué letras van a ir a dónde.

El enfoque simple aquí es tener un único punto de coordinación para determinar esto. Se puede hacer de otras formas, hay CRDTs y cosas así, pero no funcionan para todos los modelos de datos y en esta charla me centraré en el único punto de coordinación. Y para la mayoría de los desarrolladores, una architecture como esta donde tienes un único punto de coordinación para implementar la lógica de tu aplicación es realmente difícil de lograr. Necesitas hacer un despliegue en varias regiones, necesitas averiguar el enrutamiento, y si estás almacenando data, debes manejar la replicación y la conmutación por error y esto es algo que es muy difícil de hacer en muchas ubicaciones alrededor del mundo. Y los Objetos Duraderos resuelven este problema por completo. Puedes tener tu pastel de coordinación simple, fácil de entender y también puedes comértelo sin preocuparte por las operaciones y el enrutamiento.

Veamos otro ejemplo. Digamos que estoy escribiendo un documento sobre mis lugares de barbacoa favoritos en Texas. Este es un tema bastante controvertido, así que imagino que alguien querrá discutir conmigo al respecto. Estoy escribiendo mi lista, digamos que estoy en casa en Austin y me estoy conectando a un worker en el centro de datos de DFW y estoy enviando todas mis ediciones y ese worker va a obtener un Objeto Duradero con un ID basado en el nombre de mi documento, que es `Barbacoa en Texas`, y va a enviar todas mis ediciones a ese objeto. Y le digo a mi amigo, que está en Miami, donde soy originalmente, que visitó recientemente y tiene algunas discrepancias conmigo sobre qué restaurantes de barbacoa le gustan. Y él comienza a hacer sus propias ediciones, se conecta al mismo documento. Y como ambos estamos usando el mismo ID, ambos nos conectaremos al mismo Objeto Duradero y este Objeto Duradero manejará toda la coordinación para ese documento. Tengo un ejemplo más concreto aquí. Para esta charla, construí una especie de aplicación de demostración basada en Objetos Duraderos que implementa el Juego de la Vida de Conway. Y es una versión multijugador donde varias personas pueden conectarse y agregar cosas a la simulación. Y si no estás familiarizado con el Juego de la Vida de Conway, es una automata celular, es un tipo de simulación en una cuadrícula. Y tiene reglas definidas para cuando las celdas en la cuadrícula deben considerarse vivas, como coloreadas de negro o muertas, coloreadas de blanco. Y para el Juego de la Vida de Conway, las reglas son las siguientes. Cualquier celda con dos o tres vecinos vivos sigue viva en el siguiente ciclo. Cualquier celda muerta con tres vecinos vivos se vuelve viva y luego todas sus celdas vivas mueren y todas sus celdas muertas permanecen muertas. Estas reglas se aplican a cada cuadrícula, cada celda en la cuadrícula en cada ciclo y cada ciclo ocurre a un ritmo regular, digamos cada 500 milisegundos. Y así es como lo implementé con dos clases de objetos duraderos. Hay una clase de objeto duradero de Lobby que almacena una lista de IDs de objetos duraderos de Salas de Juego. Y cuando un cliente se conecta a la aplicación, ve la página del Lobby y hay una lista de salas de juego. Así que elige una sala de juego y esa sala de juego tiene un ID de objeto duradero para un objeto duradero específico para esa sala de juego. Y el cliente lo usa para conectarse al juego y luego comienza a enviar actualizaciones de las celdas que coloca en el juego.

8. WebSockets, Objetos Duraderos y Modelo de Precios

Short description:

Y todo esto ocurre a través de WebSockets, los workers redirigen las conexiones a los objetos duraderos. La sala de juego ejecuta la simulación del Juego de la Vida de Conway, enviando celdas en tiempo real a los clientes. Los objetos duraderos pueden ejecutarse en varios centros de datos a nivel global. Miles de personas pueden jugar al Juego de la Vida de Conway en salas separadas. Hay una demo disponible para que los usuarios la prueben. El modelo de precios para los objetos duraderos se basa en la duración activa de las solicitudes. Es rentable al crear objetos a nivel global. Cada objeto duradero es un hilo único de ejecución de JavaScript.

Y todo esto ocurre a través de WebSockets, los workers pueden redirigir una conexión WebSocket que ha sido enviada al worker al objeto duradero al que se conecta y todas estas celdas de la cuadrícula se pasan a través de WebSocket. Llegan a la sala de juego y la sala de juego está ejecutando la simulación real del Juego de la Vida de Conway. Y procesa todas las reglas de manera regular y luego envía las celdas en tiempo real cada vez que se produce una nueva generación y las envía a todos los clientes conectados.

Y uno puede imaginar que esto sucede, wow, este mapa es difícil de ver, uno puede imaginar que esto sucede en todo el mundo. Los objetos duraderos pueden ejecutarse en un subconjunto bastante grande de centros de datos que opera Cloudflare. En este momento, principalmente en la costa este y oeste de los Estados Unidos, y en Europa occidental y oriental, y en Asia y el sudeste asiático, y no hay límite en el número de objetos duraderos que se pueden crear. Entonces, con esta aplicación simple que tiene unas pocas líneas de código, puedes tener miles y miles y miles de personas jugando al Juego de la Vida de Conway entre sí en salas separadas.

Y así, en realidad tengo una demostración de esto. Voy a abrir esto. Creo que el Wi-Fi aquí ha sido lo suficientemente bueno como para permitir que las personas se conecten y lo prueben. Entonces, aquí, déjame mover esta ventana. Muy bien, así que si escaneas los códigos QR en la pantalla, deberías llegar a la misma página en la que estoy yo. Voy a crear una sala de Node Congress, y voy a crear un juego, y vamos a unirnos. Y así, si colocas una sola celda en la cuadrícula aquí, en realidad no va a hacer nada. Necesitas colocar algunas. La forma aquí se llama un planeador, y debería moverse por la cuadrícula, y así que si hago clic en enviar celdas aquí en la parte inferior, se enviará a través, y así que si otras personas se conectan, y colocan algunas celdas y las mueven, deberían aparecer en la pantalla, y deberías ver la misma simulación en cualquier dispositivo que estés usando como lo que estás viendo aquí arriba. Y toda esta simulación tiene lugar en un solo objeto duradero que se ha creado cerca de nosotros. De memoria, creo que el centro de datos de objetos duraderos más cercano aquí está en Ámsterdam, y así que esto se está ejecutando en algún lugar de Ámsterdam en una máquina en un edificio de concreto. Y, sí, eso es prácticamente todo en mi charla, lo dejaré funcionando por un rato para que la gente pueda jugar con él. Sí, espero que a la gente le guste esto. Esta es mi primera charla, así que estoy bastante emocionado al respecto. Sí, eso es todo por mi parte.

Entonces, voy a hacer la pregunta textualmente y tal vez la cambie un poco. Entonces, la pregunta es, ¿puedes hablar sobre el modelo de precios de usar objetos duraderos en producción? ¿Cuál sería un buen caso de uso donde los objetos duraderos sean una solución más económica? No necesitamos entrar en el modelo de precios en gran detalle, pero vale la pena señalar, ¿dónde es realmente una solución viable? Entonces, con los objetos duraderos, el caso de uso clave es si quieres crear todos estos objetos alrededor del mundo, y sería muy costoso ejecutar la infraestructura tú mismo. El modelo de precios se basa en la duración del reloj de pared cuando el objeto duradero está manejando una solicitud activa. Y así, si tu objeto duradero está manejando una solicitud, se te facturará por ese tiempo, una vez que devuelve la respuesta, ya no se te facturará. Entonces, sí, así es como funciona el modelo de facturación. ¿Hay momentos en los que no es, ya sabes, piensas, esto probablemente no es la solución correcta para un proyecto dado? Cada objeto duradero individual es un solo hilo de ejecución de JavaScript, y así que si tus objetos duraderos individuales necesitan manejar una cantidad significativa de carga, probablemente no sea el caso correcto para ti. Es realmente mejor cuando puedes dividir tu aplicación en muchos objetos duraderos, y en conjunto, tienes mucha carga, pero los objetos duraderos individuales no están tan ocupados.

9. Impacto en el rendimiento y réplicas de lectura

Short description:

Los objetos duraderos se ejecutan en un solo centro de datos, por lo que acceder a ellos desde el otro lado del mundo puede resultar en una alta latencia. Crear objetos duraderos para la coordinación en lugar de reutilizarlos puede ayudar a localizarlos. Sin embargo, si estás utilizando objetos duraderos para datos de larga duración, tendrás que lidiar con la latencia de las solicitudes que atraviesan el mundo. Se están considerando réplicas de lectura para proporcionar una vista más cercana de los datos almacenados.

Genial. Y, creo que ya has cubierto esto varias veces, pero haré la pregunta, dado que los objetos duraderos se ejecutan en un solo centro de datos, ¿cuáles son los impactos en el performance cuando se invocan desde el otro lado del mundo? Entonces, desafortunadamente, todavía tenemos que lidiar con la velocidad de la luz, por lo que si estás accediendo a un objeto duradero desde el otro lado del mundo, tendrás una alta latencia. La forma de solucionar esto es intentar crear objetos duraderos cada vez que necesites tener un punto de coordinación en lugar de reutilizarlos, y de esa manera, si todos tus clientes para una cosa en particular que estás tratando de coordinar están en el mismo lugar, tus objetos deberían estar ubicados cerca de ellos, pero si no puedes evitar esto, si los estás utilizando como un único punto de prueba o datos de larga duración, desafortunadamente, no hay nada que puedas hacer. Tu solicitud tendrá que atravesar el mundo. Estamos investigando la posibilidad de agregar réplicas de lectura, para que al menos puedas obtener una vista obsoleta de los datos almacenados en tus objetos duraderos, y eso podría estar ubicado más cerca de ti, pero no es algo que la plataforma admita actualmente.

QnA

Durable Objects Output Gate and Deno KV

Short description:

La puerta de salida de los Objetos Duraderos tiene un tiempo de espera y puede fallar si la escritura en el almacenamiento tarda demasiado. El código del usuario no puede cerrar manualmente la puerta de salida. Durable Objects y Deno KV son diferentes en términos de función sin servidor y coordinación de almacenamiento. No hay límite para el tamaño de almacenamiento de los Objetos Duraderos individuales. Las características de rendimiento no se pueden garantizar debido a las actualizaciones regulares y las prioridades de seguridad. Las conexiones WebSocket en los Objetos Duraderos se tratan de la misma manera que las solicitudes HTTP, utilizando un formato RPC interno.

Um, ¿qué sucede si tienes algunos objetos duraderos de salida ocupados para siempre, se retrasará o fallará al responder a la solicitud entrante? Creo que esta pregunta se refiere a la función de la puerta de salida. Esta, la puerta de salida tiene un tiempo de espera, por lo que si la escritura en el almacenamiento tarda más de 10 segundos, esa es una de las muchas formas en que la puerta de salida puede fallar, por lo que si es una solicitud de almacenamiento subyacente la que falla, o si se agota el tiempo de espera, la puerta de salida se romperá. Y esto simplemente reinicia el objeto, y cualquier cliente conectado deberá reconectarse a él, puedes hacer que comience desde cero. Realmente no hay forma de que el código del usuario cierre manualmente la puerta de salida y evite que se envíen mensajes salientes. Puedes controlar manualmente la puerta de entrada, no tengo un ejemplo de eso aquí, pero no es algo que la mayoría de las aplicaciones usen.

Interesante, genial. Esta pregunta surgió varias veces, como seguramente esperas en muchas formas, pero ¿podrías explicar brevemente la diferencia entre los Objetos Duraderos y Deno KV? Entonces, Deno KV, por lo que entiendo, es un almacén de datos al que accedes desde una función sin servidor sin estado, y Deno KV se replica en todo el mundo, y por lo tanto, es muy diferente de los Objetos Duraderos, donde los Objetos Duraderos tienen una función sin servidor específica que es específica para algún almacenamiento, y esa función sin servidor se ejecuta justo al lado del almacenamiento. Creo que Deno KV, desde el lado del almacenamiento duradero de los Objetos Duraderos, es un producto bastante similar, pero para hacer coordinación en el borde, por lo que puedo decir, no creo que tengan, no hay forma de dirigirse a una instancia específica para hacer coordinación en memoria. Sí, esa pregunta surgió de varias formas diferentes.

¿Cuál es el tamaño máximo para un Objeto Duradero? Esto es? No hay un límite para la cantidad de almacenamiento que un Objeto Duradero individual puede almacenar. Tenemos un límite para cada clase de cuántos datos puede almacenar toda la clase. No lo recuerdo de memoria. Ha pasado un tiempo desde que revisé los límites de uso. Hay límites en los tamaños individuales de los valores. Creo que los valores son de unos pocos megabytes, y las claves están en el rango de dos a cuatro kilobytes. Genial. Nos estamos quedando sin tiempo. Veamos qué otras preguntas podemos responder. ¿Tienen características de rendimiento garantizadas ya que la facturación depende del tiempo del reloj? Desafortunadamente, no. Este es un problema muy difícil de resolver cuando estás facturando según el tiempo del reloj porque actualizamos, como, el tiempo de ejecución de los workers en un ritmo muy regular. Siempre estamos actualizándonos con las actualizaciones de V8. Seguimos, como, el canal de lanzamiento beta de Chromium. Y así, digamos que surge un problema de seguridad en V8, entonces tenemos que actualizarlo, y luego hay una degradación del rendimiento en esa nueva versión. No hay mucho que podamos hacer allí. Necesitamos priorizar la seguridad, y por lo tanto, si tuviéramos alguna garantía en cuanto a la facturación, no podríamos garantizar eso en presencia de tener que hacer una actualización forzada como esa porque no tenemos un control del 100% del tiempo de ejecución de tu objeto.

De acuerdo. ¿Las conexiones WebSocket anulan o reducen en gran medida las ventajas del borde, en términos de velocidad? No estoy seguro de entender completamente esta pregunta. WebSocket, quiero decir, internamente en los objetos duraderos, los mensajes WebSocket y las solicitudes HTTP normales se tratan de la misma manera. En realidad, no usamos HTTP como transporte en el fondo. Todo se convierte en un formato RPC interno y se envía a través de eso.

WebSockets, HTTP, Demo Code, and Conclusion

Short description:

No hay diferencia en términos de rendimiento entre WebSockets y HTTP para objetos duraderos. Estamos trabajando en solucionar la diferencia de facturación. El código de la demostración se publicará en Twitter después de la conferencia. Gracias por una excelente charla.

Entonces, en realidad no hay diferencia entre WebSockets y HTTP en términos de características de rendimiento para objetos duraderos. Existe una diferencia de facturación en la que estamos trabajando actualmente para solucionar, pero eso debería eliminarse muy pronto.

Genial. Y la última pregunta es, ¿está disponible el código de esa demostración? Lo publicaré en mi Twitter después de la conferencia. Necesito hacerle algunas mejoras. Soy más desarrollador de C++ que desarrollador de JavaScript. Probablemente sea el desarrollador de JavaScript más antiguo en unos 10 años. Así que todos pueden decirme lo malo que es en Twitter. Nadie te dirá lo malo que es en Twitter, pero publícalo, nos interesaría mucho verlo.

Muchas gracias por una excelente charla. Realmente disfruté charlar aquí en la sesión de preguntas y respuestas.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2021React Advanced Conference 2021
36 min
Living on the Edge
React 18 introduces new APIs for rendering applications asynchronously on the server, enabling a simpler model for architecting and shipping user interfaces. When deployed on edge networking platforms like Cloudflare Workers, we can get dramatic performance and user experience improvements in our applications. In this talk, Sunil will demo and walk through this new model of writing React applications, with some insight into the implications for data fetching, styling, and overall direction of the React ecosystem.
Node Congress 2022Node Congress 2022
31 min
Database Access on the Edge with Cloudflare Workers & Prisma
Edge functions are pushing the limit of serverless computing – but with new tools, come new challenges. Due to their limitations, edge functions don't allow talking to popular databases like PostgreSQL and MySQL. In this talk, you will learn how you can connect and interact with your database from Cloudflare Workers using the Prisma Data Proxy.
You can check the slides for Alex's talk here. 
Node Congress 2022Node Congress 2022
30 min
Static first websites with Cloudflare Workers
Static websites give you all sorts of great benefits. You don’t have to worry about security or scalability. They are simple to cache, cheap to host and a breeze to maintain! But sometimes I miss all the fun things you can do with just a little bit of state! Combining the Cloudflare Pages platform with Durable Objects and the HTMLRewriter API, you can have your cake and eat it too! We’ll replicate a full WordPress experience with comments, top posts, like buttons and a page counter. All on Cloudflare’s free static site hosting platform.
You can check the slides for Jonathan's talk here.
React Advanced Conference 2022React Advanced Conference 2022
9 min
Building full-stack applications on the Edge
Scaling and maintaining applications can be a pain, especially when thinking of how to build to get the user experience to a level that you are proud of. With all these shifting parts to consider, it is important to abstract parts of your applications to global reliable services. In this talk, we will discuss some of the services that Cloudflare provides, and the role they play in improving the overall developer and user experience.

Workshops on related topic