LINUX.ORG.RU

Запись потока данных на диск

 , ,


0

1

Понадобилось записать реальный трафик (до 500Mbit/s) на диск (tcpdump-ом и/или dumpcap). Все хорошо, но они сообщают о значительных дропах (packets dropped by kernel) и это при записи на отдельный раздел на ssd.

После небольшой модификации tcpdump выяснилось, что дропы приходят пачками, а не по одиночке. Промежуток между массовыми дропами 2-5 минут.

Параллельно запущеный vmstat показал, что запись на диск происходит изредко, но большого объема и как раз в эти моменты появлялись массовые дропы.

sysctl vm.dirty_background_ratio=1
sysctl vm.dirty_ratio=5
sysctl vm.dirty_writeback_centisecs=500
sysctl vm.dirty_expire_centisecs=1500
sysctl vm.dirtytime_expire_seconds=3000

позволило записать 10 минутный фрагмент трафика без потерь

Есть ли алгоритм подбора этих параметров под конкретную дисковую подсистему?

Нет ли возможности задать эти параметры для конкретного раздела (ФС)?

★★★★★

Попробуй сжать чем-нибудь через pipe. Это и буфер создаст и нагрузку на диск снизит.

А вообще период сброса надо уменьшать, а не увеличивать. На 10 минутах небось потери были выше? А так есть шанс, что при некотором периоде сброса (маленьком) влиять перестанет.

anonymous
()
Ответ на: комментарий от anonymous

Кстати посмотри настройки tcpdump. Он же не из вежливости уступает диску - скорее всего у него буферы переполняются. Намути 100500 гигов буфер, если есть такая настройка (или прям в коде сделай).

anonymous
()
Ответ на: комментарий от anonymous

Сжимать реалтаймово 500мбит - не думаю, что это разумная идея. 50Мбайт/с на диск пишется без проблем.

Временные интервалы я уменьшил:

vm.dirtytime_expire_seconds=3000 уменьшен с 42000

vm.dirty_expire_centisecs=1500 уменьшен с 3000

Непонятно сколько страниц за раз пишет ядро.

vel ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Буфер на чтения был добавлен в первую очередь, чтоб мелкие паузы не дропали пакеты.

tcpdump пришлось править чтобы буферизация работала совместно с "-C"

Но все равно этого не хватало для компенсации паузы при сбросе 200Мб кеша.

vel ★★★★★
() автор топика
Ответ на: комментарий от post-factum

пайпа не подходит - пишу поток кусками по 1Гб. tcpdump умеет это.

А c O_DIRECT для write() будет работать writeback cache ?

Я уже подправил tcpdump c явным выполнение setbuffer() при создании файла, т.ч. если верить strace, мой tcpdump выполняет write() на полный размер заданного буфера. Добавить O_DIRECT при открытии файла - не сложно.

Если бы была возможность сделать fdatasync() неблокируемым, то поблема была бы решена.

vel ★★★★★
() автор топика
Ответ на: комментарий от anonymous

отмирроренный трафик с коммутатора либо он же, но пропущенный через iptables/nflog и уже с метками.

vel ★★★★★
() автор топика

Ои дисковой подсистемы практически не реально добится плавной работы без просадок, в вашем случае нужно разводить по тредам / процессам захват пакетов и запись на винт с большим не блокирующим буфером между ними (достаточным для хранения хотябы 20 секунд потока).

По поводу зипования 500MBit/sec - это вообще не проблема если есть много ядер, есть pigz - он отлично паралелится на 4-5 ядрах он и 1GBit/sec жать будет без проблем.

zaz ★★★★
()
Ответ на: комментарий от zaz

Ои дисковой подсистемы практически не реально добится плавной работы без просадок.

с указанными sysctl - результат почти приемлемый.

запуск vmstat -n 2 показывает достаточно равномерный поток 45-55 мбайт/с, изредко подскакивает до 100 с последующим провалом.

Все это нужно не для продакшена, а для тестирования и отладки проекта nDPI. Нужен кусок реального трафика длительнойстью 10-20 минут. В виде одного огромного файла - оно крайне неудобно. tcpdump пишущий пачку файлов по 1-2Гб - наиболее удобное решение проблемы.

vel ★★★★★
() автор топика
Последнее исправление: vel (всего исправлений: 1)
Ответ на: комментарий от vel

с указанными sysctl - результат почти приемлемый.

Ну «почти» дело такое, но любое решение дающее желаемый результат является «хорошим» :)

tcpdump пишущий пачку файлов по 1-2Гб

Я бы данную проблему решал через LD_PRELOAD и named pipe/unix socket. Запускал бы оригинальный tcpdump без модификаторов но со своим SO в LD_PRELOAD который бы перекрывал open/create для tcpdump. И вместо создания файла куда tcpdump слаживает пакеты делал connect к unxi socket и возвращал уже сконекшеный дескриптор. На другом конце сокета запустил бы свой процесс который асинхронна вычитывал поток (возможно зиповал) и асинхронно сбрасывал на винт.

Ну или как вариант взял бы на «посмотреть» какойто апаратный рейд который дает 5GBit/sec при записи

zaz ★★★★
()

После ряда экспериментов выяснилось, что для равномерной записи на диск потока N Mbytes/s X можно задать от N до N*2

X=$[$X*1000000]
sysctl vm.dirty_background_bytes=$X
sysctl vm.dirty_bytes=$X
sysctl vm.dirty_writeback_centisecs=500
sysctl vm.dirty_expire_centisecs=1500
sysctl vm.dirtytime_expire_seconds=3000
vel ★★★★★
() автор топика
Ответ на: комментарий от legolegs

я так и не смог понять про соотношение dirty_background_bytes/dirty_bytes

А какие есть соображения на эту тему ?

vel ★★★★★
() автор топика
Ответ на: комментарий от vel

Один - нижняя граница, пока столько ожидающих данных не накопится (или тайм-аут не выйдет) Линукс не почешется, другой - верхняя граница, если данных пишется больше - приложение заблокируется на write. Но я не настоящий ядерный сварщик.

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

Тогда vm.dirty_ratio нужно сделать больше чем vm.dirty_background_bytes

Но вот на сколько ? В разы больше или на 10-50% ?

vel ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.