2010-01-12 13 views
12

Así que me estoy moviendo mi sitio alejado de Apache y en Nginx, y estoy teniendo problemas con este escenario:Nginx proxy de archivos en el disco local o S3

usuario sube una foto. Esta foto se redimensiona y luego se copia a S3. Si hay espacio adecuado en el disco (o el archivo no se puede transferir a S3), se guarda una versión local.

Quiero solicitudes para que estas imágenes (como http://www.mysite.com/p/1_1.jpg) se vean por primera vez en el directorio p /. Si no existe ningún archivo local, quiero enviar la solicitud por proxy a S3 y renderizar la imagen (pero no redirigir).

En Apache, lo hice de esta manera:

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^p/([0-9]+_[0-9]+\.jpg)$ http://my_bucket.s3.amazonaws.com/$1 [P,L] 

Mi intento de replicar este comportamiento en Nginx es la siguiente:

location /p/ { 
    if (-e $request_filename) { 
     break; 
    } 
    proxy_pass http://my_bucket.s3.amazonaws.com/; 
} 

Lo que pasa es que cada solicitud intenta golpear a Amazon S3, incluso si el archivo existe en el disco (y si no existe en Amazon, obtengo errores). Si elimino la línea proxy_pass, entonces las solicitudes de archivos en el disco SI funcionan.

¿Alguna idea sobre cómo solucionar esto?

+0

Puede compartir el archivo virual.conf. – Thoman

Respuesta

33

¿No debería ser esto un ejemplo del uso try_files?

location /p/ { 
    try_files $uri @s3; 
} 

location @s3{ 
    proxy_pass http://my_bucket.s3.amazonaws.com; 
} 

Asegúrese de que no hay una barra en la siguiente url S3

+0

¡Gran respuesta! Solución clara y simple. ¡Gracias! –

0

break no está haciendo lo que espera que nginx haga lo último que le pida, lo cual tiene sentido si comienza a buscar módulos ... pero básicamente protege su proxy_pass con el does-not-exist versión

if (-f $request_filename) { 
    break; 
} 
if(!-f $request_filename) 
    proxy_pass http://s3; 
} 
+3

Lo intenté inicialmente, pero Nginx no se iniciará si tengo el 'http: // my_bucket.s3.amazonaws.com /' completo en la llamada 'proxy_pass'. Me sale el siguiente error: 'Reiniciar nginx: 2010/01/11 20:53:36 [emerg] 1485 # 0:" proxy_pass "puede no tener URI parte en la ubicación dada por la expresión regular, o dentro de la ubicación con nombre, o dentro de la instrucción "if", o dentro del bloque "limit_except" en /etc/nginx/sites-enabled/my_site.com: 39' Si elimino la barra inclinada, Nginx se iniciará, pero mis solicitudes no se enrutan correctamente más. ¿Algunas ideas? – Coomer

0

terminé resolver esto mediante la comprobación para ver si no existe el archivo, y si es así, volver a escribir esa solicitud. entonces manejar la petición re-escrito y hacer el PROXY_PASS allí, así:

location /p/ { 
    if (!-f $request_filename) { 
    rewrite ^/p/(.*)$ /ps3/$1 last; 
    break; 
    } 
} 

location /ps3/ { 
    proxy_pass http://my_bucket.s3.amazonaws.com/; 
} 
+2

El 'if' en nginx tiene un comportamiento muy impredecible. Aunque esto funciona bien, se recomienda usar 'try_files' siempre que sea posible, como en la respuesta de Dan Gayle. Visite http://wiki.nginx.org/IfIsEvil para conocer las sutilezas de 'if'. –

12

Se podría mejorar su configuración de proxy s3 como este. Adaptado de https://stackoverflow.com/a/44749584:

location /p/ { 
    try_files $uri @s3; 
} 

location @s3 { 
    set $s3_bucket  'your_bucket.s3.amazonaws.com'; 
    set $url_full   '$1'; 

    proxy_http_version  1.1; 
    proxy_set_header  Host $s3_bucket; 
    proxy_set_header  Authorization ''; 
    proxy_hide_header  x-amz-id-2; 
    proxy_hide_header  x-amz-request-id; 
    proxy_hide_header  x-amz-meta-server-side-encryption; 
    proxy_hide_header  x-amz-server-side-encryption; 
    proxy_hide_header  Set-Cookie; 
    proxy_ignore_headers Set-Cookie; 
    proxy_intercept_errors on; 

    resolver    8.8.4.4 8.8.8.8 valid=300s; 
    resolver_timeout  10s; 
    proxy_pass    http://$s3_bucket$url_full; 
} 
2

Gracias a mantener mi puesto coderwall :) Para los fines de almacenamiento en caché se puede mejorar un poco:

http { 

    proxy_cache_path   /tmp/cache levels=1:2 keys_zone=S3_CACHE:10m inactive=24h max_size=500m; 
    proxy_temp_path   /tmp/cache/temp; 

    server { 
    location ~* ^/cache/(.*) { 
     proxy_buffering  on; 
     proxy_hide_header  Set-Cookie; 
     proxy_ignore_headers Set-Cookie; 
     ... 
     proxy_cache   S3_CACHE; 
     proxy_cache_valid  24h; 
     proxy_pass    http://$s3_bucket/$url_full; 
    } 
    } 

} 

Uno más recomendación es extender caché de resolución de hasta 5 min:

resolver     8.8.4.4 8.8.8.8 valid=300s; 
resolver_timeout   10s; 
+1

No necesita una barra diagonal en la directiva ** proxy_pass **, es bastante importante. Debería verse así: 'proxy_pass http: // $ s3_bucket $ url_full;' –

Cuestiones relacionadas