Editor : La publicación del blog titulada “Introducción al módulo JavaScript de NGINX” redirige aquí. La publicación se ha actualizado con las directivas y características del módulo JavaScript de NGINX compatibles a partir de abril de 2021.
El módulo JavaScript de NGINX (njs) se lanzó al público general como módulo estable en NGINX Open Source 1.11.10 y NGINX Plus R12 . [El módulo se llamaba originalmente nginScript, nombre que aparece en algunas publicaciones anteriores]. Hemos trabajado incansablemente en JavaScript de NGINX desde su lanzamiento en septiembre de 2015 , incorporando las funciones y la compatibilidad con idiomas incluidas en el módulo estable.
NGINX JavaScript es una implementación de JavaScript única para NGINX y NGINX Plus, diseñada específicamente para casos de uso del lado del servidor y procesamiento por solicitud. Amplía la sintaxis de configuración de NGINX con código JavaScript para implementar soluciones de configuración sofisticadas.
Los casos de uso son amplios, especialmente porque el módulo JavaScript de NGINX está disponible para los protocolos HTTP y TCP/UDP. Algunos ejemplos de casos de uso para NGINX JavaScript incluyen:
Antes de analizar NGINX JavaScript con más detalle, abordemos primero dos conceptos erróneos comunes.
La comunidad NGINX ha creado varias extensiones programáticas a lo largo de los años. Al momento de escribir este artículo, Lua es el más popular de ellos; está disponible como módulo para NGINX y como módulo dinámico de terceros prediseñado y compatible para NGINX Plus. El módulo Lua y las bibliotecas complementarias proporcionan una integración profunda con el núcleo NGINX y un amplio conjunto de funcionalidades, incluido un controlador para Redis.
Lua es un potente lenguaje de programación. Sin embargo, sigue siendo bastante específico en términos de adopción y no suele encontrarse en la “caja de herramientas de habilidades” del desarrollador frontend o del ingeniero DevOps.
NGINX JavaScript no busca reemplazar a Lua y pasará algún tiempo antes de que NGINX JavaScript tenga un nivel comparable de funcionalidad. El objetivo de NGINX JavaScript es proporcionar soluciones de configuración programática a la comunidad más amplia posible mediante el uso de un lenguaje de programación popular.
NGINX JavaScript no tiene como objetivo convertir NGINX o NGINX Plus en un servidor de aplicação . En términos simples, los casos de uso de NGINX JavaScript son similares al middleware, ya que la ejecución del código JavaScript ocurre entre el cliente y el contenido. Técnicamente hablando, si bien Node.js comparte dos cosas con la combinación de NGINX JavaScript y NGINX o NGINX Plus (una arquitectura basada en eventos y el lenguaje de programación JavaScript), las similitudes terminan ahí.
Node.js utiliza el motor JavaScript V8 de Google, mientras que JavaScript de NGINX es una implementación a medida de los estándares ECMAScript, diseñado específicamente para NGINX y NGINX Plus. Node.js tiene una máquina virtual (VM) JavaScript persistente en la memoria y realiza una recolección de basura rutinaria para la administración de la memoria, mientras que NGINX JavaScript inicializa una nueva VM JavaScript y la memoria necesaria para cada solicitud y libera la memoria cuando se completa la solicitud.
Como se mencionó anteriormente, NGINX JavaScript es una implementación a medida del lenguaje JavaScript. Todos los demás motores de ejecución de JavaScript existentes están diseñados para ejecutarse dentro de un navegador web. La naturaleza de la ejecución del código del lado del cliente es diferente a la ejecución del código del lado del servidor en muchos aspectos: desde la disponibilidad de recursos del sistema hasta la cantidad posible de tiempos de ejecución simultáneos.
Decidimos implementar nuestro propio entorno de ejecución de JavaScript para cumplir con los requisitos de ejecución de código del lado del servidor y adaptarse elegantemente a la arquitectura de procesamiento de solicitudes de NGINX. Nuestros principios de diseño para NGINX JavaScript son los siguientes:
El entorno de ejecución vive y muere con la solicitud.
El módulo JavaScript de NGINX utiliza ejecución de código de bytes de un solo subproceso, diseñado para una inicialización y eliminación rápidas. El entorno de ejecución se inicializa por cada solicitud. El inicio es extremadamente rápido porque no hay estados complejos ni ayudantes que inicializar. La memoria se acumula en grupos durante la ejecución y se libera al finalizar la ejecución liberando los grupos. Este esquema de gestión de memoria elimina la necesidad de rastrear y liberar objetos individuales o de utilizar un recolector de basura.
Ejecución de código sin bloqueo
El modelo impulsado por eventos de NGINX y NGINX Plus programa la ejecución de entornos de ejecución de JavaScript de NGINX individuales. Cuando una regla de JavaScript de NGINX realiza una operación de bloqueo (como leer datos de red o emitir una subsolicitud externa), NGINX y NGINX Plus suspenden de forma transparente la ejecución de la VM de JavaScript de NGINX asociada y la reprograman cuando se completa el evento. Esto significa que puede escribir reglas de manera simple y lineal y NGINX y NGINX Plus programarlas sin bloqueo interno.
Implementar únicamente el soporte de idiomas que necesitamos
Las especificaciones de JavaScript están definidas por los estándares ECMAScript . NGINX JavaScript sigue ECMAScript 5.1 con algo de ECMAScript 6 para funciones matemáticas. Implementar nuestro propio entorno de ejecución de JavaScript nos da la libertad de priorizar el soporte del lenguaje para casos de uso del lado del servidor e ignorar lo que no necesitamos. Mantenemos una lista de los elementos del lenguaje admitidos actualmente .
Integración estrecha con las fases de procesamiento de solicitudes
NGINX y NGINX Plus procesan las solicitudes en fases distintas. Las directivas de configuración normalmente operan en una fase específica y los módulos nativos de NGINX a menudo aprovechan la capacidad de inspeccionar o modificar una solicitud en una fase particular. NGINX JavaScript expone algunas de las fases de procesamiento a través de directivas de configuración para dar control sobre cuándo se ejecuta el código JavaScript. Esta integración con la sintaxis de configuración promete la potencia y la flexibilidad de los módulos nativos de NGINX con la simplicidad del código JavaScript.
La siguiente tabla indica qué fases de procesamiento son accesibles a través de JavaScript de NGINX en el momento de escribir este artículo y las directivas de configuración que lo proporcionan.
Fase de procesamiento | Módulo HTTP | Módulo de transmisión |
---|---|---|
Acceso – Autenticación y control de acceso |
auth_request y js_content |
acceso js |
Prelectura: carga útil de lectura y escritura |
N/A | js_preread |
Filtro : respuesta de lectura/escritura durante el proxy |
filtro js_body filtro de encabezado js |
filtro js |
Contenido – Enviar respuesta al cliente |
contenido js |
N/A |
Registro/Variables – Evaluadas a demanda |
conjunto js |
conjunto js |
NGINX JavaScript se implementa como un módulo que puede compilarse en un binario de código abierto NGINX o cargarse dinámicamente en NGINX o NGINX Plus. Las instrucciones para habilitar JavaScript NGINX con NGINX y NGINX Plus aparecen al final de este artículo.
En este ejemplo, utilizamos NGINX o NGINX Plus como un proxy inverso simple y usamos NGINX JavaScript para construir entradas de registro de acceso en un formato especializado, que:
La configuración de NGINX para este ejemplo es extremadamente simple.
Como puede ver, el código JavaScript de NGINX no se alinea con la sintaxis de configuración. En su lugar, utilizamos la directiva js_import
para especificar el archivo que contiene todo nuestro código JavaScript. La directiva js_set
define una nueva variable NGINX, $access_log_headers
, y la función JavaScript que la completa. La directiva log_format
define un nuevo formato llamado kvpairs que escribe cada línea de registro con el valor de $access_log_headers
.
El bloque de servidor
define un proxy inverso HTTP simple que reenvía todas las solicitudes a https://www.example.com . La directiva access_log
especifica que todas las solicitudes se registrarán con el formato kvpairs .
Veamos ahora el código JavaScript que prepara una entrada de registro.
El valor de retorno de la función kvAccess
(una entrada de registro) se pasa a la directiva de configuración js_set
en rawheader_logging.conf . Tenga en cuenta que las variables NGINX se evalúan a pedido y esto, a su vez, significa que la función JavaScript definida por js_set
se ejecuta cuando se requiere el valor de la variable. En este ejemplo, $access_log_headers
se utiliza en la directiva log_format
y, por lo tanto, kvAccess()
se ejecuta en el momento del registro. Las variables utilizadas como parte de las directivas de mapa
o reescritura
(no ilustradas en este ejemplo) activan la ejecución de JavaScript correspondiente en una fase de procesamiento anterior.
Podemos ver esta solución de registro NGINX mejorada con JavaScript en acción al pasar una solicitud a través de nuestro proxy inverso y observar la entrada del archivo de registro resultante, que incluye encabezados de solicitud con el prefijo in.
y encabezados de respuesta con el prefijo out.
$ curl http://127.0.0.1/ $ tail --lines=1 /var/log/nginx/access_headers.log 2021-04-23T10:08:15+00:00 cliente=172.17.0.1 método=GET uri=/index.html estado=200 entrada.Host=localhost:55081 entrada.User-Agent=curl/7.64.1 entrada.Accept=*/* salida.Content-Type=text/html salida.Content-Length=612 salida.ETag=\x22606339ef-264\x22 salida.Accept-Ranges=bytes
Gran parte de la utilidad de JavaScript de NGINX es resultado de su acceso a las partes internas de NGINX. Este ejemplo utiliza varias propiedades del objeto de solicitud ( r
) . El módulo JavaScript Stream de NGINX (para aplicações TCP y UDP) utiliza uno o más
objetos de sesión con su propio conjunto de propiedades. Para conocer otros ejemplos de soluciones JavaScript de NGINX para HTTP y TCP/UDP, consulte Casos de uso del módulo JavaScript de NGINX .
Nos encantaría conocer los casos de uso que se le ocurran para NGINX JavaScript. Cuéntenos sobre ellos en la sección de comentarios a continuación.
Consulte estas publicaciones de blog para explorar otros casos de uso de HTTP y TCP/UDP para el módulo JavaScript de NGINX:
auth_request
con el módulo JavaScript de NGINX en “Validación de tokens de acceso de OAuth 2.0 con NGINX y NGINX Plus”
[ngx_snippet name=’njs-enable-instructions’]
"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.