Nginx Proxy для файлов на локальном диске или S3 - PullRequest
12 голосов
/ 12 января 2010

Итак, я перемещаю свой сайт из Apache в Nginx, и у меня возникают проблемы с этим сценарием:

Пользователь загружает фотографию. Размер этой фотографии изменяется, а затем копируется в S3. Если на диске имеется подходящее место (или файл не может быть перенесен на S3), локальная версия сохраняется.

Я хочу, чтобы запросы на эти изображения (например, http://www.mysite.com/p/1_1.jpg)) сначала просматривались в каталоге p /. Если локальный файл не существует, я хочу передать запрос на S3 и обработать изображение (но не перенаправить ).

В Apache я сделал это так:

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

Моя попытка воспроизвести это поведение в Nginx такова:

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

Что происходит, так это то, что каждый запрос пытается попасть в Amazon S3, даже если файл существует на диске (и если он не существует в Amazon, я получаю ошибки.) Если я удаляю строку proxy_pass, то запросы на файлы диск работает.

Есть идеи, как это исправить?

Ответы [ 5 ]

33 голосов
/ 20 июня 2012

Разве это не пример использования try_files?

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

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

Убедитесь, что на URL S3 нет следующей косой черты

12 голосов
/ 09 октября 2013

Вы можете улучшить конфигурацию прокси-сервера s3 следующим образом. Адаптировано с 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;
}
3 голосов
/ 27 февраля 2014

Спасибо за сохранение моего поста Coderwall :) Для целей кэширования вы можете немного его улучшить:

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

}

Еще одна рекомендация - продлить кэш распознавателя до 5 минут:

resolver                  8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout          10s;
0 голосов
/ 14 января 2010

В итоге я решил эту проблему, проверив, существует ли файл, и, если да, переписал этот запрос. Затем я обрабатываю переписанный запрос и выполняю там proxy_pass, например:

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

location /ps3/ {
  proxy_pass http://my_bucket.s3.amazonaws.com/;
}
0 голосов
/ 12 января 2010

break делает не совсем то, что вы ожидаете, nginx сделает последнее, о чем вы просите, что имеет смысл, если вы начнете копаться в создании модулей ... но в основном защитите свой proxy_pass с помощью . не существует версия

if (-f $request_filename) {
    break;
}
if(!-f $request_filename)
    proxy_pass  http://s3;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...