¿Node.js siempre será más lento que Golang?

Existe la sensación de que, literalmente, cada semana aparece un nuevo "marco web" para Node.js, que se llama algo que funciona más rápido que todo lo anterior. Todo el mundo sabe que Express es lento, pero ¿es el próximo marco capaz de mejorar realmente el rendimiento del subsistema de E / S Node.js? Lo único que puede hacer es eliminar la carga excesiva en el sistema creado por Express. No se habla de mejorar algo fundamental. De hecho, para mejorar radicalmente la situación, debe trabajar a un nivel más profundo y no agregar nuevas abstracciones sobre Node.js.

imagen

¿Qué se necesita para crear aplicaciones de servidor en la plataforma Node.js que se ejecutan mucho más rápido que todo lo que es hoy?

Análisis de la situación


Express es uno de los frameworks web más antiguos para Node.js. Se basa en las capacidades estándar de esta plataforma, brindando a los desarrolladores una interfaz conveniente basada en el concepto de la aplicación y permitiéndole administrar rutas URL, parámetros, métodos y similares.

Express es simple; ayuda a los programadores a desarrollar aplicaciones rápidamente. Lo único que le falta es el rendimiento. Los proyectos que aparecen constantemente, como Fastify, se esfuerzan por brindar a los desarrolladores las mismas capacidades que Express, pero con menos pérdida de rendimiento. Pero ellos mismos son los que crean una carga adicional en el sistema y afectan gravemente el rendimiento. Están severamente limitados por lo que puede proporcionar la plataforma Node.js. Y puede dar, en comparación con la competencia, no tanto.


El número de solicitudes HTTP procesadas por diferentes servidores por segundo

Presta atención a la línea roja. Esta es la plataforma máxima Node.js. Para ella, independientemente de si sus nombres contienen la palabra "rápido" o no, no pueden cruzar esta línea. Este es en realidad un límite de rendimiento muy bajo cuando se compara la plataforma Node.js con sus alternativas populares como Golang.

Afortunadamente, Node.js admite complementos C ++, carpetas de Google V8 que le permiten vincular JavaScript y C ++, y le permite llamar a cualquier mecanismo desde JavaScript, incluso si estos mecanismos son proporcionados por algo distinto a la plataforma Node.js.

Esto permite expandir y mejorar las capacidades de las aplicaciones JavaScript, le permite alcanzar nuevos niveles de rendimiento. Esto permite que los programas de JavaScript expriman todo lo posible del motor de Google V8, sin limitarse a lo que los desarrolladores de Node.js encontraron suficiente.

Sobre µWebSockets.js


A principios de este mes, lancé un nuevo proyecto: µWebSockets.js . GitHub se usa como hosting para su código, no npm, pero puede instalarlo para Node.js usando npm de esta manera:

npm install uNetworking/uWebSockets.js#v15.0.0 

Para trabajar con µWebSockets.js, no necesita un compilador. Linux, macOS y Windows son compatibles. La versión inicial del sistema es 15.0.0, la numeración de la versión se lleva a cabo de acuerdo con las reglas de versiones semánticas.

µWebSockets.js es un servidor web alternativo para aplicaciones de back-end escritas en JS. Consiste en aproximadamente 6 mil líneas de código C y C ++ y supera significativamente las mejores soluciones escritas en Golang. Entonces, el intercambio de bitfinex.com ya ha portado sus dos API comerciales (REST y WebSocket) a µWebSockets.js y las está introduciendo gradualmente en la producción. Paolo Ardoino de Bitfinex señala que este es un gran proyecto. Me gustaría decir que el hecho de que tuve la oportunidad de lanzar µWebSockets.js se debe totalmente al apoyo que me brindaron BitMEX, Bitfinex y Coinbase.

Características de µWebSockets.js


µWebSockets.js es un nuevo proyecto lanzado bajo la licencia Apache 2.0, que es una continuación de lo que se conoce como "uws". Este proyecto es una pila completa para Google V8, que comienza en el nivel del núcleo del sistema operativo, reemplaza por completo las características estándar de Node.js y representa un subsistema de E / S estable, seguro, que cumple con los estándares, rápido y liviano para Node.js. Así es como se ve la interacción de la aplicación JS con el sistema operativo usando µWebSockets.js.


Interacción de la aplicación JS con el SO utilizando µWebSockets.js

Como puede ver, el proyecto consta de varias capas. Cada capa depende solo de la capa anterior. Esta arquitectura simplifica la identificación y corrección de errores, así como la implementación del trabajo para expandir la solución debido a la implementación de nuevas características.

Cabe señalar que la capa µSockets sí misma consta de tres subcapas, que son mecanismos para trabajar con eventos y con la red, así como herramientas para proteger los datos. Esto permite, si es necesario, reemplazar partes de la solución, agregar implementaciones alternativas de ciertas características al sistema, sin encontrar la necesidad de cambiar el código a un nivel superior.

Por ejemplo, si necesita reemplazar OpenSSL con algo, simplemente cambie el archivo ssl.c con sus seiscientas líneas de código a lo que necesita. Sin embargo, otras capas del sistema ni siquiera saben qué es SSL. Este enfoque, además de la conveniencia de reemplazar algunas partes del sistema con otras, también conduce a una simplificación del proceso de detección de errores.


ΜSockets subcapas internas

La arquitectura presentada aquí es muy diferente de la monolítica que se usa en Node.js, donde en el mismo archivo de código fuente puede encontrar llamadas a libuv, comandos para trabajar con el sistema y llamadas a OpenSSL y V8. En Node.js todo esto es mixto, nadie se propuso aislar partes individuales de esta plataforma. Esto complica enormemente el proceso de realizar cambios importantes en Node.js.

Sobre el desarrollo de µWebSockets.js


Aquí hay un ejemplo extremadamente simplificado y abreviado de trabajar con µWebSockets.js, cuya tarea principal es demostrar las capacidades básicas del sistema.

 /* SSL-   */ uWS.SSLApp({   key_file_name: 'misc/key.pem',   cert_file_name: 'misc/cert.pem',   passphrase: '1234' }).get('/hello', (res, req) => {   /*    */   res.end('Hello World!'); }).ws('/*', {   open: (ws, req) => {       console.log('A WebSocket connected via URL: ' + req.getUrl() + '!');   },   message: (ws, message, isBinary) => {       /* OK   false          *     */       let ok = ws.send(message, isBinary);   },   drain: (ws) => {       console.log('WebSocket backpressure: ' + ws.getBufferedAmount());   },   close: (ws, code, message) => {       console.log('WebSocket closed');   } }).listen(port, (token) => {   if (token) {       console.log('Listening to port ' + port);   } }); 

En cierto sentido, podemos decir que µWebSockets.js que usa SSL puede omitir Gorilla WebSocket, una implementación del protocolo WebSocket en Go, sin SSL. Es decir, resulta que el código JS puede intercambiar mensajes usando SSL incluso más rápido que, bajo ciertas condiciones, el código escrito en Go sin SSL. Creo que este es un excelente resultado.

Implementación rápida del protocolo WebSocket


Socket.IO, en muchos sentidos, puede considerarse el equivalente de Express en tiempo real. Ambos proyectos aparecieron hace mucho tiempo, es fácil trabajar con ellos, son populares. Pero ellos, entre otras cosas, también son lentos.


Diversas implementaciones de WebSocket

Las tareas que el desarrollador de Socket.IO ayuda a resolver se reducen a la implementación de la funcionalidad para publicar mensajes y suscribirse a ellos, a la capacidad de enviar y recibir mensajes.

Al mismo tiempo, vale la pena señalar el uso de algunos mecanismos adicionales para trabajar con el protocolo WebSocket, ya que los navegadores han respaldado esta tecnología durante mucho tiempo. El tráfico SSL no puede ser interpretado por los proxys corporativos, pasa a través de ellos de la misma manera que cualquier tráfico HTTP; como resultado, el uso del protocolo WebSocket sobre SSL no bloquea el tráfico correspondiente. Se pueden proporcionar mecanismos de repuesto para soportar WebSocket, pero no tiene sentido usarlos. Solo aumentan injustificadamente la complejidad de las decisiones.

Uno de los objetivos de µWebSockets.js es proporcionar a los desarrolladores características similares a las que se encuentran en Socket.IO para que µWebSockets.js pueda reemplazar completamente a Socket.IO sin la necesidad de envoltorios de alto nivel . Esto es posible si no se utiliza algún protocolo especial no estándar.

Muchas empresas tienen problemas para publicar y suscribirse a mensajes mientras trabajan con WebSocket. Cabe señalar que en la versión descrita de µWebSockets.js a estas características no se les prestó mucha atención, pero ahora se está trabajando seriamente en ellas. El resultado será muy rápido (las pruebas muestran que µWebSockets.js ya es más rápido que Redis). Así que estad atentos.

Resumen


Actualmente se está desarrollando µWebSockets.js, se agregan nuevas características al proyecto y se corrigen los errores. Tomará algún tiempo deshacerse de esos defectos menores que son característicos de los primeros lanzamientos de nuevos programas. Tenga en cuenta que este es un gran proyecto que consta de miles de líneas de código escritas en C y C ++, que se almacenan en tres repositorios. Aquí se encuentra el contenedor de JavaScript: uWebSockets.js. Aquí hay un servidor web escrito en C ++ - uWebSockets. Y aquí está la biblioteca base escrita en C - uSockets.

El proyecto en cuestión es utilizado por empresas, los programas utilizados por los cuales crean una gran carga en los subsistemas de E / S. En estas empresas, la estabilidad y la seguridad, que es completamente natural y obvia, son las características más importantes del software que utilizan.

Estimados lectores! ¿Planea usar µWebSockets.js en sus proyectos?

Source: https://habr.com/ru/post/439976/


All Articles