Proxy pass nginx что это
Основы работы с Nginx: проксирование, балансировка нагрузки, буферизация и кэширование
В этом руководстве мы обсудим возможности HTTP-проксирования веб-сервера Nginx, которые позволяют ему передавать запросы на http-серверы бэкэнда для дальнейшей обработки. Nginx часто настраивается как обратный прокси-сервер, который помогает масштабировать инфраструктуру или передавать запросы другим серверам, которые не предназначены для обработки больших клиентских нагрузок.
Вы научитесь масштабировать свою инфраструктуру, используя встроенные функции балансировки нагрузки Nginx. Также вы узнаете, как с помощью буферизации и кеширования улучшить производительность прокси-операций клиентов.
Основы проксирования
Одной из причин использовать проксирование Nginx является возможность масштабирования инфраструктуры. Nginx умеет одновременно управлять несколькими параллельными соединениями. Это делает его идеальным сервером для контакта с клиентами. Сервер может передавать запросы на любое количество бэкэнд-серверов для обработки основного массива трафика, поступающего в вашу инфраструктуру. Это также обеспечивает гибкость при добавлении или замене бэкэнд-серверов по мере необходимости.
Вторя причина настроить HTTP-проксирование – это наличие в инфраструктуре серверов приложений, которые не могут обрабатывать клиентские запросы напрямую в производственных средах. Многие фреймворки предоставляют встроенные веб-серверы, но большинство из них не столь надежны, как высокопроизводительные серверы, такие как Nginx. Использование обратного прокси Nginx может улучшить пользовательский опыт и повысить безопасность.
Проксирование в Nginx осуществляется путем обработки запроса, направленного на сервер Nginx, и передачи его другим серверам для фактической обработки. Результат запроса передается обратно на Nginx, который затем передает информацию клиенту. Другими серверами в этом случае могут быть удаленные компьютеры, локальные серверы или даже другие виртуальные серверы, определенные в настройке Nginx. Серверы, к которым обращается прокси Nginx, называются upstream серверами.
Nginx может проксировать запросы на серверы, которые обмениваются данными с помощью протоколов http(s), FastCGI, SCGI и uwsgi или memcached через отдельные наборы директив для каждого типа проксирования. В этом мануале мы сосредоточимся на протоколе http. Экземпляр Nginx отвечает за передачу запроса и связь с любым компонентом обмена сообщениями в формате, который может понять upstream сервер.
Директива proxy_pass
Самый простой тип проксирования включает в себя передачу запроса на один сервер, который может связываться с помощью http. Этот тип проксирования известен как proxy pass и обрабатывается одноименной директивой proxy_pass.
Директива proxy_pass в основном встречается в контекстах location. Она также поддерживается блоками if в контексте location и limit_except. Когда запрос совпадает с адресом, указанным в proxy_pass, он пересылается по этому URL-адресу.
Рассмотрим такой пример:
В приведенном выше фрагменте конфигурации в конце блока server в определении proxy_pass не указывается URI. Для определений, соответствующих этому шаблону, запрошенный клиентом URI будет передан на upstream сервер без изменений.
Например, когда этот блок обрабатывает запрос /match/here/please, URI запроса будет отправлен на сервер example.com как http://example.com/match/here/please.
Рассмотрим альтернативный сценарий:
В приведенном выше примере прокси-сервер определяется вместе с сегментом URI в конце (/new/prefix). Когда в определении proxy_pass указывается URI, то часть запроса, которая соответствует определению location, заменяется этим URI.
К примеру, запрос /match/here/please будет передаваться на upstream сервер как http://example.com/new/prefix/please. Префикс /match/here заменяется на /new/prefix. Об этом важно помнить.
Иногда такая замена невозможна. В этих случаях URI в конце определения proxy_pass игнорируется, и на upstream сервер передается исходный URI клиента или URI, измененный другими директивами.
Например, при использованием регулярных выражений Nginx не может определить, какая часть URI соответствует выражению, поэтому он отправляет исходный URI-запрос клиента. Или, например, если директива rewrite используется в одном и том же location, она переписывает URI клиента, но он все же обрабатывается в одном блоке. В этом случае будет передан переписанный URI.
Обработка заголовков в Nginx
Чтобы upstream сервер обработал запрос должным образом, одного URI недостаточно. Запрос, поступающий от имени клиента через Nginx, будет выглядеть иначе, чем запрос, поступающий непосредственно от клиента. Большая часть этого – заголовки, которые согласуются с запросом.
Когда Nginx проксирует запрос, он автоматически вносит некоторые поправки в заголовки, полученные от клиента.
Первый вывод, который можно сделать из вышеизложенной информации: если вы не хотите передавать тот или иной заголовок, нужно задать ему значение пустой строки. Заголовки с такими значениями полностью удаляются из переданного запроса.
Также следует убедиться, что в нестандартных заголовках нет подчеркиваний, что если ваше бэкэнд-приложение будет обрабатывать такие заголовки. Если вам нужны заголовки, в которых используется символ подчеркивания, вы можете установить директиве underscores_in_headers значение on (это валидно либо в контексте http, либо в контексте объявления server по умолчанию для комбинации IP-адреса/порта). Если вы этого не сделаете, Nginx пометит эти заголовки как некорректные и просто сбросит их, прежде чем перейти к upstream серверу.
Заголовок Host часто имеет такие значения:
Настройка или сброс заголовков
Чтобы настроить или установить заголовки для прокси-соединений, можно использовать директиву proxy_set_header. Например, чтобы изменить заголовок Host и добавить дополнительные заголовки, нужно использовать что-то вроде этого:
Конечно, директиву proxy_set_header стоит переместить в контекст server или http, чтоб иметь возможность ссылаться на нее:
Раздел Upstream для балансировки нагрузки проксируемых соединений
В предыдущих примерах вы увидели, как сделать настроить простое HTTP-прокси соединение на одном сервере. Nginx позволяет легко масштабировать эту конфигурацию, указав целые пулы бэкэнд-серверов, на которые можно передавать запросы.
Это можно сделать с помощью директивы upstream, которая позволяет определить пул серверов. Эта конфигурация предполагает, что любой из перечисленных серверов способен обрабатывать запрос клиента. Это позволяет масштабировать инфраструктуру практически без усилий. Директива upstream должна быть установлена в контексте http конфигурации Nginx.
Рассмотрим простой пример:
# http context
upstream backend_hosts <
server host1.example.com;
server host2.example.com;
server host3.example.com;
>
server <
listen 80;
server_name example.com;
location /proxy-me <
proxy_pass http:// backend_hosts ;
>
>
В приведенном выше примере был создан контекст upstream под названием backend_hosts. После определения это имя будет доступно в proxy pass как обычный домен. Как вы можете видеть, в блоке server все запросы, сделанные в example.com/proxy-me/…, передаются в пул, который вы определили выше. В этом пуле хост выбирается с помощью настраиваемого алгоритма. По умолчанию это простой процесс round-robin (каждый запрос будет поочередно маршрутизироваться на другой хост).
Изменение алгоритма балансировки в контексте upstream
Настроить алгоритм в пуле upstream можно с помощью таких флагов и директив:
При изменении алгоритма блок может выглядеть так:
В приведенном выше примере сервер будет выбран по наименьшему количеству соединений. Можно также добавить директиву ip_hash, чтобы обеспечить «липкость» сессии.
Что касается метода hash, вы должны указать ключ для хэша. Это может быть что угодно:
В приведенном выше примере запросы будут распределяться на основе значений IP-адреса и порта клиента. Также здесь есть опциональный параметр consistent, который реализует алгоритм хэширования ketama consistent. Это означает, что если upstream серверы изменятся, это будет иметь минимальное воздействие на кэш.
Установка веса сервера для балансировки
В объявлениях бэкэнд-серверов по умолчанию все серверы весят одинаково. Это предполагает, что каждый сервер может и должен обрабатывать одинаковый объем нагрузки (с учетом эффектов алгоритмов балансировки). Тем не менее, вы также можете установить пользовательский вес своих серверов:
Теперь host1.example.com будет получать в три раза больше трафика, чем другие два сервера. Вес каждого сервера по умолчанию равен 1.
Использование буферов для освобождения бэкэнд-серверов
Один из главных вопросов при проксировании – насколько изменится скорость работы при добавлении сервера. Увеличение или уменьшение количества серверов можно значительно смягчить с помощью системы буферизации и кэширования Nginx.
При проксировании на другой сервер на опыт клиента влияет скорость двух разных подключений:
Nginx имеет возможность корректировать свое поведение на основе того, какое из этих соединений вы хотите оптимизировать.
Без буферов данные с прокси-сервера сразу же отправляются к клиенту. Если клиентские соединения быстрые, буферизацию можно отключить, чтобы клиент как можно скорее мог получить данные. При использовании буферов прокси-сервер Nginx будет временно хранить ответ бэкэнда, а затем передавать эти данные клиенту. Если клиент работает медленно, это позволит серверу Nginx быстрее закрыть соединение с бэкэндом. Затем он сможет обрабатывать передачу данных клиенту любым возможным способом.
Nginx по умолчанию использует буферизацию, так как скорость соединения, как правило, меняется в зависимости от клиента. Буферизация настраивается с помощью следующих директив. Их можно установить в контексте http, server или location. Важно иметь в виду, что директивы size касаются каждого запроса, поэтому они могут повлиять на производительность серверов при поступлении множества клиентских запросов.
Как вы можете видеть, Nginx предоставляет довольно много разных директив для настройки поведения буферизации. В большинстве случаев вам не придется использовать их, но некоторые из этих значений могут пригодиться. Возможно, наиболее полезными являются proxy_buffers и proxy_buffer_size.
В этом примере увеличивается количество доступных буферов для обработки запросов и уменьшается размер буфера для хранения заголовков:
# server context
proxy_buffering on;
proxy_buffer_size 1k;
proxy_buffers 24 4k;
proxy_busy_buffers_size 8k;
proxy_max_temp_file_size 2048m;
proxy_temp_file_write_size 32k;
location / <
proxy_pass http://example.com;
>
Если у вас есть быстрые клиенты, которым нужно быстро отправить данные, можно полностью отключить буферизацию. Nginx будет по-прежнему использовать буферы, если сервер upstream быстрее, чем клиент, но он попытается немедленно передать данные клиенту. Если клиент работает медленно, это может привести к тому, что upstream соединение останется открытым до тех пор, пока клиент не сможет получить данные. Когда буферизация выключена, будет использоваться только буфер, определенный директивой proxy_buffer_size:
# server context
proxy_buffering off;
proxy_buffer_size 4k;
location / <
proxy_pass http://example.com;
>
Высокая доступность (опционально)
Проксирование Nginx можно сделать более надежным, добавив избыточный набор балансировщиков нагрузки, чтобы создать инфраструктуру высокой доступности.
Настройка высокой доступности – это инфраструктура без единой точки отказа, и балансировщики нагрузки являются частью этой конфигурации. Имея несколько балансировщиков нагрузки, вы сможете предотвратить простои, если один из балансировщиков станет недоступен.
Кэширование и снижение времени ответа
Буферизация помогает освободить сервер бэкэнда для обработки большего количества запросов, но Nginx также может кэшировать контент с бэкэнд-серверов, устраняя необходимость подключения к upstream серверу для обработки запросов.
Настойка прокси-кэша
Для настройки кэширования ответов бэкэнд серверов можно использовать директиву proxy_cache_path, которая определяет пространство для хранения кэша. Её следует задавать в контексте http.
В приведенном ниже примере показано, как использовать эту и некоторые другие директивы для настройки системы кэширования.
# http context
proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=backcache:8m max_size=50m;
proxy_cache_key «$scheme$request_method$host$request_uri$is_args$args»;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
Директива proxy_cache_path определяет каталог в файловой системе, где нужно хранить кэш. В этом примере это каталог /var/lib/nginx/cache. Если этот каталог не существует, вы можете создать его и определить права доступа к нему:
Параметр levels= указывает, как будет организован кэш. Nginx создаст ключ кеша путем хэширования значения ключа (он настраивается ниже). В результате будет создан каталог, имя которого состоит из одного символа (это будет последний символ хешированного значения), и подкаталог с именем из двух символов (следующие два символа в конце хэша). Это помогает Nginx быстро найти соответствующие значения.
Параметр keys_zone= определяет имя зоны кеша (backcache). Здесь также указывается, сколько метаданных можно хранить. В этом случае сервер будет хранить 8 МБ ключей. На 1 мегабайте Nginx может хранить около 8000 записей. Параметр max_size устанавливает максимальный размер кэшированных данных.
Директива proxy_cache_key устанавливает ключ, который будет использоваться для хранения кешированных значений. Этот же ключ используется для проверки того, можно ли запросить данные из кеша. Здесь используется комбинация схемы (http или https), метода HTTP-запроса, а также запрошенного хоста и URI.
Директива proxy_cache_valid может быть указана несколько раз. Она позволяет определить, как долго должны храниться значения в зависимости от кода состояния. В данном примере удачные и переадресованные ответы хранятся в течение 10 минут, а ответы 404 удаляются каждую минуту.
Теперь зона кэширования настроена, но пока что Nginx не знает, когда именно применять кеширование.
Эта информация указывается в контексте location для бекэнд серверов:
Используя директиву proxy_cache, можно указать, что для этого контекста следует использовать зону кэширования backcache. Nginx проверит запись перед тем, как перейти к серверу.
Рекомендации по кэшированию результатов
Кеширование увеличивает скорость прокси-сервера. Но не стоит забывать о нескольких нюансах.
Во-первых, любая личная информация пользователей ни в коем случае не должна кэшироваться, чтобы пользователи не получали в ответ данные о других пользователях. Эта проблема не касается статичных сайтов.
Если на сайте есть динамические элементы, им следует уделить внимание. Решение этой проблемы зависит от бекэнд-сервера. Для личных данных используется заголовок Cache-Control со значением no-cache, no-store или private.
Есть связанный с этим поведением заголовок max-age, который определяет срок хранения кэша в секундах.
Его значение зависит от чувствительности данных. При разумном использовании этого заголовка конфиденциальные данные будут в безопасности, а часто изменяемый контент будет своевременно обновляться.
Если вы используете nginx и на бэкэнде, добавьте директиву expires, которая определяет значение max-age заголовка Cache-Control:
Первый блок поддерживает кэш в течение часа. Второй блок присваивает заголовку Cache-Control значение no-cache. Для внесения других изменений примените директиву add_header:
Proxy pass nginx что это
В этой мы рассмотрим возможности сервера NGINX в http проксировании, что помогает перенаправлять запросы на бекэнд сервера для дальнейшей обработки. Довольно часто Nginx настраивают в качестве реверсивного прокси для упрощения масштабирования инфраструктуры или для перенапраления запросов на сервера, которые не предназначены для работы при большой нагрузке.
Также мы затронем каким образом можно осуществить масштабирование при помощи встроенных в Nginx средствах балансировки и каким образом буферизация и кеширование помогут вам улучшить работоспособность прокси.
Общая информация по прокси
Если раньше вы сталкивались только с простыми односерверными настройками, то наверняка у вас возникает вопрос: «А зачем вообще перенаправлять запросы?».
Одна из основных причин — масштабирование инфраструктуры. Изначально Nginx был создан с возможностью обрабатывать множество одновременных соединений. Таким образом он способен перенаправлять запрос какому угодно количеству бекэнд-серверов, что позволяет вам распределить нагрузку. Также архитектура сервера помогает вам легко добавлять новые или отключать старые бекэнд-сервера.
Другой причиной может служит ситуация, когда ваш бекэнд-сервер не может обрабатывать поступающий к нему напрямую запрос. Многие фреймворки имеют в своем составе веб-сервера, но им, как правило, далеко до возможностей Nginx. Разместив Nginx до этих серверов ускорит работу и повысит безопасность вашего приложения.
Проксирование в Nginx работает путем изменения полученного запроса и передачи его серверам, отвечающим за его обработку. Результат отправляется обратно Nginx, который в свою очередь отвечает клиенту. В роли тех самых «других» серверов могут выступать удаленные или локальные машины, а иногда очередные виртуальные сервера, созданные в пределах Nginx. Сервера, на которые nginx перенаправляет запросы называются вышестоящими серверами ( upstream servers ).
Nginx способен перенаправлять запросы используя http(s), FastCGI, uwsgi или memcached протоколы посредством различных наборов директив для каждого типа прокси. В этой статье мы остановимся на протоколе http. Nginx отвечает за передачу запроса в таком виде, в котором вышестоящий сервер способен его понять.
Разбираем базовый проход через http прокси
Давайте взглянем на пример:
В этом примере в конце описания сервера не указан URI адрес. При получении запроса, соответствующего этой настройке, он будет без изменения передан вышестоящему серверу.
Приведем другой пример:
Такая замена не всегда возможна. В таком случае URI игнорируется и вышестоящий сервер получает либо оригинальный запрос, либо измененный другими директивами.
Разбираемся как Nginx обрабатывает заголовки
Стоит понимать, что одного только URI не достаточно, чтобы вышестоящий сервер корректно обработал запрос. Перенаправленный nginx запрос будет немного видоизменен. Больше всего будут затронуты заголовки запроса.
При передаче запроса Nginx вносит необходимые изменения в заголовки:
Nginx убирает все пустые заголовки. Нет никакого смысла загружать сервер пустыми заголовками.
Часто используемые значения заголовка host:
Установка или переназначение заголовков
Конечно, есть смысл перенести директиву proxy_set_header в раздел серверного или http контекста, чтобы можно было ссылаться на неё из разных мест настройки.
Определение вышестоящего контекста для балансировки прокси соединений
В предыдущем примере мы рассмотрели как создать простое прокси http соединение до бекэнд сервера. Nginx позволяет нам указывать целый пул серверов, которым можно переадресовывать запросы.
Эту возможность можно использовать при помощи директивы upstream задав ей список доступных серверов. Такая настройка подразумевает, что каждый сервер из этого списка способен полностью ответить на поступивший к нему запрос. То есть мы можем легко масштабировать свою инфраструктуру без лишних проблем. Директива upstream должна быть указана в контексте http настройки nginx сервера.
Разберем простой пример:
Изменение алгоритма балансировки
Изменить алгоритм в пределах пула серверов можно при задании определенных флагов и директив:
При изменении алгоритма балансировки блок настройки принимает следующий вид:
Указание весов серверов при балансировки
При задании списка серверов, каждый сервер имеет равнозначный вес. То есть каждый сервер может и должен обрабатывать одну и ту же степень нагрузки (принимая во внимания алгоритм балансировки). Но вы так же можете задать каждому серверу определенный вес.
В этом примере сервер host1.example.com будет получать в три раза больше запросов, чем два других сервера. По-умолчанию значение веса для каждого сервера устанавливается в единицу.
Использованию буферов для освобождения бекэнд серверов
Главный вопрос при проксировании это насколько изменится скорость работы при добавлении дополнительного сервера. Переход на большее или меньшее количество серверов может быть значительно смягчен при помощи системы буферизации и кеширования nginx.
При передачи запроса серверу следует учитывать скорость обоих соединений:
соединение клиент — nginx сервер соединение nginx сервер — бекэнд сервер
Nginx способен изменять свое поведение в зависимости от того, какое из соединений вы планируете оптимизировать.
Без использования буферов данные поступившие от прокси сервера сразу же возвращаются клиенту. Если вы отталкиваетесь от того, что клиентское соединение достаточно быстрое, то буферизацию можно отключить. При использовании буферов Nginx какое-то время хранит ответ полученный от бекэнд сервера и потом отправляет его клиенту. Если клиент не достаточно быстр, то nginx закрывает соединение с бекэнд-сервером как можно быстрее, а данные отправляет клиенту как только тот будет готов их принять.
proxy_busy_buffer_size : эта директива указывает максимально возможное количество занятых буферов. Хотя клиент может читать информацию только из одного буфера за подход, буферы образуют очередь для отправки данных клиентам. Таким образом она указывает на объем информации в буфере, которая имеет такое состояние.
proxy_max_temp_file_size : максимальный размер временного файла на диске на каждый запрос. Они создаются в случае, если ответ бекэнд сервера не помещается в один буфер. proxy_temp_file_write_size : максимально возможный объем информации, которая записывается за один подход в файл, если ответ сервера не помещается в буфер. proxy_temp_path : путь к месту на диске, где Nginx разрешается хранить временные файлы, если ответ не умещается в буфер.
Настройка прокси кеширования для уменьшения времени ответа
Буферизация помогает ослабить нагрузку на бекэнд-сервера, тем самым обработать большее число запросов. Nginx также предлагает механизм для кеширования ответов от бекэнд-серверов. Что помогает вообще отказаться от обращению к вышестоящим серверам при повторных запросах.
Настройка прокси кеша
В следующем примере мы выполним необходимые настройки для поднятия системы кеширования:
Пареметр level= указывает организацию кеша. Nginx будет создавать ключ кеша исходя из хеша значения ключа (настраивается ниже). Мы указали уровни таким образом, что получим каталог, название которого состоит из одного символа и вложенный в него каталог с названием из двух символов. Вам скорее всего не придется вдаваться в эти подробности, но эти параметры помогают Nginx быстрее найти нужную информацию.
Директива proxy_chache_key задает ключ для хранения кешированных значений. Он же применяется при поиске данных в кеше. Мы используем комбинацию из схемы соединения, метода, хоста и URI.
Директива proxy_cache_valid может быть указана несколько раз. Она указывает срок хранения данных в зависимости от кода ответа. В нашем примере мы храним данные в течение 10 минут для удачных и перенаправленных ответов и всего лишь одну минуту для ответов со статусом 404.
Итак мы настроили зону кеширования, но не указали Nginx, когда именно применять кеширование.
Эта информация указывается в контексте location для бекэнд серверов:
При использовании директивы proxy_cache мы указываем, что зона backcache должна быть использована для данного контекста. Таким образом nginx перед тем как обратиться к бекэнд серверу проверит наличие ответа в кеше.
Нюансы кешированных ответов
Кеширование значительно повышает скорость работы вашего прокси-сервера. Но не стоит забывать о нескольких моментах.
No-cache : указывает, что ответ не должен отправляться до тех пор, пока сервер не проверит не изменились ли данные на бекэнд-сервере. Такое значение используется при работе с динамическими данными. Хешированные метаданные заголовка Etag проверяются при каждом запросе. Если бекэнд отдает такие же значения, то тогда данные отправляются из кеша.
No-store : в этом случае ни при каких условиях данные не должны храниться в кеше. Такой подход является самым безопасным при работе с личными данными.
private : данные не должны кешироваться в общем пространстве кеша. При таком подходе, например, браузер пользователя может кешировать данные в то время как, прокси сервер нет.
Public : данные разрешается кешировать везде.
Значение этого заголовка зависит от чувствительности данных. При правильном использовании личные данные будут в безопасности, а часто изменяемое содержимое останется актуальным.