Reducción de la utilización de la CPU en un servidor nodejs

Estoy buscando formas interesantes de reducir la utilización de la CPU en un servidor NodeJS.

Durante mi investigación he encontrado el siguiente artículo: http://engineering.linkedin.com/nodejs/blazing-fast-nodejs-10-performance-tips-linkedin-mobile

Todos estos son excelentes consejos, pero tengo una pregunta con respecto a la pista n.º 4.

¿Esto realmente significa que un usuario está solicitando "JavaScriptTemplate.html" y luego se solicita todo el JSON posteriormente (que no se implementa aquí)?

Suponiendo que todo el contenido dinámico debería estar disponible sin la interacción del usuario (por ejemplo, solicitar JSON en un evento de clic de botón), ¿cuál es la mejor manera de lograrlo? Puedo pensar en cargar dependencias JS adicionales (requirejs) donde se ejecutan funciones para solicitar las cosas JSON.

Dado que nunca veo grandes sitios web para llamar a archivos html estáticos, sino que solicitan rutas a sus servidores de aplicaciones, ¿qué tan común es la solución sugerida por el enlace anterior? ¿Realmente usan plantillas del lado del servidor para desperdiciar la utilización de la CPU en contenido de texto mayormente estático?

Para Node (expressJS), esta debe ser una forma subóptima, especialmente si el HTML que se va a producir es bastante complejo... idealmente, Node debería operar como un servidor API que proporciona datos JSON.

¿Tienes algunas ideas para compartir?

preguntado el 31 de diciembre de 12 a las 15:12

2 Respuestas

Gracias por compartir la publicación, es excelente (y muy oportuna para mí).

En realidad, está haciendo dos preguntas: 1) cómo cargar datos para representar el lado del cliente html sin interacción del cliente y 2) cómo enviar un archivo estático a un navegador cuando el usuario realmente solicita una ruta.

Representación de página sin interacción del usuario y mi ¢2 en el cliente MVC

1) Debe ejecutar todo el código de inicialización/carga de datos/representación para representar la página después de que se haya cargado. Si usa jQuery en el cliente (como lo hacen la mayoría de las aplicaciones web):

$(document).ready(function(){
    // Your code here
});

solo esta copiado de documentos de jQuery.

La mayoría de la gente usa backbone/guion bajo para construir la capa MVC en el cliente. Aunque hay muchos marcos del lado del cliente mucho más sofisticados (y aparentemente más poderosos) para hacerlo, esta pareja le brinda el poder suficiente sin limitar sus opciones o reducir su flexibilidad que definitivamente necesitará en algún momento. El guión bajo (que de todos modos es una dependencia de la red troncal) además de muchas funciones muy útiles (se sorprenderá de lo que es posible con JavaScript si dedica una hora a leer todo el manual de una página) tiene sus propias plantillas que son engañosamente simples y al mismo tiempo tiempo extremadamente poderoso ya que solo ejecutan todas las plantillas internas de javascript.

Aunque por lo general es algo malo tener la lógica de la aplicación en las plantillas (como lo permite el subrayado y la mayoría de los motores de plantillas más sofisticados y "más poderosos" no lo hacen), a menudo es muy útil y mucho mejor poder agregar algo de lógica en la plantilla. cuando te encuentras en un rincón estrecho (como sucede a menudo) que rediseñar mucha lógica de la aplicación o agregar plantillas adicionales.

Además, mi opinión es evitar usar require.js o cualquier otro cargador de módulos (hasta que realmente deba usarlos) como escribí aquí.

Sirviendo html estático para cualquier ruta y configuración nginx para nodo-como-api

2) Debe volver a escribir las solicitudes en todas las rutas para responder con el mismo archivo html estático (o varios archivos html dependientes de la ruta). Dependiendo de sus preferencias o requisitos de la aplicación, puede ser el archivo con un cuerpo vacío (en cuyo caso los usuarios verán una página en blanco hasta que se carguen sus datos y la página se represente/inserte en el cuerpo), alguna página de bienvenida o incluso alguna página de plantilla donde en lugar de datos se muestra una rueda giratoria.

La forma en que reescribe las solicitudes depende del servidor web que utilice para servir contenido estático y para las solicitudes de proxy. Si usa Apache (una opción poco probable con Node, ya que es síncrono), necesita usar archivos .htaccess. Si usa Nginx como lo hace la mayoría de las personas que usan el nodo, debe usar la directiva de reescritura dentro del bloque del servidor en el archivo de configuración como se hace en el ejemplo a continuación:

server {
    listen       80;
    server_name  example.com;
    root         html/example;

    access_log   logs/example.log;

    # location block below sends specific static assets from inside your app's
    # public directory when routes /img, /js, /css, /views are requested
    location ~ /(img|js|css|views)/ {
        rewrite ^(.*)$ /public/$1 break;
    }

    # location block below proxies all data requests (/api route) to your node app
    location /api {
        proxy_pass             http://localhost:3000/;
        proxy_redirect         http://localhost:3000/ http://example.com;
        proxy_connect_timeout  30s;
        proxy_read_timeout     30s;
        proxy_cookie_domain    localhost example.com;
        #proxy_http_version     1.1;
    }

    # location block below rewrites all other routes to a specific html file
    # that is sent to the client and that is supposed to load all JS and
    # static assets to render a page
    location / {
        rewrite ^(.*)$ /public/app.html;
    }
}

La forma en que presenta una página en el cliente (y los datos que solicita del servidor para hacerlo) dependerá de la ruta que solicitó el usuario (a la que puede acceder/cambiar en javascript, así como también puede configurar/acceder/cambiar las cookies ). Toda la navegación dentro de la aplicación (cuando el usuario hace clic en cualquier botón o enlace interno; debe capturar todos los eventos de clic) ocurre sin solicitudes adicionales de páginas o activos estáticos que ya están cargados, solo se envían solicitudes de datos al servidor.

Espero que ayude.

Actualización SEO

La configuración sugerida para nginx es adecuada solo si no necesita ninguna página indexada por robots y visible para otras aplicaciones web que necesitan sus html estáticos, como Facebook, por ejemplo, para las páginas que desea indexar, debe agregar condiciones a enrute las solicitudes de los robots de manera diferente (basado en $http_user_agent) y también represente algunos html estáticos para esas rutas. Pero puede ser un html puramente semántico diferente (más pequeño, sin imágenes de diseño, divs/clases de diseño, elementos de interfaz de usuario y javascript para reducir las solicitudes de robots de rastreo y aplicaciones web).

contestado el 23 de mayo de 17 a las 11:05

Gracias por su arduo trabajo. ¡Respuesta impresionante! 1: jquery's ready() es excelente, pero ahora todos estos buenos marcos como angular están surgiendo y planeo usar uno de ellos para manejar tales cosas. 2: Un pequeño malentendido aquí. Mi verdadera preocupación proviene de la impresión de que muchas páginas usan plantillas del lado del servidor en sus servidores de aplicaciones para generar principalmente páginas html estáticas (por lo que no es posible un almacenamiento en caché real). Usar nginx (como mencionaste) parece ser mucho mejor... Lo que me parece "gracioso" es solicitar estos archivos html a través de la URL directamente (consulte la otra respuesta a continuación)... - josefrizz

1. 1) No hay contradicción en el uso de la mayoría de los marcos y jquery.ready(). 2) Pasé algún tiempo con Angular.js, hace exactamente lo que los creadores de backbone llaman "pintarte en un rincón al tomar decisiones para las que estás mejor equipado" en su porque columna vertebral sección, y lo hace antes de lo esperado. Desafortunadamente, la mayoría de los otros marcos "agradables" parecen hacer lo mismo. Backbone, aunque no se ve bien, es extremadamente útil y muy fácil de aprender. - esp

2. 1) La generación de páginas en el lado del servidor es histórica y tradicional y, si bien es común, no siempre es el caso. Solo recientemente, los navegadores se volvieron lo suficientemente potentes como para mostrar páginas con un rendimiento satisfactorio. 2) Puede hacer que sus usuarios soliciten (o tener enlaces como) ejemplo.com/app.html pero no es muy convencional. La configuración sugerida responde con /public/app.html a casi todas las rutas solicitadas (digamos ejemplo.com/catalog/product/33) y te deja implementar toda la lógica de la aplicación en el cliente. - esp

2. 3) Puede representar páginas en el lado del servidor y hacer que también se puedan almacenar en caché, aunque administrarlo es un dolor de cabeza adicional, por lo que es mejor evitarlo. Los inconvenientes de representar páginas en el servidor son a) utiliza muchos más recursos del servidor que enviar solo datos, b) no puede evitar al menos cierta duplicación del esfuerzo de desarrollo. La única razón para mostrar páginas en el lado del servidor es hacer que su sitio sea rastreable. Tiene sentido entregar contenido estático solo a robots sin cabeza (así que voy a buscar si puedo configurar nginx para responder de manera diferente a diferentes agentes de usuario :)... - esp

Impresionante, estás haciendo un gran trabajo aquí. Gracias por compartir todos los detalles. Definitivamente investigaré la columna vertebral, gracias por su gran experiencia. Realmente emocionado ahora. Muy buen punto en su segunda respuesta y es bueno saber sobre el ejemplo de enrutamiento dado. Hacerlo de esta manera tiene mucho sentido ahora. Estoy totalmente de acuerdo con el problema rastreable... ¡felicitaciones! - josefrizz

No es el enfoque más común, pero sigue siendo bastante común hoy en día. Hay muchos marcos web (AngularJS por google, knockear, bigote, etc) que funcionan bien con esta idea de plantillas en el lado del cliente.

El modelo se solicita al servidor (es decir, json) y se asigna a una vista estática (plantilla).

Creo que encaja muy bien cuando tienes un servidor API que proporciona datos JSON. De esta forma puedes desarrollar un cliente API más, en este caso un cliente web (RIA). Pero no creo que la razón principal detrás de este enfoque sea ahorrar CPU.

Respondido el 31 de diciembre de 12 a las 16:12

¡Gracias! Espero que angularjs proporcione una forma de ayudar a solicitar datos JSON en las cargas de página iniciales. Lo que realmente me desconcierta/preocupa es llamar a una página html estática, como se ha hecho hace 10 años. Pero lo tomo como una forma aceptada porque no puedo pensar en ninguna otra forma eficiente para un mejor almacenamiento en caché. Llamar a una determinada ruta en la aplicación web siempre implica hablar con el servidor del nodo (algo que solo quiero hacer cuando hablo con la base de datos). Si me equivoco o si tiene alguna idea adicional, hágamelo saber... PD: ¿Hay alguna manera de mirar detrás de los nombres de dominio de nivel superior de los grandes jugadores? - josefrizz

Según el marco. No es obligatorio obtener las plantillas del lado del servidor (puede definirlas como un 'div' en su página, por ejemplo), y se pueden almacenar en caché localmente en cualquier caso. Si está buscando ejemplos de sitios que los utilizan, eche un vistazo a construido con.angularjs.org (angular). Puede encontrar más sitios usando knockout/backbone ya que han estado más tiempo en el mercado. - Guido

Gracias. Echaré un vistazo a buildwith.angular.org con seguridad. Definitivamente agradable saber cómo todas estas páginas utilizan el enfoque del lado del cliente (más allá de index.html en su carga inicial) y cómo se han inspirado en los grandes jugadores. - josefrizz

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.