У меня есть система, обращающаяся к ряду серверных служб через четыре кэша лака с балансировкой нагрузки. Примерно 0,1% запросов усекается, поскольку varnish возвращает заголовок неверной длины содержимого. Эта ошибка возникает во всех кешах и различных серверных модулях.
Varnish настроен так, чтобы ничего не кэшировать без допустимых заголовков управления кешем, и эти конкретные запросы не кэшируются. Клиент не отправляет заголовок Accept-Encoding, поэтому Varnish запрашивает ответ в формате gzip с серверной части и отправляет клиенту несжатую версию.
В журнале varnishlog все запросы к серверу выглядят одинаково:
BerespStatus 200
BerespReason OK
BerespHeader Content-Encoding: gzip
BerespHeader Content-Length: 1001
BerespHeader Content-Type: application/json
BerespHeader Date: Fri, 08 Feb 2019 14:59:06 GMT
BerespHeader Vary: Accept-Encoding
TTL RFC 0 10 0 1549637947 1549637947 1549637946 0 0 cacheable
VCL_call BACKEND_RESPONSE
TTL VCL 120 10 0 1549637947 cacheable
TTL VCL 120 10 0 1549637947 uncacheable
VCL_return deliver
Filters testgunzip
Storage malloc Transient
Fetch_Body 3 length stream
Gzip u F - 1001 3792 80 7906 7944
BackendReuse 54 default
Length 1001
Я считаю, что линия Gzip u F - 1001 3792 80 7906 7944
заявляет, что заархивированный ответ размером 1001 байт не сжимается до 3792 байта.
Есть три разных типа ответа. Около 50% установили длину содержимого 3792:
VCL_call RECV
ReqHeader Surrogate-Capability: key=ESI/1.0
VCL_return hash
VCL_call HASH
VCL_return lookup
HitMiss 1052359 119.885211
VCL_call MISS
VCL_return fetch
Link bereq 1052362 fetch
Timestamp Fetch: 1549633459.720553 0.004765 0.004765
RespProtocol HTTP/1.1
RespStatus 200
RespReason OK
RespHeader Content-Encoding: gzip
RespHeader Content-Length: 1000
RespHeader Content-Type: application/json
RespHeader Date: Fri, 08 Feb 2019 13:44:19 GMT
RespHeader Vary: Accept-Encoding
RespHeader Age: 0
RespHeader Via: 1.1 varnish (Varnish/6.1)
VCL_call DELIVER
RespHeader X-Cache: MISS
RespHeader X-Cache-Hits: 0
VCL_return deliver
Timestamp Process: 1549633459.720567 0.004779 0.000014
RespUnset Content-Encoding: gzip
RespHeader Accept-Ranges: bytes
RespUnset Content-Length: 1000
RespHeader Content-Length: 3792
Gzip U D - 1001 3792 80 7906 7944
Около 50% без заголовка длины содержимого, но с фрагментированным кодированием передачи:
Same as above except
...
RespUnset Content-Length: 1000
RespHeader Transfer-Encoding: chunked
Gzip U D - 1001 3792 80 7906 7944
И 0,1%, которые ломают клиента из-за неправильной длины содержимого:
...
RespUnset Content-Length: 1001
RespHeader Content-Length: 208
Gzip U D - 1001 3792 80 7906 7944
Есть ли у кого-нибудь мысли относительно причины этого? Есть предложения по следующему шагу отладки?
Мой VCL ничего не делает с заголовками длины содержимого. Я использую varnish 6.1 (я собираюсь перейти на стабильную версию 6.0.2, но еще не пробовал)
РЕДАКТИРОВАТЬ:
Снижен до 6.0.2, но проблема все еще остается.
РЕДАКТИРОВАТЬ 2:
Я отключил varnish от обновления запроса до gzip с помощью переключателя команд -p "http_gzip_support=off"
и это устранило проблему за счет того, что не заархивированные запросы все еще не заархивировались, когда они попадают в бэкэнд, но на данный момент этого достаточно.