У меня есть простая конфигурация nginx для /info
расположение.
location /info {
uwsgi_read_timeout 20s;
uwsgi_send_timeout 20s;
uwsgi_pass unix:///tmp/uwsgi.sock;
include uwsgi_params;
}
Это место необходимо кэшировать. Я добавил
proxy_cache info_cache;
proxy_cache_valid 200 10m;
к этой конфигурации. Работало нормально.
Через некоторое время мы поняли, что старые глючные клиенты нашего приложения отправляют заголовок If-None-Match
, и доставки nginx 304 Not Modified
как и ожидалось. Проблема в том, что эти клиенты ждут 200 OK
плюс тело ответа. К сожалению, мы не можем исправить их все.
Можно ли игнорировать nginx If-None-Match
и до сих пор из кеша доставляешь?
После нескольких тестов, даже если сбросить значение заголовка, proxy_set_header If-None-Match "";
, если контент поступает из кеша, nginx проверяет If-None-Match
. Вспоминая это из прокси, а не статично.
Вы пробовали изменить http://nginx.org/r/if_modified_since по умолчанию exact
к off
?
if_modified_since off;
Основываясь на моем прочтении src/http/modules/ngx_http_not_modified_filter_module.c
:: ngx_http_not_modified_header_filter()
:
Если заголовок If-Modified-Since
присутствует (и не пусто), а if_modified_since
директива установлена на off
(будучи NGX_HTTP_IMS_OFF
define
в исходном коде), то ngx_http_test_if_modified()
немедленно возвращает истину, что приводит к короткому замыканию фильтра с return ngx_http_next_header_filter(r)
; другими словами, в таком случае If-None-Match
логика не будет выполняться.
Обратите внимание, что это происходит, только если If-Modified-Since
заголовок действительно присутствует (и непустой) в запросе (в дополнение к If-None-Match
что вы имеете дело), в противном случае путь кода будет продолжаться без NGX_HTTP_IMS_OFF
установка, имеющая какой-либо эффект; Я думаю, здесь ожидается, что если клиенты уже включают If-None-Match
, затем If-Modified-Since
вероятно также включен; таким образом, похоже, нет отдельной опции для отключения обработки If-None-Match
конкретно и индивидуально.
78 if (r->headers_in.if_modified_since || r->headers_in.if_none_match) {
79
80 if (r->headers_in.if_modified_since
81 && ngx_http_test_if_modified(r))
82 {
83 return ngx_http_next_header_filter(r);
84 }
85
86 if (r->headers_in.if_none_match
87 && !ngx_http_test_if_match(r, r->headers_in.if_none_match))
88 {
89 return ngx_http_next_header_filter(r);
90 }
…
132ngx_http_test_if_modified(ngx_http_request_t *r)
133{
…
139 if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) {
140 return 1;
141 }
Обратите внимание, что ETag
поддержку вместе с If-None-Match
, доступно только в stable-1.4
и выше (отсутствует в stable-1.2
и ниже), поэтому возможен вариант с более ранней версией.
Вы пробовали очистить ETag
перед клиентом?
Ваши клиенты отправляют If-None-Match: *
? Если да, то согласно https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26, не выполнение действия GET будет правильным (например, возврат 304 Not Modified
совершенно правильно), и это именно то, что делает nginx, что можно легко проверить, запустив что-то вроде curl -H"If-None-Match: *" -v localhost:80
при установке по умолчанию с nginx / 1.15.9 (обратите внимание, что stable-1.2
не имеет ETag
или If-None-Match
поддержка, как они впервые появились с stable-1.4
).
Если нет, вы можете попробовать опустить ETag
в ваших ответах, чтобы обмануть клиентов, чтобы они не отправляли If-None-Match
.
Ты можешь использовать http://nginx.org/r/add_header очистить ETag
заголовок из ответов клиентам:
add_header ETag "";
Кстати, я также пробовал изменить $http_if_none_match
непосредственно с http://nginx.org/r/set, но эффекта не было.
В качестве последнего средства, если лучшее решение недоступно (хотя я думаю, что вышеперечисленные решения также могут сработать), вы можете поставить еще один экземпляр nginx перед обычным кеширующим nginx специально для этих глючных клиентов. В этом новом экземпляре nginx вы должны отключить все виды кеширования, удалить заголовок, который неправильно обрабатывается вашими ошибочными клиентскими приложениями, и передать запрос обычному экземпляру nginx, который выполняет кеширование.
В частности, вы можете убедиться, что этот новый экземпляр также не будет выполнять буферизацию, http://nginx.org/r/proxy_bufferingв противном случае вы рискуете снизить производительность из-за дополнительного шага повторного сохранения материала на диск с помощью дополнительного экземпляра; в противном случае все это должно быть скопировано в память и, вероятно, будет достаточно быстрым.
Я думаю, что этот подход определенно должен сработать, потому что у этого переднего nginx не было бы кеша, поэтому он не мог ответить с 304 Not Modified
, тогда как серверный nginx не получит If-None-Match
если вы очистите If-None-Match
на веб-интерфейсе nginx с http://nginx.org/r/proxy_set_header прежде чем делать http://nginx.org/r/proxy_pass на бэкэнд nginx.
P.S. Другой ответ предлагает использовать http://nginx.org/r/proxy_ignore_headers, но, основываясь на документации вокруг него, а также вокруг http://nginx.org/r/proxy_set_header, это не похоже на окропление If-None-Match
должно иметь значение; плюс, похоже, нет _set_header
вариант для uwsgi
в любом случае.
P.P.S. Другой потенциальный путь, если вам на самом деле не нужно доставлять вещи из кеша, - это изменение http://nginx.org/r/uwsgi_cache_revalidate по умолчанию off
к on
; однако я думаю, что это тоже будет зависеть от _set_header
, который отсутствует в uwsgi
версия.