Proxy inverso HTTPS de NGINX: TTFB rápido pero baja concurrencia

Proxy inverso HTTPS de NGINX: TTFB rápido pero baja concurrencia

Tengo una aplicación que ejecuta: NGINX (SSL) => VARNISH (CACHE) => APACHE/PHP.

Correrpunto de referencia ab, puedo lograr más de 30.000 solicitudes por segundo en la capa de barniz (a través de HTTP) a través de una instancia EC2 t2.small. Sin embargo, cuando ejecuto la prueba a través de NGINX (HTTPS), solo puedo enviar 160 solicitudes por segundo (un promedio de 43 ms para TTFB desde la web pública).

@nginx.conf

user  nginx;
worker_processes  auto;

worker_rlimit_nofile 65535;

error_log  /var/log/nginx/error.log;

pid        /var/run/nginx.pid;


events {
    worker_connections  16024;
        multi_accept on;
}

y a nivel http:

sendfile        on;
tcp_nopush     on;

keepalive_timeout  10;


ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

@dominio.conf

server {
        listen 443 ssl;

        server_name xyz.com;
        ssl_certificate /home/st/ssl3/xyz.crt;
        ssl_certificate_key /home/xyz/ssl3/xyz.key;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

        ssl_session_tickets on;

        location / {

                proxy_buffers 8 8k;
                proxy_buffer_size 2k;


            proxy_pass http://127.0.0.1:79;
            proxy_set_header X-Real-IP  $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header X-Forwarded-Port 443;
            proxy_set_header Host $host;

                proxy_redirect off;

        }

    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
}

Aquí está el punto de referencia para Apache directamente

INTERNO => @APACHE:

Concurrency Level:      10
Time taken for tests:   0.694 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Non-2xx responses:      1002
Keep-Alive requests:    996
Total transferred:      705122 bytes
HTML transferred:       401802 bytes
Requests per second:    1440.93 [#/sec] (mean)
Time per request:       6.940 [ms] (mean)
Time per request:       0.694 [ms] (mean, across all concurrent requests)
Transfer rate: 992.22 [Kbytes/sec] received

Aquí está el punto de referencia para Varnish (antes se ejecutaba a 20-30k; usé mis ciclos de CPU, el cajero automático promedio es de 4-8k rps)

INTERNO => @VARNISH => @APACHE:

Concurrency Level:      10
Time taken for tests:   0.232 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    0
Total transferred:      23439800 bytes
HTML transferred:       23039412 bytes
Requests per second:    4310.16 [#/sec] (mean)
Time per request:       2.320 [ms] (mean)
Time per request:       0.232 [ms] (mean, across all concurrent requests)
Transfer rate:          98661.39 [Kbytes/sec] received

Aquí está el punto de referencia para NGINX a través deHTTP

INTERNO => @NGINX[HTTP] => @VARNISH => @APACHE:

Concurrency Level:      10
Time taken for tests:   0.082 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Non-2xx responses:      1001
Keep-Alive requests:    1000
Total transferred:      382382 bytes
HTML transferred:       184184 bytes
Requests per second:    12137.98 [#/sec] (mean)
Time per request:       0.824 [ms] (mean)
Time per request:       0.082 [ms] (mean, across all concurrent requests)
Transfer rate:          4532.57 [Kbytes/sec] received

Aquí está el punto de referencia para NGINX a través deHTTPS

INTERNO => @NGINX[HTTPS=>HTTP] => @VARNISH => @APACHE:

Concurrency Level:      10
Time taken for tests:   7.029 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Non-2xx responses:      1000
Keep-Alive requests:    0
Total transferred:      663000 bytes
HTML transferred:       401000 bytes
Requests per second:    142.27 [#/sec] (mean)
Time per request:       70.288 [ms] (mean)
Time per request:       7.029 [ms] (mean, across all concurrent requests)
Transfer rate:          92.12 [Kbytes/sec] received

Respuesta1

Bueno, a partir de la información que usted ha proporcionado (y no ha proporcionado), sólo puedo suponer. Pero a juzgar por el tipo de instancia (t2 tiene un rendimiento basado en tickets ampliables y, cuando no hay tickets, obtiene aproximadamente el 20 % de un núcleo; no es una buena instancia para realizar pruebas comparativas) y el uso abpara pruebas (por cierto, cuando lo escribes). como 'prueba AB', lo primero que me viene a la mente eseste) Yo diría que su desempeño es más o menos el esperado.

Al iniciar una sesión SSL o TLS, la tarea que requiere más rendimiento no es el cifrado/descifrado de datos, sino el intercambio de claves. Como abno utiliza el almacenamiento en caché de sesiones SSL, el intercambio de claves debe realizarse en cada conexión.

Dependiendo del conjunto de cifrado/kex/auth realmente utilizado (no lo sé, no abse proporciona ningún resultado), eso puede suponer bastante trabajo para la CPU. Y como ambos extremos están en la misma máquina, se duplican los requisitos de CPU por conexión (es una simplificación, pero aquí es suficiente).

En el uso en el mundo real, Keep Alives puede ayudarle a obtener un mejor rendimiento (depende del cliente, los navegadores normales lo usan; inténtelo ab -k). Y obtendrá un mejor rendimiento del almacenamiento en caché de la sesión SSL que mencionó (nuevamente depende del cliente, los navegadores normales lo admiten).

Hay varias otras formas que le ayudarán a mejorar su rendimiento. Por supuesto que puede obtener un mejor hardware. Puede optimizar el tamaño de sus claves (depende del nivel de protección requerido para la aplicación); las claves más pequeñas suelen ser más económicas. Las pruebas desde una máquina diferente pueden mejorar o no el rendimiento aparente. Y obtener una compilación de OpenSSL diferente, o una biblioteca SSL completamente diferente, también podría proporcionar un mejor rendimiento.

Sólo como referencia, puedes echar un vistazo aeste papelpor Intel. Comparan el rendimiento en una máquina altamente optimizada (y algún software optimizado). Considere que tiene menos de 1/30 de su potencia informática disponible (podría ser tan bajo como 1/150 si se le acabaron los boletos).

Sin embargo, si necesita SSL de alto rendimiento, podría valer la pena considerar usar Amazon ELB para realizar la terminación SSL por usted, ya que ya está en EC2.

Editar: por ejemploApache JMetroutiliza el almacenamiento en caché de contexto SSL.httperftambién lo hace. JMeter me parece especialmente bueno para simular cargas reales. Pero para esta forma httperf de almacenamiento en caché de sesiones podría funcionar mejor.

No ver ninguna diferencia -kpuede deberse a que todavía no se usa. Depende de la configuración de concurrencia y (al menos en mi máquina) parece depender también de la URL. No usa keepalives si uso un nombre de dominio que apunta a más de una IP en la URL (no me preguntes por qué).

Dependiendo de su percepción de lo masivo, no esperaría obtener más de 500 conexiones por segundo en ráfagas en esta instancia bastante pequeña y no más de 250 cps sostenidos.

Comparar http de texto plano de barniz con nginx ssl es comparar peras con manzanas. O más bien comparar los arándanos con las sandías en términos de requisitos de hardware.

Nuevamente para su referencia (observe la Keep-Alive requests: 100línea).

Sin-k

Concurrency Level:      1
Time taken for tests:   0.431 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      399300 bytes
HTML transferred:       381200 bytes
Requests per second:    232.26 [#/sec] (mean)
Time per request:       4.305 [ms] (mean)
Time per request:       4.305 [ms] (mean, across all concurrent requests)
Transfer rate:          905.69 [Kbytes/sec] received

Con-k

Concurrency Level:      1
Time taken for tests:   0.131 seconds
Complete requests:      100
Failed requests:        0
Keep-Alive requests:    100
Total transferred:      402892 bytes
HTML transferred:       381200 bytes
Requests per second:    762.11 [#/sec] (mean)
Time per request:       1.312 [ms] (mean)
Time per request:       1.312 [ms] (mean, across all concurrent requests)
Transfer rate:          2998.53 [Kbytes/sec] received

Edit2: Bueno, debes comprender que servir contenido directamente desde la memoria (eso es lo que está haciendo Varnish) es lo más fácil posible. Analizas los encabezados, encuentras el contenido en la memoria y lo escupes. Y Varnish sobresale en esto.

Establecer una conexión cifrada es un nivel completamente diferente. Entonces, una vez que agrega nginx, tiene que realizar el protocolo de enlace SSL (intercambio de claves, autenticación) y el cifrado, lo que requiere muchos más recursos. Luego analiza los encabezados. Luego tiene que crear otra conexión TCP con Varnish.

De nuevo, en el mencionadopapel intel, tienen 28 núcleos y realizaron algunos ajustes en su OpenSSL para obtener 38k HTTPS cps (un poco más que el rendimiento de Varnish). Tiene aproximadamente 1/5 de un núcleo y se ve afectado por sus vecinos virtuales.

CitandoLista de instancias de Amazon EC2:

Por ejemplo, una instancia t2.small recibe créditos continuamente a un ritmo de 12 créditos de CPU por hora. Esta capacidad proporciona un rendimiento básico equivalente al 20 % de un núcleo de CPU.

Y otro maspapelde los propios nginx:

Resumen de resultados Un único núcleo Intel virtualizado normalmente puede realizar hasta 350 operaciones de protocolo de enlace SSL de 2048 bits por segundo, utilizando cifrados criptográficos modernos. Esto equivale a varios cientos de nuevos usuarios de su servicio por segundo y por núcleo.

información relacionada