Cómo maximizar el rendimiento de Python con NGINX, parte 1: servicio web y almacenamiento en caché

NGINX | 31 de marzo de 2016

Introducción: cómo se utiliza NGINX con Python

Python es famoso por ser fácil y divertido de usar, por facilitar el desarrollo de software y por ofrecer un rendimiento en tiempo de ejecución que, según se dice, supera al de otros lenguajes de scripting. (Aunque la última versión de PHP, PHP 7, podría competir de tú a tú con Python).

Todo el mundo quiere que su sitio web y su aplicación funcionen más rápido. Además, cualquier sitio web cuyo tráfico esté creciendo o experimente picos repentinos es vulnerable a problemas de rendimiento y periodos de inactividad, que suelen producirse en los peores momentos, es decir, cuando hay más actividad. Asimismo, casi todos los sitios web sufren problemas de rendimiento y periodos de inactividad, tanto si el volumen de tráfico crece de forma constante como si experimentan picos repentinos de uso.

Ahí es donde entran en juego NGINX y NGINX Plus. Mejoran el rendimiento de los sitios web de tres formas distintas:

  1. Como servidor web – NGINX se desarrolló originalmente para resolver el problema de las 10 000 conexiones simultáneas (C10K) – es decir, para admitir fácilmente 10 000 conexiones simultáneas o más. Usar NGINX como servidor web para su aplicación Python hace que su sitio web sea más rápido, incluso con niveles de tráfico bajos. Cuando tiene muchos miles de usuarios, es prácticamente seguro que ofrecerá un rendimiento mucho mayor, menos fallos y menos tiempo de inactividad. También puede almacenar en caché archivos estáticos o usar microcaché en su servidor web NGINX, aunque ambas opciones funcionan mejor cuando se ejecutan en un servidor proxy inverso NGINX independiente (consulte el párrafo siguiente).
  2. Como servidor proxy inverso – Puede «incorporar NGINX» como servidor proxy inverso delante de la configuración actual de su servidor de aplicaciones. NGINX se conecta a Internet y reenvía las solicitudes a su servidor de aplicaciones. Este «sencillo truco» hace que su sitio web funcione más rápido, reduce el tiempo de inactividad, consume menos recursos del servidor y mejora la seguridad. También puede almacenar en caché archivos estáticos en el servidor proxy inverso (lo cual resulta muy eficiente), añadir microalmacenamiento en caché de contenido dinámico para reducir la carga de la propia aplicación y mucho más.
  3. Como equilibrador de carga para varios servidores de aplicaciones – Empiece por implementar un servidor proxy inverso. A continuación, amplíe la capacidad ejecutando varios servidores de aplicaciones en paralelo y utilizando NGINX o NGINX Plus para equilibrar la carga del tráfico entre ellos. Con este tipo de implementación, puede adaptar fácilmente el rendimiento de su sitio web a las necesidades de tráfico, aumentando la fiabilidad y el tiempo de actividad. Si necesita que una sesión de usuario determinada permanezca en el mismo servidor, configure el equilibrador de carga para que admita la persistencia de sesión.

NGINX y NGINX Plus ofrecen ventajas tanto si los utiliza como servidor web para su aplicación Python, como servidor proxy inverso, como equilibrador de carga o para las tres funciones.

En este primer artículo de una serie de dos partes, presentamos cinco consejos para mejorar el rendimiento de tus aplicaciones Python, entre ellos, cómo usar NGINX y NGINX Plus como servidor web, cómo implementar el almacenamiento en caché de archivos estáticos y cómo usar la microcaché para los archivos generados por las aplicaciones. En la segunda parte, explicaremos cómo usar NGINX y NGINX Plus como servidor proxy inverso y como equilibrador de carga para varios servidores de aplicaciones.

Consejo 1 – Identifica los cuellos de botella de rendimiento de Python

Hay dos situaciones muy distintas en las que el rendimiento de una aplicación Python es importante: en primer lugar, con un número habitual y «razonable» de usuarios; y, en segundo lugar, cuando está sometida a cargas elevadas. Muchos propietarios de sitios web se preocupan demasiado poco por el rendimiento con cargas ligeras, cuando —en nuestra humilde opinión— deberían estar pendientes de cada décima de segundo del tiempo de respuesta. Reducir los tiempos de respuesta en unos pocos milisegundos es una tarea difícil y poco agradecida, pero mejora la satisfacción de los usuarios y los resultados empresariales.

Sin embargo, esta entrada del blog y la segunda parte que la acompaña se centran en el escenario que sí preocupa a todo el mundo: los problemas de rendimiento que se producen cuando un sitio web recibe mucho tráfico, como ralentizaciones importantes y caídas. Además, muchos ataques informáticos imitan los efectos de un aumento repentino del número de usuarios, y mejorar el rendimiento del sitio suele ser también un paso importante para hacer frente a los ataques.

Con un sistema que asigna una determinada cantidad de memoria por usuario, como Apache HTTP Server, la incorporación de usuarios provoca que la memoria física se sobrecargue a medida que se conectan cada vez más usuarios. El servidor empieza a utilizar el disco como memoria de intercambio, el rendimiento cae en picado y, como consecuencia, se producen problemas de rendimiento y bloqueos. Migrar a NGINX, tal como se describe en esta entrada del blog, ayuda a resolver este problema.

Python es especialmente propenso a sufrir problemas de rendimiento relacionados con la memoria, ya que, por lo general, utiliza más memoria para realizar sus tareas que otros lenguajes de scripting (y, como resultado, las ejecuta más rápido). Por tanto, en igualdad de condiciones, es posible que una aplicación basada en Python «se caiga» con una carga de usuarios menor que una aplicación escrita en otro lenguaje.

Optimizar tu aplicación puede ayudar en cierta medida, pero no suele ser la mejor forma ni la más rápida de resolver los problemas de rendimiento del sitio relacionados con el tráfico. Los pasos descritos en esta entrada del blog y en la segunda parte que la acompaña son la mejor forma y la más rápida de abordar estos problemas. Después de seguir los pasos indicados aquí, puedes volver a mejorar tu aplicación o reescribirla para que utilice una arquitectura de microservicios.

Consejo 2: elige una implementación en un único servidor o en varios servidores

Los sitios web pequeños funcionan bien cuando se implementan en un único servidor. Los sitios web grandes requieren varios servidores. Pero si se encuentra en un punto intermedio —o su sitio está pasando de ser pequeño a ser grande—, tendrá que tomar algunas decisiones interesantes.

Si tienes una implementación en un único servidor, corres un riesgo considerable si se producen picos de tráfico o un rápido crecimiento del tráfico general. Tu capacidad de escalado es limitada, y entre las posibles soluciones se incluyen mejorar tu aplicación, cambiar tu servidor web a NGINX, adquirir un servidor más grande y rápido o trasladar el almacenamiento a una red de distribución de contenidos (CDN). Cada una de estas opciones requiere tiempo para implementarse, conlleva un coste y puede introducir errores o problemas durante la implementación.

Además, con una implementación en un único servidor, tu sitio tiene, por definición, un único punto de fallo, y muchos de los problemas que pueden dejarlo fuera de servicio no tienen soluciones rápidas ni sencillas.

NGINX y Python trabajan conjuntamente para ofrecer un alto rendimiento gracias a las capacidades de NGINX para servir contenido web, equilibrar la carga y almacenar contenido en caché
«Colocar NGINX delante de» los servidores de aplicaciones

Si cambia su servidor a NGINX en una implementación con un único servidor, puede elegir libremente entre NGINX Open Source y NGINX Plus. NGINX Plus incluye soporte de nivel empresarial y funciones adicionales. Algunas de estas funciones adicionales, como la supervisión de la actividad en tiempo real, son relevantes para una implementación con un único servidor, mientras que otras, como el equilibrio de carga y la persistencia de sesión, entran en juego si utiliza NGINX Plus como servidor proxy inverso en una implementación con varios servidores.

En definitiva, a menos que tenga la certeza de que su sitio va a seguir siendo pequeño durante mucho tiempo y que el tiempo de inactividad no supone una gran preocupación, una implementación con un único servidor conlleva ciertos riesgos. Una implementación con varios servidores ofrece una escalabilidad prácticamente ilimitada: se pueden eliminar los puntos únicos de fallo y ajustar el rendimiento según sus necesidades, con la posibilidad de ampliar la capacidad rápidamente.

Consejo 3 – Cambia tu servidor web a NGINX

En los primeros tiempos de la Web, el nombre «Apache» era sinónimo de «servidor web». Sin embargo, NGINX se desarrolló a principios de la década de 2000 y su popularidad no ha dejado de crecer; ya es el servidor web número 1 en los 1.000, 10.000 y 100.000 sitios web más populares del mundo, así como en los [ngx_snippet name=’proportion-top-sites’].

NGINX se desarrolló para resolver el problema C10K – es decir, para gestionar más de 10.000 conexiones simultáneas con una cantidad de memoria determinada. Otros servidores web necesitan una porción de memoria para cada conexión, por lo que agotan la memoria física y se ralentizan o bloquean cuando miles de usuarios quieren acceder a un sitio al mismo tiempo. NGINX gestiona cada solicitud por separado y puede escalar sin problemas para atender a muchos más usuarios. (También resulta excelente para otros fines, como describiremos más adelante).

A continuación se muestra una visión general de alto nivel de la arquitectura de NGINX.

Arquitectura para orientar la configuración de Python mediante las capacidades de NGINX para servir contenido web, equilibrar la carga y almacenar en caché
Arquitectura de NGINX, extraída de La arquitectura de las aplicaciones de código abierto, volumen II

En el diagrama, un servidor de aplicaciones Python se sitúa en el bloque Servidor de aplicaciones del backend y se muestra que se accede a él mediante FastCGI. NGINX no «sabe» cómo ejecutar Python, por lo que necesita una puerta de enlace a un entorno que sí sepa hacerlo. FastCGI es una interfaz muy utilizada para PHP, Python y otros lenguajes.

Sin embargo, una opción más popular para la comunicación entre Python y NGINX es la interfaz de puerta de enlace del servidor web (WSGI). WSGI funciona en entornos multiproceso y multihilo, por lo que se adapta bien a todas las opciones de implementación mencionadas en esta entrada del blog.

Si cambia a NGINX como servidor web, encontrará abundante documentación sobre los pasos necesarios:

Este fragmento muestra cómo se puede configurar NGINX para usarlo con uWSGI ; en este caso, en un proyecto que utiliza el framework de Python Django:

http {    # ...
    upstream django {
       server 127.0.0.1:29000;
    }

    server {
        listen 80;
        server_name myapp.example.com;

        root /var/www/myapp/html;

        location / {
            index index.html;
        }

        location /static/  {
            alias /var/django/projects/myapp/static/;
        }

        location /main {
            include /etc/nginx/uwsgi_params;
            uwsgi_pass django;

            uwsgi_param Host $host;
            uwsgi_param X-Real-IP $remote_addr;
            uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
            uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto;
        }
    }
}

Consejo 4 – Implementa el almacenamiento en caché de archivos estáticos

El almacenamiento en caché de contenido estático consiste en guardar una copia de los archivos que no cambian con mucha frecuencia —ya sea cada pocas horas o nunca— en una ubicación distinta del servidor de aplicaciones. Un ejemplo típico de contenido estático es una imagen JPEG que se muestra como parte de una página web.

El almacenamiento en caché de archivos estáticos es una forma habitual de mejorar el rendimiento de las aplicaciones y, de hecho, se lleva a cabo en varios niveles:

  • En el navegador del usuario
  • En proveedores de Internet de distintos niveles, desde la red interna de una empresa hasta un proveedor de servicios de Internet (ISP)
  • En un servidor web, como describiremos aquí

Implementar el almacenamiento en caché de archivos estáticos en el servidor web ofrece dos ventajas:

  • Entrega más rápida al usuario – NGINX está optimizado para almacenar archivos estáticos en caché y procesa las solicitudes de contenido estático mucho más rápido que un servidor de aplicaciones.
  • Menor carga en el servidor de aplicaciones – El servidor de aplicaciones ni siquiera recibe las solicitudes de archivos estáticos almacenados en caché, ya que el servidor web se encarga de atenderlas.

El almacenamiento en caché de archivos estáticos funciona bien con una implementación de un único servidor, pero el servidor web y el servidor de aplicaciones siguen compartiendo el hardware subyacente. Si el servidor web mantiene ocupado el hardware recuperando un archivo de la caché —aunque lo haga de forma muy eficiente—, esos recursos de hardware no están disponibles para la aplicación, lo que puede ralentizarla en cierta medida.

Para permitir el almacenamiento en caché del navegador, configure correctamente los encabezados HTTP de los archivos estáticos. Tenga en cuenta el encabezado HTTP Cache-Control (y, en particular, su opción max-age), el encabezado Expires y las etiquetas Entity. Para obtener una buena introducción al tema, consulte Uso de NGINX y NGINX Plus como puerta de enlace de aplicaciones con uWSGI y Django en la Guía de administración de NGINX Plus.

El siguiente código configura NGINX para almacenar en caché archivos estáticos, incluidos archivos JPEG, GIF, PNG, vídeos MP4, archivos de PowerPoint y muchos otros. Sustituya www.example.com por la URL de su servidor web.

server {    # substitute your web server's URL for "www.example.com"
    server_name www.example.com;
    root /var/www/example.com/htdocs;
    index index.php;
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

   location / {
        try_files $uri $uri/ /index.php?$args;
    }

   location ~ .php$ {
        try_files $uri =404;
        include fastcgi_params;
        # substitute the socket, or address and port, of your Python server
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        #fastcgi_pass 127.0.0.1:9000;
 	}  

   location ~* .(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
                  |jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
                  |midi|wav|bmp|rtf)$ {
        expires max;
        log_not_found off;
        access_log off;
    }
}

Consejo 5 – Implementa el microalmacenamiento en caché

El microalmacenamiento en caché ofrece una gran oportunidad para mejorar el rendimiento de los servidores de aplicaciones que ejecutan Python, PHP y otros lenguajes. A efectos de almacenamiento en caché, existen tres tipos de páginas web:

  • Archivos estáticos – Se pueden almacenar en caché, como se describe en el Consejo 4.
  • Páginas no personalizadas generadas por la aplicación – Por lo general, no tiene sentido almacenarlas en caché, ya que deben estar actualizadas. Un ejemplo sería una página que se muestra a un usuario de comercio electrónico que no ha iniciado sesión (véase el punto siguiente) – los productos disponibles, las recomendaciones de productos similares, etc., pueden cambiar constantemente, por lo que es importante mostrar una página actualizada. Sin embargo, si otro usuario llega, por ejemplo, una décima de segundo después, puede ser perfectamente válido mostrarle la misma página que al usuario anterior.
  • Páginas personalizadas generadas por la aplicación – No resulta útil almacenarlas en caché, ya que son específicas de cada usuario y es poco probable que un mismo usuario vea dos veces la misma página personalizada. Un ejemplo sería una página de comercio electrónico para un usuario que ha iniciado sesión; esa misma página no puede mostrarse a otros usuarios.

Los archivos estáticos y los archivos no personalizados generados por aplicaciones se pueden almacenar en caché

El microalmacenamiento en caché resulta útil para el segundo tipo de página descrito anteriormente: páginas generadas por la aplicación y no personalizadas. «Micro» hace referencia a un periodo breve. Cuando su sitio genera la misma página varias veces por segundo, almacenarla en caché durante un segundo apenas afectará a su actualización. Sin embargo, este breve periodo de almacenamiento en caché puede reducir enormemente la carga del servidor de aplicaciones, especialmente durante los picos de tráfico. En lugar de generar 10, 20 o 100 páginas (con el mismo contenido) durante el periodo de validez de la caché, genera una página determinada una sola vez; después, la página se almacena en caché y se sirve desde ella a numerosos usuarios.

El efecto es casi milagroso. Un servidor que funciona con lentitud al gestionar decenas de solicitudes por segundo se vuelve bastante rápido cuando solo tiene que gestionar una. (Además, por supuesto, de las páginas personalizadas). Nuestro compañero Owen Garrett tiene una entrada de blog en la que explica con más detalle las ventajas del microalmacenamiento en caché, e incluye código de configuración. El cambio principal, que consiste en configurar una caché de proxy con un tiempo de espera de un segundo, solo requiere unas pocas líneas de código de configuración.

proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;server {
    proxy_cache cache;
    proxy_cache_valid 200 1s;
    # ...
}

Para ver más ejemplos de configuración, consulta el blog de Tyler Hicks‑Wright sobre Python y uWSGI con NGINX.

Conclusión

En la Parte I hemos repasado soluciones para mejorar el rendimiento de una implementación de Python en un único servidor, así como el almacenamiento en caché, que puede implementarse en un único servidor o ejecutarse en un servidor proxy inverso o en un servidor de caché independiente. (El almacenamiento en caché funciona mejor en un servidor independiente.) La siguiente parte, Parte 2, describe soluciones de rendimiento que requieren dos o más servidores.

Si desea explorar las funciones avanzadas de NGINX Plus para su aplicación, como la asistencia técnica, la supervisión de la actividad en tiempo real y la reconfiguración sobre la marcha, inicie hoy mismo su prueba gratuita de 30 días o póngase en contacto con nosotros para hablar sobre sus casos de uso.


Compartir
Etiquetas: Python, F5 NGINX, 2016, Tech

Sobre el autor

Floyd Smith
Floyd SmithDirector de marketing de contenidos

Más artículos de Floyd Smith

Artículos relacionados del blog

Únete a F5 NGINX en AppWorld 2024
NGINX | 04/01/2024

Únete a F5 NGINX en AppWorld 2024

Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
NGINX | 26/09/2023

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source

La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.

Exposición de APIs en Kubernetes
NGINX | 10/03/2022

Exposición de APIs en Kubernetes

La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
NGINX | 23/08/2021

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto

Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.

Presentamos NGINX Plus R22
NGINX | 09/06/2020

Presentamos NGINX Plus R22

NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.

Presentamos NGINX Plus R17
NGINX | 11/12/2018

Presentamos NGINX Plus R17

NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.