#varnish #varnish-vcl
#лак #лак-vcl
Вопрос:
Мы пытаемся использовать Varnish в качестве прокси / кэша для нашего медиа-сервера. Наши потоки — это MPEG-TS (h264 / h265) через http. На этом медиа-сервере 1000 прямых трансляций, и каждый поток получает несколько подключений. Мы попытались настроить Varnish, как показано ниже, но у нас возникли следующие проблемы.
- Потоки закрываются через короткий промежуток времени
- Иногда не удается подключиться к потокам, застрял при подключении…
- Получил эти ошибки в varnislog;
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Resource temporarily unavailable
- FetchError eof socket fail
- FetchError Resource temporarily unavailable
- FetchError eof socket fail
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Could not get storage
- FetchError Resource temporarily unavailable
- FetchError eof socket fail
- FetchError Resource temporarily unavailable
- FetchError eof socket fail
- FetchError Resource temporarily unavailable
- FetchError eof socket fail
- FetchError Could not get storage
- FetchError Could not get storage
Моя конфигурация;
vcl 4.0;
import directors;
backend s6855 {
.host = "127.0.0.1";
.port = "6855";
.first_byte_timeout = 10s; # How long to wait before we receive a first byte from our backend?
.connect_timeout = 5s; # How long to wait for a backend connection?
.between_bytes_timeout = 30s; # How long to wait between bytes received from our backend?
}
backend s6866 {
.host = "127.0.0.1";
.port = "6866";
.first_byte_timeout = 10s; # How long to wait before we receive a first byte from our backend?
.connect_timeout = 5s; # How long to wait for a backend connection?
.between_bytes_timeout = 30s; # How long to wait between bytes received from our backend?
}
backend s6877 {
.host = "127.0.0.1";
.port = "6877";
.first_byte_timeout = 10s; # How long to wait before we receive a first byte from our backend?
.connect_timeout = 5s; # How long to wait for a backend connection?
.between_bytes_timeout = 30s; # How long to wait between bytes received from our backend?
}
backend s6888 {
.host = "127.0.0.1";
.port = "6888";
.first_byte_timeout = 10s; # How long to wait before we receive a first byte from our backend?
.connect_timeout = 5s; # How long to wait for a backend connection?
.between_bytes_timeout = 30s; # How long to wait between bytes received from our backend?
}
backend s6899 {
.host = "127.0.0.1";
.port = "6899";
.first_byte_timeout = 10s; # How long to wait before we receive a first byte from our backend?
.connect_timeout = 5s; # How long to wait for a backend connection?
.between_bytes_timeout = 30s; # How long to wait between bytes received from our backend?
}
sub vcl_init {
new fb = directors.round_robin();
fb.add_backend(s6855);
fb.add_backend(s6866);
fb.add_backend(s6877);
fb.add_backend(s6888);
fb.add_backend(s6899);
}
sub vcl_recv {
set req.grace = 120s;
set req.backend_hint = fb.backend();
if (req.url ~ "(.ts)" ) {
unset req.http.Range;
}
if (req.http.cookie) {
unset req.http.cookie;
}
if (req.method != "GET" amp;amp; req.method != "HEAD") {
return (pipe);
}
if (req.method == "GET" amp;amp; req.url ~ "(.ts)" ) {
unset req.http.Accept-Encoding;
return(hash);
}
return(hash);
}
sub vcl_hash {
hash_data(req.url);
return(lookup);
}
sub vcl_backend_response {
set beresp.grace = 2m;
set beresp.ttl = 120s;
set beresp.do_gunzip = false;
set beresp.do_gzip = false;
if (bereq.url ~ "(.ts)") {
set beresp.ttl = 60s;
set beresp.http.X-Cacheable = "YES";
}
else {
set beresp.ttl = 10m;
set beresp.http.X-Cacheable = "NO";
}
if ( beresp.status == 404 ) {
set beresp.ttl = 5m;
}
return(deliver);
}
sub vcl_hit {
if (obj.ttl == 0s) {
return(pass);
}
return(deliver);
}
sub vcl_miss {
}
sub vcl_deliver {
set resp.http.X-Served-By = "For Test";
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache = "MISS";
}
if(resp.http.magicmarker) {
unset resp.http.magicmarker;
set resp.http.Age="0";
}
unset resp.http.Via;
unset resp.http.X-Varnish;
}
Поскольку новичок в Varnish не уверен, как отладить проблему, ваша помощь будет оценена по достоинству.
Спасибо
Ответ №1:
Проблема, с которой вы сталкиваетесь, заключается не только в недостатке хранилища объектов, но и в том факте, что ваш самый большой HTTP-ответ больше, чем общий размер хранилища объектов.
Это означает, что Varnish не может LRU освободить требуемое пространство для размещения объекта в кэше.
Could not get storage
это ошибка, которая обычно возвращается, когда это происходит.
Проверьте размеры
Важно выяснить, насколько велик ваш кэш и каков размер объекта, который у вас выходит из строя.
Ваши varnishd
настройки среды выполнения укажут вам, насколько велика ваша объектная память. -s malloc,<size>
Содержит это значение.
Вы также можете использовать varnishstat
для проверки размера и использования вашего кэша памяти и временного хранилища:
varnishstat -f SMA.*.g* -f MAIN.n_lru_nuked
MAIN.n_lru_nuked
Счетчик, который также включен в эту команду, покажет, сколько объектов, которые Varnish принудительно удаляет из кэша, чтобы освободить место для новых объектов.
Устранение проблемы
Самый простой способ устранить проблему — назначить больше памяти для Varnish via -s malloc,<size>
. Не забудьте перезапустить Varnish после изменения этих настроек.
После этого следующая команда поможет вам определить, достаточно ли места для хранения, и если Varnish все еще необходимо принудительно удалять объекты из кэша, освободите место:
varnishstat -f SMA.*.g* -f MAIN.n_lru_nuked
Более устойчивый план
Другой план состоит в том, чтобы полагаться на механизм массивного хранилища (MSE). Это механизм хранения, который является частью Varnish Enterprise.
Он сочетает в себе память и дисковое хранилище и оптимизирован для обработки больших объемов данных. Он позволяет избежать фрагментации и спроектирован так, чтобы не страдать от типичной задержки доступа к диску.
Существуют официальные образы компьютеров для AWS, Azure и Google Cloud, которые позволяют экспериментировать с этим механизмом хранения данных без предварительной покупки лицензии.
Убийственная функция MSE — это регулятор памяти. Это механизм, который динамически определяет размер хранилища памяти ваших кэшей на основе потребностей запросов и ответов.
Если вам не хватает памяти, а для обработки потоков требуется не так много памяти, регулятор памяти автоматически выделит больше памяти механизму хранения.
Если вы используете уровень сохраняемости MSE, вы можете размещать террабайты данных на одной машине, не сталкиваясь с этими проблемами.
В Varnish Software, компании, которая создает Varnish Enterprise, мы рассматриваем MSE как основную функцию, которую компании потокового видео OTT используют для ускорения доставки видео.
Что, если моя оценка совершенно неверна
Хотя Could not get storage
ошибка обычно появляется, когда Varnish пытается сохранить огромные объекты в кэше, когда размер кэша слишком мал, я также могу ошибаться.
В этом случае я бы посоветовал вам запустить varnishlog
и просмотреть полную трассировку того, что происходит в этой конкретной транзакции:
varnishlog -g request -q "ReqUrl eq '/my-url'"
В этом примере отображаются все детали запросов на /my-url
. Пожалуйста, измените это на URL, который вы пытаетесь отслеживать.
Выходные данные обычно дают вам лучшее представление о том, как ведет себя Varnish. Это может помочь нам выяснить, как устранить проблему, если моя первоначальная оценка была неверной.
Комментарии:
1. Большое вам спасибо за ваш ответ на этот вопрос. Я подозреваю, что мои настройки времени ttl и грации специально. Я не понимаю, почему мои объекты не исчезают в кэше и не обновляются своевременно. Поскольку файл в данном случае представляет собой поток mpegts, который имеет непрерывную транзакцию данных, которая будет расти / течь бесконечно, в какой-то момент varnish должен проанализировать часть и обслужить ее, а затем до времени ttl, я думаю, должны быть свежие данные для обслуживания. MSE на самом деле наше лекарство для этого проекта, но, к сожалению, у нас нет возможности использовать его в данный момент. Мой файл systemd pastebin.com/tT3X50Cz . 32 ГБ оперативной памяти / 32C процессор
2. @Talion Я хотел бы видеть значение
n_lru_limited
счетчика приvarnishstat
возникновении ошибки. Ошибки указывают на то, что Varnish не удалось освободить хранилище.