конфликт блоков nginx x-accel

X-Accel-Redirect, похоже, не соблюдает правила и прецеденты конфигурации блоков nginx.
рассмотрим этот пример:

server {
...
limit_conn limitedIP 10;

location ^~ /files/ {
internal
alias /var/www/files/;
limit_conn limitedIP 20;
}

location ~ \.php$ {
...
limit_conn limitedIP 30;
}
}

Если я обращаюсь к / файлам напрямую (при удалении внутреннего курса), используется правило limit_conn 20, что нормально.

но если я использую X-Accel-Redirect в php-скрипте для / files, то используется правило limit_conn 30. даже если я удаляю эту строку из блока местоположения php, используется правило limit_conn 10 из блока сервера, что очень странно. наконец, если я удаляю limit_conn 10 из серверного блока, используется правило limit_conn 20, которое я ожидал сначала.

Я проверил это на nginx версии 1.6.2.

limit_conn — просто пример, и несколько директив ведут себя так. есть идеи?

1

Решение

Так работают модули limit_conn и limit_req. Эти модули имеют дело с соединениями между пользователями и сервером, и поскольку внутренние перенаправления не открывают какие-либо новые такие соединения, Nginx проверяет ограничения только один раз на запрос и не считает необходимым проверять их снова.

В вашем примере запрос пользователя сначала совпадает со вторым местоположением, которое запускает вызов обработчика limit_conn для первого вызова. Вот почему используется правило limit_conn 30. Обработчик будет вызван второй раз после внутреннего перенаправления, но он почти сразу завершит свою работу, ничего не проверяя (вернуть NGX_DECLINED).

Если вы прокомментируете правило limit_conn 30 во втором расположении, правило limit_conn 10 будет унаследовано от контекста сервера, что является совершенно нормальным поведением для Nginx. В этом случае опять-таки сначала будет вызван обработчик limit_conn для основного запроса, а следующий вызов (после внутреннего перенаправления) ничего не сделает.

Наконец, когда вы комментируете все строки limit_conn за исключением правила limit_conn 20, обработчик limit_conn сначала будет вызываться после внутреннего перенаправления, и, таким образом, это правило в конечном итоге будет использовано.

ОБНОВИТЬ:

Поскольку правило limit_conn проверяется при установлении нового соединения, открытие нового соединения решит вашу проблему. Концептуально конфигурация будет выглядеть так:

limit_conn_zone $binary_remote_addr zone=limitedIP:10m;

server {
# You can use any random unused non-system port
listen 127.0.0.1:8889;
server_name internal.server;

set_real_ip_from  127.0.0.1/32;
real_ip_header    X-Forwarded-For;

location ^~ /files/ {
limit_conn limitedIP 20;
alias /var/www/files/;
}
}

server {
...

location ^~ /files/ {
internal;
proxy_set_header Host "internal.server";
proxy_set_header X-Forwarded-For $remote_addr;

# Make sure you specify the same port as above
proxy_pass http://127.0.0.1:8889;
}

location ~ \.php$ {
...
limit_conn limitedIP 30;
}
}

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

К сожалению, я не могу представить какой-либо другой способ решить проблему только с Nginx.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]