Подтвердить что ты не робот

Ресурсы Nginx Proxy Amazon S3

Я выполняю некоторые задачи WPO, поэтому PageSpeed ​​предложил мне использовать кеширование браузера. Я успешно улучшил его для некоторых статических файлов на моем сервере Nginx, однако мои файлы изображений, хранящиеся на сервере Amazon S3, по-прежнему отсутствуют.

Я прочитал подход, касающийся обновления каждого файла в S3, чтобы включить некоторые метатеги заголовков (Expires и Cache-Control). Я думаю, что это не очень хороший подход. У меня есть тысячи файлов, поэтому для меня это невозможно.

Я думаю, что самый удобный подход - настроить мой сервер Nginx 1.6.0 на прокси-сервер S3 файлов. Я читал об этом, но у меня нет опыта в конфигурации сервера, поэтому я получил пару примеров с этих сайтов: https://gist.github.com/benjaminbarbe/1961db5ffbaad57eff12

Я добавил этот код местоположения в свой серверный блок в файле конфигурации nginx:

#inside server block
location /mybucket.s3.amazonaws.com/ {


        proxy_http_version     1.1;
        proxy_set_header       Host mybucket.s3.amazonaws.com;
        proxy_set_header       Authorization '';
        proxy_hide_header      x-amz-id-2;
        proxy_hide_header      x-amz-request-id;
        proxy_hide_header      Set-Cookie;
        proxy_ignore_headers   "Set-Cookie";
        proxy_buffering        off;
        proxy_intercept_errors on;      
        proxy_pass             http://mybucket.s3.amazonaws.com;
      }

Конечно, это не работает для меня. В моих запросах нет заголовка. Итак, сначала я думаю, что запросы не соответствуют местоположениям.

Accept-Ranges:bytes
Content-Length:90810
Content-Type:image/jpeg
Date:Fri, 23 Jun 2017 04:53:56 GMT
ETag:"4fd0be549fbcaf9b47c18a15146cdf16"
Last-Modified:Tue, 09 Jun 2015 09:47:13 GMT
Server:AmazonS3
x-amz-id-2:cKsq1qRra74DqVsTewh3P3sgzVUoPR8aAT2NFCuwA+JjCdDZfk7/7x/C0WPjBa51GEb4C8LyAIc=
x-amz-request-id:94EADB4EDD3DE1C1
4b9b3361

Ответ 1

Ваш подход к прокси файлам S3 через Nginx имеет большой смысл. Он решает множество проблем и предоставляет дополнительные преимущества, такие как маскирование URL-адресов, прокси-кеш, ускорение передачи путем разгрузки SSL/TLS. Вы делаете это почти правильно, позвольте мне показать, что осталось, чтобы сделать его идеальным.

Для примеров запросов я использую ведро S3 и URL изображения, упомянутые в публичном комментарии, к исходному вопросу.

Начнем с проверки заголовков файлов Amazon S3

curl -I http://yanpy.dev.s3.amazonaws.com/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg

HTTP/1.1 200 OK
Date: Sun, 25 Jun 2017 17:49:10 GMT
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Accept-Ranges: bytes
Content-Type: binary/octet-stream
Content-Length: 378843
Server: AmazonS3

Мы можем видеть, что отсутствует Cache-Control, но заголовки Conditional GET уже настроены. Когда мы повторно используем E-Tag/Last-Modified (как работает кеш-клиент на стороне браузера), мы получаем HTTP 304 вместе с пустой Content-Length. Интерпретация этого - клиент (завиток в нашем случае) запрашивает ресурс, говорящий, что передача данных не требуется, если файл не был изменен на сервере:

curl -I http://yanpy.dev.s3.amazonaws.com/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg 
--header "If-None-Match: 37a907fc5dd7cfd0c428af78f09e95a9"

HTTP/1.1 304 Not Modified
Date: Sun, 25 Jun 2017 17:53:33 GMT
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Server: AmazonS3

curl -I http://yanpy.dev.s3.amazonaws.com/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg 
--header "If-Modified-Since: Wed, 21 Jun 2017 07:42:31 GMT"

HTTP/1.1 304 Not Modified
Date: Sun, 25 Jun 2017 18:17:34 GMT
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Server: AmazonS3

"PageSpeed ​​предложила использовать кеширование браузера", что означает Cache = элемент управления отсутствует. Nginx как прокси для S3 файлов решает не только проблема с отсутствующими заголовками, но и экономия трафика используя кеш-прокси Nginx.

Я использую macOS, но конфигурация Nginx работает на Linux точно так же без изменений. Шаг за шагом:

1.Установить Nginx

brew update && brew install nginx

2.Setup Nginx в прокси-сервер S3, см. конфигурацию ниже

3.Request файл через Nginx. Пожалуйста, посмотрите заголовок Сервер, теперь мы видим Nginx, а не Amazon S3:

curl -I http://localhost:8080/s3/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg

HTTP/1.1 200 OK
Server: nginx/1.12.0
Date: Sun, 25 Jun 2017 18:30:26 GMT
Content-Type: binary/octet-stream
Content-Length: 378843
Connection: keep-alive
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Accept-Ranges: bytes
Cache-Control: max-age=31536000

Запросить файл через Nginx

4.Request файл с использованием прокси Nginx с условным GET:

curl -I http://localhost:8080/s3/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg 
--header "If-None-Match: 37a907fc5dd7cfd0c428af78f09e95a9"

HTTP/1.1 304 Not Modified
Server: nginx/1.12.0
Date: Sun, 25 Jun 2017 18:32:16 GMT
Connection: keep-alive
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Cache-Control: max-age=31536000

Запросить файл с использованием прокси Nginx с условным GET

5.Request файл, используя кеш-прокси Nginx, просмотрите заголовок X-Cache-Status, его значение - MISS, пока кеш не разогреется после первого запроса

curl -I http://localhost:8080/s3_cached/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg
HTTP/1.1 200 OK
Server: nginx/1.12.0
Date: Sun, 25 Jun 2017 18:40:45 GMT
Content-Type: binary/octet-stream
Content-Length: 378843
Connection: keep-alive
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Cache-Control: max-age=31536000
X-Cache-Status: HIT
Accept-Ranges: bytes

Запросить файл с использованием кеша прокси Nginx

На основе официальная документация Nginx Я предоставляю конфигурацию Nginx S3 с оптимизированными настройками кэширования, которые поддерживают следующие параметры:

  • proxy_cache_revalidate инструктирует NGINX использовать условный GET запросы при обновлении содержимого с серверов происхождения
  • параметр обновления в директиву proxy_cache_use_stale указывает, что NGINX должен предоставлять устаревший контент, когда клиенты запрашивают элемент в то время как обновление к нему загружается с исходного сервера, вместо перенаправления повторных запросов на сервер
  • с включенным proxy_cache_lock, если несколько клиентов запросят файл, который не является текущим в кэше (MISS), только первый из них запросы разрешены до исходного сервера.

Конфигурация Nginx:

worker_processes  1;
daemon off;

error_log  /dev/stdout info;
pid        /usr/local/var/nginx/nginx.pid;


events {
  worker_connections  1024;
}


http {
  default_type       text/html;
  access_log         /dev/stdout;
  sendfile           on;
  keepalive_timeout  65;

  proxy_cache_path   /tmp/ levels=1:2 keys_zone=s3_cache:10m max_size=500m
                     inactive=60m use_temp_path=off;

  server {
    listen 8080;

    location /s3/ {
      proxy_http_version     1.1;
      proxy_set_header       Connection "";
      proxy_set_header       Authorization '';
      proxy_set_header       Host yanpy.dev.s3.amazonaws.com;
      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;
      add_header             Cache-Control max-age=31536000;
      proxy_pass             http://yanpy.dev.s3.amazonaws.com/;
    }

    location /s3_cached/ {
      proxy_cache            s3_cache;
      proxy_http_version     1.1;
      proxy_set_header       Connection "";
      proxy_set_header       Authorization '';
      proxy_set_header       Host yanpy.dev.s3.amazonaws.com;
      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_cache_revalidate on;
      proxy_intercept_errors on;
      proxy_cache_use_stale  error timeout updating http_500 http_502 http_503 http_504;
      proxy_cache_lock       on;
      add_header             Cache-Control max-age=31536000;
      add_header             X-Cache-Status $upstream_cache_status;
      proxy_pass             http://yanpy.dev.s3.amazonaws.com/;
    }

  }
}

Ответ 2

Без деталей, с которыми скомпилированы модули Nginx, мы можем сказать два способа добавления заголовков Expires и Cache-Control ко всем файлам.

Nginx S3 proxy

Это то, о чем вы просили - с помощью Nginx добавить заголовки кеширования с истечением срока действия на S3 файлы.

Nginx этот набор-misc-nginx-модуль нужен для поддержки прокси Nginx S3 и изменения/добавления срока действия, управления кешем на лету, Это стандартное полное руководство от компиляции к использованию, это отлично руководство для nginx-extras для сервера Ubuntu. Это полное руководство с примером в WordPress.

Есть больше модулей S3 для дополнительных вещей. Без этих модулей Nginx не поймет, и configure test (nginx -t) пройдет тест с неправильной конфигурацией. set-misc-nginx-module минимально для ваших нужд. Что бы вы хотели, лучший пример в этом Github gist.

Поскольку не все используются с компиляцией, и настройка действительно немного сложна, я также пишу способ установить заголовок Expires и Cache-Control для всех файлов в одном ведро Amazon S3.

Срок службы ковша Amazon S3 и заголовок Cache-Control

Кроме того, можно установить заголовки Expires и Cache-Control для всех объектов в одном ведре AWS S3 с помощью script или командной строки. Существует несколько таких бесплатных библиотек и скриптов в Github как этот, bucket explorer, инструмент Amazon, Amazon this doc и этот документ. Команда будет подобна этому инструменту cp CLI:

aws s3 cp s3://mybucket/ s3://mybucket/ --recursive --metadata-directive REPLACE \
--expires 2027-09-01T00:00:00Z --acl public-read --cache-control max-age=2000000,public

Ответ 3

Из архитектурного обзора, что вы пытаетесь сделать, это неправильный способ:

  • Amazon S3 предположительно оптимизирован как высокодоступный кэш; добавив на него ручной проксирующий слой, вы просто вводите лишнюю дополнительную задержку и огромную точку отказа, а также потеряете все преимущества, которые могут возникнуть из S3

  • Ваш анализ производительности в отношении количества файлов неверен. Если у вас тысячи файлов на S3, правильным решением было бы написать одноразовый script, чтобы изменить требуемые атрибуты на S3, вместо того, чтобы вручную перекрыть механизм проксирования, который вы не полностью понимаете, и это будет выполняться много раз (ad nauseam). Выполнение проксирования, скорее всего, будет полосой помощи, и, на самом деле, скорее всего, это снизит производительность, а не увеличит ее (даже если вы получите автоматическое средство без гражданства, сообщите об этом в противном случае). Не говоря уже о том, что это также будет ненужным утечкой ресурсов и может повлиять на фактические проблемы с производительностью и гейзенбуги по линии.


Тем не менее, если вы все еще хотите проксировать с добавлением заголовков, правильный способ сделать это с nginx будет с помощью expires.

Например, вы можете разместить expires max; до или после директивы proxy_pass в соответствующем месте.

Директива expires автоматически выполняет настройку правильного заголовка Cache-Control для вас; но вы также можете использовать add_header директиву, если вы хотите вручную добавить пользовательские заголовки ответов.