Índice
- Nuestra necesidad de un servicio Pub/Sub
- Elegir construir vs. Comprar
- Construyendo nuestra solución
- Arquitectura a 30000 pies
- Conclusión (TLDR)
Muchas aplicaciones actuales dependen de la transferencia de datos en tiempo real. Como el tamaño de los datos de cada mensaje en nuestro sistema varía desde unos pocos bytes hasta 100 MB, necesitábamos una solución escalable que pudiera soportar una multitud de escenarios. En este artículo, Dhimil Gosalia explica por qué debería considerar crear también un servicio Pub/Sub interno. A través de la lente del problema del mundo real de BrowserStack, obtendrá una comprensión más profunda de los requisitos y el proceso de creación de su propio Pub/Sub.
El mundo actual funciona en tiempo real. Ya sea negociando acciones o pidiendo comida, los consumidores de hoy esperan resultados inmediatos. Del mismo modo, todos esperamos saber cosas de inmediato, ya sea sobre noticias o deportes. En otras palabras, Zero es el nuevo héroe.
Esto también se aplica a los desarrolladores de software: ¡posiblemente algunas de las personas más impacientes! Antes de profundizar en la historia de BrowserStack, sería negligente por mi parte no brindar algunos antecedentes sobre Pub/Sub. Para aquellos de ustedes que están familiarizados con los conceptos básicos, no duden en saltarse los dos párrafos siguientes.
Muchas aplicaciones actuales dependen de la transferencia de datos en tiempo real. Veamos más de cerca un ejemplo: las redes sociales. Facebook y Twitter generan feeds relevantes y tú (a través de su aplicación) los consumes y espías a tus amigos. Lo logran con una función de mensajería, en la que si un usuario genera datos, se publicarán para que otros los consuman en un abrir y cerrar de ojos. Cualquier retraso significativo hará que los usuarios se quejen, el uso disminuirá y, si persiste, se producirá. Hay mucho en juego, al igual que las expectativas de los usuarios. Entonces, ¿cómo soportan servicios como WhatsApp, Facebook, TD Ameritrade, Wall Street Journal y GrubHub grandes volúmenes de transferencias de datos en tiempo real?
Todos ellos utilizan una arquitectura de software similar a alto nivel llamada modelo “Publish-Subscribe”, comúnmente conocido como Pub/Sub.
“En la arquitectura de software , publicación-suscripción es un patrón de mensajería en el que los remitentes de mensajes , llamados editores, no programan los mensajes para que se envíen directamente a receptores específicos, llamados suscriptores, sino que clasifican los mensajes publicados en clases sin saber qué suscriptores, si cualquiera, puede haber. De manera similar, los suscriptores expresan interés en una o más clases y solo reciben mensajes que son de su interés, sin saber qué editores, si los hay, existen”.
— Wikipedia
¿Aburrido de la definición? Volvamos a nuestra historia.
En BrowserStack, todos nuestros productos admiten (de una forma u otra) software con un componente sustancial de dependencia en tiempo real, ya sea registros de pruebas automatizadas, capturas de pantalla del navegador recién creadas o transmisión móvil de 15 fps.
En tales casos, si cae un solo mensaje, un cliente puede perder información vital para prevenir un error . Por lo tanto, necesitábamos escalar para requisitos de tamaño de datos variados. Por ejemplo, con los servicios de registro de dispositivos en un momento determinado, se pueden generar 50 MB de datos en un solo mensaje. Tamaños como este podrían bloquear el navegador. Sin mencionar que el sistema de BrowserStack necesitaría escalar para productos adicionales en el futuro.
Como el tamaño de los datos de cada mensaje varía desde unos pocos bytes hasta 100 MB, necesitábamos una solución escalable que pudiera admitir una multitud de escenarios. En otras palabras, buscábamos una espada que pudiera cortar todos los pasteles. En este artículo, analizaré el por qué, el cómo y los resultados de crear nuestro servicio Pub/Sub internamente.
A través de la lente del problema del mundo real de BrowserStack, obtendrá una comprensión más profunda de los requisitos y el proceso de creación de su propio Pub/Sub .
Nuestra necesidad de un servicio Pub/Sub
BrowserStack tiene alrededor de 100 millones de mensajes, cada uno de los cuales tiene entre aproximadamente 2 bytes y 100+ MB. Estos se transmiten por todo el mundo en cualquier momento, todos a diferentes velocidades de Internet.
Los mayores generadores de estos mensajes, por tamaño de mensaje, son nuestros productos BrowserStack Automate. Ambos tienen paneles de control en tiempo real que muestran todas las solicitudes y respuestas para cada comando de una prueba de usuario. Entonces, si alguien ejecuta una prueba con 100 solicitudes donde el tamaño promedio de solicitud-respuesta es de 10 bytes, esto transmite 1×100×10 = 1000 bytes.
Ahora consideremos el panorama más amplio ya que, por supuesto, no realizamos solo una prueba al día. Más de aproximadamente 850.000 pruebas de BrowserStack Automate y App Automate se ejecutan con BrowserStack todos los días. Y sí, tenemos un promedio de alrededor de 235 solicitudes-respuestas por prueba. Dado que los usuarios pueden tomar capturas de pantalla o solicitar fuentes de páginas en Selenium, nuestro tamaño promedio de solicitud-respuesta es de aproximadamente 220 bytes.
Entonces, volviendo a nuestra calculadora:
850.000×235×220 = 43.945.000.000 bytes (aprox.) o sólo 43,945 GB por día
Ahora hablemos de BrowserStack Live y App Live . Seguramente tenemos a Automate como nuestro ganador en forma de tamaño de datos. Sin embargo, los productos Live toman la delantera en cuanto a la cantidad de mensajes pasados. Por cada prueba en vivo, se pasan alrededor de 20 mensajes por minuto. Realizamos alrededor de 100.000 pruebas en vivo, cada una de las cuales dura en promedio alrededor de 12 minutos, lo que significa:
100.000×12×20 = 24.000.000 mensajes por día
Ahora vamos a lo asombroso y notable: creamos, ejecutamos y mantenemos la aplicación para esto llamado pusher con 6 instancias t1.micro de ec2. ¿El costo de ejecutar el servicio? Alrededor de $70 por mes .
Elegir construir vs. Comprar
Lo primero es lo primero: como startup, como la mayoría de las demás, siempre estábamos entusiasmados de construir cosas internamente. Pero todavía evaluamos algunos servicios disponibles. Los requisitos principales que teníamos eran:
- Fiabilidad y estabilidad,
- Alto rendimiento y
- Rentabilidad.
Dejemos de lado los criterios de rentabilidad, ya que no se me ocurre ningún servicio externo que cueste menos de $70 al mes (¡envíame un tweet si conoces uno que lo cueste!). Entonces nuestra respuesta es obvia.
En términos de confiabilidad y estabilidad, encontramos empresas que brindaban Pub/Sub como servicio con un SLA de tiempo de actividad de más del 99,9 por ciento, pero había muchos términos y condiciones adjuntos. El problema no es tan simple como cree, especialmente si considera las vastas tierras de Internet abierta que se encuentran entre el sistema y el cliente. Cualquiera que esté familiarizado con la infraestructura de Internet sabe que la conectividad estable es el mayor desafío. Además, la cantidad de datos enviados depende del tráfico. Por ejemplo, una tubería de datos que está en cero durante un minuto puede explotar durante el siguiente. Los servicios que ofrecen una fiabilidad adecuada durante esos momentos de ráfaga son raros (Google y Amazon).
El rendimiento para nuestro proyecto significa obtener y enviar datos a todos los nodos de escucha con una latencia cercana a cero . En BrowserStack, utilizamos servicios en la nube (AWS) junto con alojamiento compartido. Sin embargo, nuestros editores y/o suscriptores podrían estar ubicados en cualquier lugar. Por ejemplo, puede implicar que un servidor de aplicaciones de AWS genere datos de registro muy necesarios o terminales (máquinas donde los usuarios pueden conectarse de forma segura para realizar pruebas). Volviendo al tema de la Internet abierta nuevamente, si tuviéramos que reducir nuestro riesgo, tendríamos que asegurarnos de que nuestro Pub/Sub aprovechara los mejores servicios de host y AWS. Fanfics en Español
Otro requisito esencial era la capacidad de transmitir todo tipo de datos (Bytes, texto, datos multimedia extraños, etc.). Considerando todo esto, no tenía sentido depender de una solución de terceros para respaldar nuestros productos. A su vez, decidimos revivir nuestro espíritu emprendedor y arremangarnos para codificar nuestra propia solución.
Construyendo nuestra solución
Pub/Sub por diseño significa que habrá un editor que generará y enviará datos, y un Suscriptor que los aceptará y procesará. Esto es similar a una radio: un canal de radio transmite (publica) contenido en todas partes dentro de un rango. Como suscriptor, puedes decidir si sintonizas ese canal y lo escuchas (o apagas la radio por completo).
A diferencia de la analogía de la radio, donde los datos son gratuitos para todos y cualquiera puede decidir sintonizarlos, en nuestro escenario digital necesitamos autenticación, lo que significa que los datos generados por el editor solo pueden ser para un único cliente o suscriptor en particular.
Arriba hay un diagrama que proporciona un ejemplo de un buen Pub/Sub con:
- Editores
Aquí tenemos dos editores que generan mensajes basados en una lógica predefinida. En nuestra analogía con la radio, estos son nuestros radio jockeys que crean el contenido. - Temas
Aquí hay dos, lo que significa que hay dos tipos de datos. Podemos decir que estos son nuestros canales de radio 1 y 2. - Suscriptores
Tenemos tres y cada uno lee datos sobre un tema en particular. Una cosa a tener en cuenta es que el suscriptor 2 está leyendo varios temas. En nuestra analogía con la radio, estas son las personas que sintonizan un canal de radio.
Comencemos a comprender los requisitos necesarios para el servicio.
- Un componente evento
Esto se activa sólo cuando hay algo que activar. - Almacenamiento transitorio
Esto mantiene los datos persistidos por un corto período de tiempo, de modo que si el suscriptor es lento, todavía tiene una ventana para consumirlos. - Reducir la latencia
Conectar dos entidades a través de una red con saltos y distancia mínimos.
Elegimos una pila de tecnología que cumplía con los requisitos anteriores:
- Node.js
Porque ¿por qué no? En todo caso, no necesitaríamos un procesamiento de datos pesado y, además, es fácil de incorporar. - Redis
admite datos perfectamente de corta duración. Tiene todas las capacidades para iniciar, actualizar y caducar automáticamente. También supone menos carga para la aplicación.
Node.js para conectividad de lógica empresarial
Node.js es un lenguaje casi perfecto cuando se trata de escribir código que incorpora IO y eventos. Nuestro problema particular tenía ambos, haciendo que esta opción sea la más práctica para nuestras necesidades.
Seguramente otros lenguajes como Java podrían estar más optimizados, o un lenguaje como Python ofrece escalabilidad. Sin embargo, el costo de comenzar con estos lenguajes es tan alto que un desarrollador podría terminar de escribir código en Node en el mismo tiempo.
Para ser honesto, si el servicio tuviera la posibilidad de agregar funciones más complicadas, podríamos haber buscado otros idiomas o una pila completa. Pero aquí tenemos un matrimonio hecho en el cielo. Aquí está nuestro paquete.json :
{ "name": "Pusher", "version": "1.0.0", "dependencies": { "bstack-analytics": "*****", // Hidden for BrowserStack reasons. :) "ioredis": "^2.5.0", "socket.io": "^1.4.4" }, "devDependencies": {}, "scripts": { "start": "node server.js" }}
En pocas palabras, creemos en el minimalismo, especialmente cuando se trata de escribir código. Por otro lado, podríamos haber usado bibliotecas como Express para escribir código extensible para este proyecto. Sin embargo, nuestro instinto emprendedor decidió dejarlo pasar y guardarlo para el próximo proyecto. Herramientas adicionales que utilizamos:
- ioredis
Esta es una de las bibliotecas más compatibles para la conectividad de Redis con Node.js utilizada por empresas como Alibaba. - socket.io
La mejor biblioteca para una conectividad elegante y alternativa con WebSocket y HTTP.
Redis para almacenamiento transitorio
Redis como servicio escalable es muy confiable y configurable. Además, existen muchos proveedores de servicios administrados confiables para Redis, incluido AWS. Incluso si no desea utilizar un proveedor, es fácil comenzar con Redis.
Analicemos la parte configurable. Comenzamos con la configuración maestro-esclavo habitual, pero Redis también viene con modos de clúster o centinela. Cada modo tiene sus propias ventajas.
Si pudiéramos compartir los datos de alguna manera, un clúster de Redis sería la mejor opción. Pero si compartimos los datos mediante alguna heurística, tenemos menos flexibilidad ya que la heurística debe seguirse en todos los casos . ¡Menos reglas, más control es bueno para la vida!
Redis Sentinel funciona mejor para nosotros ya que la búsqueda de datos se realiza en un solo nodo, conectándose en un momento determinado mientras los datos no están fragmentados. Esto también significa que incluso si se pierden varios nodos, los datos siguen distribuidos y presentes en otros nodos. Entonces tienes más HA y menos posibilidades de pérdida. Por supuesto, esto eliminó las ventajas de tener un clúster, pero nuestro caso de uso es diferente.
Arquitectura a 30000 pies
El siguiente diagrama proporciona una imagen de muy alto nivel de cómo funcionan nuestros paneles de Automate y App Automate . ¿Recuerdas el sistema en tiempo real que teníamos en la sección anterior?
En nuestro diagrama, nuestro flujo de trabajo principal está resaltado con bordes más gruesos. La sección “automatizar” consta de:
- Terminales
Compuesto por las versiones originales de Windows, OSX, Android o iOS que obtienes mientras pruebas en BrowserStack. - Hub
El punto de contacto para todas sus pruebas de Selenium y Appium con BrowserStack.
La sección "servicio al usuario" aquí es nuestro guardián, asegurando que los datos se envíen y guarden para la persona adecuada. También es nuestro guardián de seguridad. La sección "empujador" incorpora el corazón de lo que discutimos en este artículo. Está formado por los sospechosos habituales, entre ellos:
- Redis
Nuestro almacenamiento transitorio para mensajes, donde en nuestro caso los registros automáticos se almacenan temporalmente. - Editor
Esta es básicamente la entidad que obtiene datos del centro. Todas las respuestas a sus solicitudes son capturadas por este componente que escribe en Redissession_id
como canal. - Suscriptor
Lee los datos de Redis generados parasession_id
. También es el servidor web para que los clientes se conecten a través de WebSocket (o HTTP) para obtener datos y luego enviarlos a clientes autenticados.
Finalmente, tenemos la sección del navegador del usuario, que representa una conexión WebSocket autenticada para garantizar que session_id
se envíen los registros. Esto permite que el JS de front-end lo analice y embellezca para los usuarios.
De manera similar al servicio de registros, aquí tenemos un empujador que se utiliza para otras integraciones de productos. En lugar de session_id
, utilizamos otra forma de identificación para representar ese canal. ¡Todo esto funciona con Pusher!
Conclusión (TLDR)
Hemos tenido un éxito considerable en la creación de Pub/Sub. Para resumir por qué lo construimos internamente:
- Se adapta mejor a nuestras necesidades;
- Más barato que los servicios subcontratados;
- Control total sobre la arquitectura general.
Sin mencionar que JS encaja perfectamente en este tipo de escenario. ¡Lo que necesita el problema es un bucle de eventos y una gran cantidad de IO! JavaScript es la magia del pseudo hilo único.
Los eventos y Redis como sistema simplifican las cosas para los desarrolladores, ya que pueden obtener datos de una fuente y enviarlos a otra a través de Redis. Entonces lo construimos.
Si el uso se adapta a su sistema, ¡recomiendo hacer lo mismo!
Otras lecturas
- Creación y acoplamiento de una aplicación Node.js con arquitectura sin estado con la ayuda de Kinsta
- El final de mi viaje Gatsby
- Calendarios de eventos para Web simplificados con estas opciones comerciales
- Las nuevas unidades de ventana gráfica CSS no resuelven el problema clásico de la barra de desplazamiento
(rb, ra, il, mrn)Explora más en
- Nodo.js
- javascript
- Herramientas
Tal vez te puede interesar:
- Creación de su propia biblioteca de validación de React: la experiencia del desarrollador (Parte 3)
- Introducción a Quasar Framework: creación de aplicaciones multiplataforma
- Creación de un componente web retro que se puede arrastrar con iluminación
- Creación y acoplamiento de una aplicación Node.js con arquitectura sin estado con la ayuda de Kinsta
Creación de un servicio Pub/Sub interno utilizando Node.js y Redis
Nuestra necesidad de un servicio Pub/SubElegir construir vs. ComprarConstruyendo nuestra soluciónArquitectura a 30000 piesConclusión (TLDR)Índice
programar
es
https://aprendeprogramando.es/static/images/programar-creacion-de-un-servicio-pubsub-interno-utilizando-node-946-0.jpg
2024-09-21
Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente