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: MISS
dos 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/nginx
directorio tiene 755 permisos y www-data
propietario, 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 curl
comandos 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 http
a https
, no hubo problemas.