Nginx como proxy inverso sin almacenamiento en caché

Nginx como proxy inverso sin almacenamiento en caché

Estoy intentando configurar Nginx como proxy inverso de almacenamiento en caché. El servidor de origen es Apache y aloja una instancia de WordPress, si eso importa.

La funcionalidad de proxy inverso funciona como se esperaba, pero el caché no parece funcionar. Si obtengo el mismo recurso estático dos veces seguidas, obtengo x-proxy-cache: MISSdos veces.

assodigitale.it es el dominio, 138.201.87.123 la dirección IP del servidor de origen y 138.201.87.124 la dirección IP del proxy Nginx.

El servidor de origen parece responder permitiendo que el proxy almacene en caché el recurso:

$ curl --connect-to ::138.201.87.123:443 --http2 -I https://assodigitale.it/wp-content/uploads/2018/03/aereo.jpg
HTTP/2 200 
date: Sun, 11 Mar 2018 20:59:39 GMT
server: Apache/2.4.25 (Debian)
content-length: 32989
strict-transport-security: max-age=31536000; includeSubdomains; preload
last-modified: Wed, 07 Mar 2018 09:34:41 GMT
etag: "80dd-566cf44ca2952"
accept-ranges: bytes
vary: Accept-Encoding
cache-control: max-age=1209600, public
x-content-type-options: nosniff
content-type: image/jpeg

La primera solicitud al servidor proxy da como resultado un MISS, como se esperaba:

$ curl --connect-to ::138.201.87.124:443 --http2 -I https://assodigitale.it/wp-content/uploads/2018/03/aereo.jpg
HTTP/2 200 
server: nginx/1.13.9
date: Sun, 11 Mar 2018 21:04:00 GMT
content-type: image/jpeg
content-length: 32989
strict-transport-security: max-age=31536000; includeSubdomains; preload
last-modified: Wed, 07 Mar 2018 09:34:41 GMT
etag: "80dd-566cf44ca2952"
vary: Accept-Encoding
cache-control: max-age=1209600, public
x-content-type-options: nosniff
x-proxy-cache: MISS
strict-transport-security: max-age=4838400; includeSubDomains; preload
accept-ranges: bytes

La segunda solicitud al proxy Nginx debería resultar en un HIT, pero resulta en otro MISS:

$ curl --connect-to ::138.201.87.124:443 --http2 -I https://assodigitale.it/wp-content/uploads/2018/03/aereo.jpg
HTTP/2 200 
server: nginx/1.13.9
date: Sun, 11 Mar 2018 21:05:52 GMT
content-type: image/jpeg
content-length: 32989
strict-transport-security: max-age=31536000; includeSubdomains; preload
last-modified: Wed, 07 Mar 2018 09:34:41 GMT
etag: "80dd-566cf44ca2952"
vary: Accept-Encoding
cache-control: max-age=1209600, public
x-content-type-options: nosniff
x-proxy-cache: MISS
strict-transport-security: max-age=4838400; includeSubDomains; preload
accept-ranges: bytes

Aquí está la parte relevante de mi configuración de nginx:

proxy_cache_path /srv/cache/nginx levels=1:2 keys_zone=revproxy:2000m inactive=2880m use_temp_path=off;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_methods GET HEAD;
proxy_cache_valid any 1m;
proxy_cache_valid 200 1440m;

server {
    listen 443 ssl http2;
    ssl on;
    server_name assodigitale.it;

    ssl_certificate /etc/letsencrypt/live/assodigitale.it/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/assodigitale.it/privkey.pem;

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;

    location / {
        proxy_cache revproxy;
        add_header X-Proxy-Cache $upstream_cache_status;
        add_header Strict-Transport-Security "max-age=4838400; includeSubDomains; preload";

        proxy_pass  https://138.201.87.123;
        proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
        proxy_cache_bypass $http_x_forceflushcacheurl;
        proxy_cache_lock on;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_hide_header Upgrade;
        proxy_buffering off;
        proxy_connect_timeout       600;
        proxy_send_timeout          600;
        proxy_read_timeout          600;
        send_timeout                600;
        proxy_ignore_headers Set-Cookie;

        http2_push_preload on;
        client_max_body_size 64M;
    }
}

El /srv/cache/nginxdirectorio tiene 755 permisos y www-datapropietario, y Nginx se ejecuta como www-data. De hecho, Nginx escribe sus carpetas allí, es decir 0 1 2 3 4 5 6 7 8 9 a b c d e f, pero el espacio total ocupado ahora es de 344 Kb, para un sitio que es bastante grande y que tiene mucho más que tráfico ocasional.

Probar los mismos curlcomandos anteriores, pero con páginas en lugar de imágenes, produce el mismo resultado, siempre es un FALLO.

¿Por qué Nginx se niega a almacenar recursos en caché?

Respuesta1

debe configurar proxy_buffering on; de lo contrario, nginx no almacenará en caché la respuesta.

el oficialdocumentodicho:

Cuando el almacenamiento en búfer está deshabilitado, la respuesta se pasa a un cliente de forma sincrónica, inmediatamente después de recibirla. nginx will not try to read the whole response from the proxied server.El tamaño máximo de los datos que nginx puede recibir del servidor a la vez lo establece la directiva proxy_buffer_size.

Respuesta2

Copié la configuración de otro proxy Nginx similar que ejecuto, la adapté al sitio web y ahora funciona.

Esta es la configuración que estoy usando actualmente:

proxy_cache_path /srv/cache/nginx levels=1:2 keys_zone=revproxy:2000m inactive=2880m use_temp_path=off;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_methods GET HEAD;
proxy_cache_valid any 1m;
proxy_cache_valid 200 1440m;    
server {
    listen 443 ssl http2;
    ssl on;
    server_name assodigitale.it;

    ssl_certificate /etc/letsencrypt/live/assodigitale.it/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/assodigitale.it/privkey.pem;

        ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;    
        ssl_ciphers RC4:HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        keepalive_timeout    60;
        ssl_session_timeout  10m;

    location / {
            proxy_cache revproxy;
            add_header X-Proxy-Cache $upstream_cache_status;

            proxy_pass  https://138.201.87.123;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
            proxy_cache_lock on;
            proxy_set_header        Host            $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_hide_header      Upgrade;
            proxy_buffering on;
            proxy_connect_timeout       600;
            proxy_send_timeout          600;
            proxy_read_timeout          600;
            send_timeout                600;
            client_max_body_size 64M;
    }
}

Si bien esto puede ser una respuesta porque resuelve el problema, no entiendo por qué funciona (o, más precisamente, por qué la configuración anterior no lo hizo), así que no voy a aceptar mi propia respuesta.

Tal vez alguien pueda detectar la diferencia particular en las dos configuraciones que hace que el caché funcione: esa sería una respuesta aceptable.

Respuesta3

Tuvimos un problema similar. Estábamos usando nginx como caché de proxy para un depósito s3 (para poder admitir la lista blanca de IP). Nos dimos cuenta de que no estábamos obteniendo datos de un punto final https a pesar de que nuestro proxy funcionaba en https. Parece que a nginx no le gustó eso. Una vez que cambiamos de httpa https, no hubo problemas.

información relacionada