Проксирование хранилища объектов с помощью Nginx в Ubuntu 16.04

Данный мануал поможет настроить Nginx для проксирования запросов к хранилищу объектов. Nginx будет получать HTTP(S)-запросы пользователей и передавать их вашему сервису хранения объектов, который будет обрабатывать результаты  и возвращать их Nginx.

Такая настройка позволяет:

  • Добавить пользовательский домен.
  • Добавить кэширование.
  • Использовать свой SSL-сертификат.
  • Использовать различные механизмы контроля доступа.
  • Кэшировать активы в центре данных, который находится ближе к вашим пользователям

Этот мануал поможет настроить Nginx для передачи запросов по пользовательскому домену (опционально – с SSL-сертификатом Let’s Encrypt) в хранилище с публичными активами, а затем настроить кеширование, чтобы ускорить обработку часто посещаемых объектов.

Требования

  • Сервер Ubuntu 16.04 с предварительно установленным веб-сервером Nginx (читайте мануал Установка Nginx в Ubuntu 16.04).
  • Домен, указывающий на ваш сервер (в мануале используется условный домен assets.example.com).
  • Хранилище объектов и какой-нибудь файл в нем (в мануале используется условный example.png).
  • URL вашего хранилища.

1: Настройка прокси-сервера

По умолчанию установка Nginx на Ubuntu вернет страницу Welcome to Nginx для всех запросов. Чтобы веб-сервер Nginx мог выполнять другие действия с запросами этого домена, нужно добавить новую конфигурацию.

Откройте новый конфигурационный файл в каталоге /etc/nginx/sites-available:

sudo nano /etc/nginx/sites-available/assets.example.com

Это откроет пустой файл в текстовом редакторе. Вставьте следующую конфигурацию (не забудьте заменить условные данные своим доменным именем и URL-адресом хранилища):

server {
listen 80;
listen [::]:80;
server_name assets.example.com;
location / {
proxy_pass https://example.nyc3.example-storage.com/;
proxy_hide_header      Strict-Transport-Security;
}
}

Сохраните и закройте файл. Это стандартный блок server. Сначала он определяет, какой порт прослушивается (80 на  IPv4 и IPv6), затем указывается server_name, на которое будет отвечать Nginx.

Далее идет блок location. Все директивы этого блока (в фигурных скобках) будут применяться только к определенным URL-адресам. В данном случае значение / указывает, что блок должен применяться ко всем URL-ам.

Директива proxy_pass сообщает Nginx передавать запросы на указанный сервер. Строка proxy_hide_header отделяет заголовок Strict-Transport-Security перед передачей ответа клиенту. Хранилище использует этот заголовок для переключения всех HTTP-соединений на HTTPS. Передача этого заголовка вашим пользователям может иметь неожиданные последствия, если сайт доступен как для HTTP, так и для HTTPS-соединений.

Теперь нужно включить конфигурацию. Создайте симлинк на конфигурационный файл в каталоге /etc/nginx/sites-enabled/:

sudo ln -s /etc/nginx/sites-available/assets.example.com /etc/nginx/sites-enabled/

Чтобы проверить синтаксис, запустите nginx -t как root:

sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Перезапустите Nginx:

sudo systemctl reload nginx

Теперь протестируйте прокси-сервер.

Тестирование прокси-сервера

Чтобы протестировать соединение, можно использовать curl. Команда curl -I вернет только HTTP-заголовки ответов. Этого достаточно, чтобы понять, что все работает правильно.

Извлеките объект из хранилища с помощью URL:

curl -I https://example.nyc3.example-storage.com/example.png
HTTP/1.1 200 OK
Content-Length: 81173
Accept-Ranges: bytes
Last-Modified: Tue, 28 Nov 2017 21:19:37 GMT
ETag: "7b2d05a5bd1bfeebcac62990daeafd14"
x-amz-request-id: tx000000000000000002398-005a1edfcd-afba2-nyc3a
Content-Type: image/png
Date: Wed, 29 Nov 2017 16:26:53 GMT
Strict-Transport-Security: max-age=15552000; includeSubDomains; preload

В первой строке вы увидите 200 OK, это значит, что запрос отправлен успешно. Сервер вернул размер файла (Content-Length), тип файла (Content-Type) и другую информацию о дате и кэше.

Извлеките тот же файл через прокси:

curl -I http://assets.example.com/example.png
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 29 Nov 2017 16:27:24 GMT
Content-Type: image/png
Content-Length: 81173
Connection: keep-alive
Accept-Ranges: bytes
Last-Modified: Tue, 28 Nov 2017 21:19:37 GMT
ETag: "7b2d05a5bd1bfeebcac62990daeafd14"
x-amz-request-id: tx00000000000000000a045-005a1edfec-a89a3-nyc3a

Вывод почти такой же. Основное изменение – это заголовок Server, который идентифицирует Nginx. Если вы получили похожий результат, ваш прокси работает правильно!

2: Настройка кэширования

Чтобы кэшировать ответы, Nginx необходимо место для хранения ключей, метаданных и самого контента ответа. Создайте каталог кэша в каталоге system/tmp. Для этого добавьте сниппет конфигурации в новый файл /etc/nginx/conf.d/. Откройте этот файл:

sudo nano /etc/nginx/conf.d/example-cache.conf

Вставьте следующую строку, сохраните и закройте файл.

proxy_cache_path /tmp/example-cache/ levels=1:2 keys_zone=example-cache:16m max_size=10g inactive=60m use_temp_path=off;

Эта строка определяет несколько характеристик кэша:

  • /tmp/example-cache/ — путь к кэшу.
  • levels=1:2 устанавливает двухуровневую иерархию каталогов для хранения кэшированного контента. Слишком большое количество файлов в одном каталоге может вызвать проблемы со скоростью и надежностью, поэтому благодаря этой опции Nginx будет разделять файлы между несколькими каталогами.
  • keys_zone=example-cache:16m задает название кэша и устанавливает 16 мегабайт памяти для хранения ключей. Этого должно быть достаточно для хранения данных более чем 100 000 ключей.
  • max_size=10g ограничивает размер кэша до 10 гигабайт. Вы можете настроить этот параметр согласно вашим требованиям.
  • inactive=60m: Nginx удалит кэшированные файлы через 60 минут, если за это время они не запрашивались (даже если срок хранения файлов не истек). Вы можете настроить это значение по своему вкусу, если у вас много объектов, которые редко запрашиваются.
  • use_temp_path=off: Nginx будет записывать временные файлы в каталог кэша, что поможет избежать необходимости копировать файлы между файловыми системами.

Теперь нужно включить новый блок и добавить дополнительные опции. Откройте конфигурационный файл сайта:

sudo nano /etc/nginx/sites-available/assets.example.com

Добавьте в конец блока location / следующее (после директивы proxy_hide_header, но до закрывающей фигурной скобки):

. . .
proxy_cache            example-cache;
proxy_cache_valid      200 60m;
proxy_cache_use_stale  error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_revalidate on;
proxy_cache_lock       on;
proxy_ignore_headers   Set-Cookie;
add_header             X-Cache-Status $upstream_cache_status;
. . .

Сохраните и закройте файл.

  • proxy_cache сообщает Nginx, какой кэш используется (в данном случае это example-cache, который вы ранее определили в файле example-cache.conf).
  • proxy_cache_valid позволяет Nginx рассматривать любой ответ 200, действительный в течение 60 минут. Это означает, что после того, как прокси успешно извлечет файл из хранилища, в течение следующих 60 минут Nginx будет использовать кэшированную копию, не запрашивая объект в хранилище. Обратите внимание: если ваши объекты имеют набор заголовков Cache-Control, значение заголовка переопределит эту конфигурацию.
  • proxy_cache_use_stale позволяет Nginx возвращать устаревший ответ (срок действия которого истек), если хранилище не отвечает, выдает ошибку или если кэшированный ответ находится в процессе обновления.
  • proxy_cache_revalidate позволяет прокси-серверу проверять кэшированные файлы с помощью условных GET-запросов. Это означает, что, когда срок действия кэшированного файла истекает, и Nginx необходимо проверить хранилище, Nginx будет использовать заголовки If-Modified-Since или If-None-Match, чтобы извлечь объект только в случае, если он действительно изменился. Если он не был обновлен, хранилище вернет 304 Not Modified, и Nginx просто снова пометит существующий кэшированный ответ как действительный.
  • proxy_cache_lock задерживает последующие запросы к объекту, когда прокси-сервер уже извлекает его из бэкэнда сервера. Когда первый запрос будет обработан, остальные запросы будут отправлены из кеша.
  • proxy_ignore_headers Set-Cookie игнорирует куки-файлы, которые могут помешать кешированию.
  • add_header X-Cache-Status … добавляет заголовок с информацией о том, был ли запрос обработан из кэша (HIT) или нет (MISS). Если запрос был в кэше, но срок его действия истек, вы увидите заголовок (REVALIDATED).

Теперь проверьте конфигурацию на предмет ошибок и перезапустите Nginx, если ошибок нет:

sudo nginx -t
sudo systemctl reload nginx

Теперь нужно убедиться, что кэш работает как ожидалось.

Тестирование кэша

Чтобы убедиться, что кэш работает, можно использовать curl и поискать заголовок X-Cache-Status:

curl -I http://assets.example.com/example.png
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 29 Nov 2017 18:40:28 GMT
Content-Type: image/png
Content-Length: 81173
Connection: keep-alive
Last-Modified: Tue, 28 Nov 2017 21:19:37 GMT
ETag: "7b2d05a5bd1bfeebcac62990daeafd14"
x-amz-request-id: tx000000000000000013841-005a1eff1b-a89e4-nyc3a
X-Cache-Status: MISS
Accept-Ranges: bytes

Первый запрос получит заголовок MISS. Повторите попытку:

curl -I http://assets.example.com/example.png
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 29 Nov 2017 18:40:53 GMT
Content-Type: image/png
Content-Length: 81173
Connection: keep-alive
Last-Modified: Tue, 28 Nov 2017 21:19:37 GMT
ETag: "7b2d05a5bd1bfeebcac62990daeafd14"
x-amz-request-id: tx000000000000000013841-005a1eff1b-a89e4-nyc3a
X-Cache-Status: HIT
Accept-Ranges: bytes

Теперь запрос получил заголовок HIT. Это значит, что объект был обслужен из кэша через прокси.

3: Настройка TLS/SSL (опционально)

Настоятельно рекомендуется защитить сайт и активы протоколом HTTPS. Чтобы узнать, как загрузить и установить бесплатные сертификаты от центра сертификации Let’s Encrypt, читайте руководство Создание сертификата Let’s Encrypt для виртуального хоста Nginx в Ubuntu 16.04.

Заключение

Данный мануал помог настроить Nginx для проксирования запросов в хранилище объектов и добавить кэширование для повышения производительности.

Полученная установка – хороший старт, но вы можете самостоятельно оптимизировать некоторые параметры в соответствии с трафиком и потребностями приложения.

Документация Nginx, в частности, модуль ngx_http_proxy, может предоставить более подробную информацию о доступных параметрах конфигурации.

Tags: ,