2010-01-12 8 views
12

Also meine Seite Ich bin bewegt von Apache weg und auf Nginx, und ich habe Probleme mit diesem Szenario:Nginx Proxy-Dateien auf lokalen Festplatte oder S3

Börse ein Foto. Dieses Foto wird in der Größe geändert und dann in S3 kopiert. Wenn auf der Festplatte ein geeigneter Speicherplatz vorhanden ist (oder die Datei nicht in S3 übertragen werden kann), wird eine lokale Version beibehalten.

Ich möchte Anforderungen für diese Bilder (z. B. http://www.mysite.com/p/1_1.jpg) zunächst im Verzeichnis p/suchen. Wenn keine lokale Datei vorhanden ist, möchte ich die Anfrage an S3 weiterleiten und das Bild rendern (aber nicht umleiten).

In Apache, ich tat dies in etwa so:

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

Mein Versuch, dieses Verhalten in Nginx zu replizieren, ist dies:

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

Was passiert, ist, dass jede Anfrage Amazon S3 zu schlagen versucht, Selbst wenn die Datei auf der Festplatte existiert (und wenn sie nicht auf Amazon existiert, erhalte ich Fehler.) Wenn ich die proxy_pass-Zeile entferne, funktionieren die Anforderungen für Dateien auf der Festplatte.

Irgendwelche Ideen, wie Sie das beheben können?

+0

Können Sie virual.conf-Datei teilen. – Thoman

Antwort

33

Sollte dies nicht ein Beispiel sein try_files der Verwendung?

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

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

Sicherstellen, dass kein folgenden slash auf der S3-URL ist

+0

Große Antwort! Klare und einfache Lösung. Vielen Dank! –

0

break nicht ganz das tut, was Sie nginx erwarten, dass das letzte, was Sie davon fragen tun, was Sinn macht, wenn Sie rund um Module graben machen ... aber im Grunde Ihre proxy_pass mit dem schützen does-not-exist Version

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

Ich habe das anfangs versucht, aber Nginx wird nicht starten, wenn ich das volle 'http: // my_bucket.s3.amazonaws.com /' im Aufruf 'proxy_pass' habe. Ich bekomme folgende Fehlermeldung: 'Neustart nginx: 2010/01/11 20:53:36 [emerg] 1485 # 0:" proxy_pass "darf keinen URI-Teil in der Position haben, die durch regulären Ausdruck angegeben wird, oder innerhalb des benannten Ortes oder innerhalb der "if" -Anweisung oder innerhalb des "limit_except" -Blocks in /etc/nginx/sites-enabled/my_site.com: 39' Wenn ich den abschließenden Schrägstrich entferne, startet Nginx, aber meine Anfragen werden nicht weitergeleitet richtig mehr. Irgendwelche Ideen? – Coomer

0

landete ich diese Lösung durch zu prüfen, ob sich die Datei nicht existiert, und wenn ja, diese Anforderung neu zu schreiben. Ich kümmere mich um dann die erneute schriftliche Anfrage und tun das proxy_pass es, etwa so:

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

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

Das 'if' in nginx hat ein sehr unberechenbares Verhalten. Obwohl dies gut funktioniert, wird empfohlen, 'try_files' zu verwenden, wann immer es möglich ist, wie in Dan Gayles Antwort. Überprüfen Sie http://wiki.ninx.org/IfIsEvil für die Feinheiten von "if". –

12

Sie Ihre s3 Proxy-Konfiguration wie diese verbessern könnte. Angepasst von 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

Dank meiner coderwall Post zu halten :) Für den Caching Zweck Sie es ein bisschen verbessern können:

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; 
    } 
    } 

} 

Eine weitere Empfehlung ist Resolver-Cache bis zu 5 min zu verlängern:

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

Sie benötigen keinen nachgestellten Schrägstrich in der Anweisung ** proxy_pass **, das ist ziemlich wichtig. Es sollte so aussehen: 'proxy_pass http: // $ s3_bucket $ url_full;' –

Verwandte Themen