Назад | Перейти на главную страницу

Настройка параметров IP-маршрутизации Linux - secret_interval и tcp_mem

Сегодня у нас возникла небольшая проблема переключения при отказе с одной из наших виртуальных машин HAProxy. Когда мы покопались в ней, мы обнаружили следующее:

Jan 26 07:41:45 haproxy2 kernel: [226818.070059] __ratelimit: 10 callbacks suppressed
Jan 26 07:41:45 haproxy2 kernel: [226818.070064] Out of socket memory
Jan 26 07:41:47 haproxy2 kernel: [226819.560048] Out of socket memory
Jan 26 07:41:49 haproxy2 kernel: [226822.030044] Out of socket memory

Который, на эта ссылка, по-видимому, связано с низкими настройками по умолчанию для net.ipv4.tcp_mem. Поэтому мы увеличили их в 4 раза по сравнению со значениями по умолчанию (это Ubuntu Server, не уверен, имеет ли значение вариант Linux):

current values are:    45984   61312   91968
new values are:       183936  245248  367872

После этого мы начали видеть странное сообщение об ошибке:

Jan 26 08:18:49 haproxy1 kernel: [ 2291.579726] Route hash chain too long!
Jan 26 08:18:49 haproxy1 kernel: [ 2291.579732] Adjust your secret_interval!

Тсс .. это секрет!!

Очевидно, это связано с /proc/sys/net/ipv4/route/secret_interval по умолчанию 600 и контролирует периодическая очистка кеша маршрута

В secret_interval указывает ядру, как часто удалять ВСЕ записи хэша маршрута, независимо от того, насколько они новые / старые. В нашей среде это вообще плохо. ЦП будет занят восстановлением тысяч записей в секунду каждый раз при очистке кеша. Однако мы установили его запуск один раз в день, чтобы предотвратить утечки памяти (хотя у нас их никогда не было).

Хотя мы рады уменьшить это, кажется странным рекомендовать удалять весь кеш маршрута через определенные промежутки времени, а не просто быстрее выталкивать старые значения из кеша маршрутов.

После некоторого расследования мы обнаружили /proc/sys/net/ipv4/route/gc_elasticity что кажется лучшим вариантом для контроля размера таблицы маршрутов:

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

Мы изменили эластичность с 8 до 4 в надежде на более агрессивную очистку кеша маршрутов. В secret_interval не кажется нам правильным. Но есть множество настроек, и неясно, какие из них действительно правильные.

Мы не хотим делать маршрутизацию Linux хуже, поэтому мы как бы боимся связываться с некоторыми из этих настроек.

Может ли кто-нибудь посоветовать, какие параметры маршрутизации лучше всего настроить для экземпляра HAProxy с высоким трафиком?

Никогда не сталкивался с этой проблемой. Однако вам, вероятно, следует увеличить ширину хэш-таблицы, чтобы уменьшить ее глубину. Используя "dmesg", вы увидите, сколько записей у вас сейчас:

$ dmesg | grep '^IP route'
IP route cache hash table entries: 32768 (order: 5, 131072 bytes)

Вы можете изменить это значение с помощью параметра командной строки загрузки ядра. rhash_entries. Сначала попробуйте вручную, а затем добавьте в свой lilo.conf или grub.conf.

Например: kernel vmlinux rhash_entries=131072

Возможно, у вас очень ограниченная хеш-таблица, потому что вы выделили небольшой объем памяти вашей виртуальной машине HAProxy (размер хеш-функции маршрута регулируется в зависимости от общего объема ОЗУ).

Что касается tcp_mem, быть осторожен. Ваши первоначальные настройки заставляют меня думать, что вы используете 1 ГБ ОЗУ, 1/3 из которых может быть выделена для сокетов TCP. Теперь вы выделили 367872 * 4096 байт = 1,5 ГБ ОЗУ для сокетов TCP. Вы должны быть очень осторожны, чтобы не исчерпать память. Практическое правило - выделить 1/3 памяти для HAProxy, еще 1/3 - для стека TCP и последнюю 1/3 - для остальной части системы.

Я подозреваю, что ваше сообщение "закончилась память сокета" исходит из настроек по умолчанию в tcp_rmem и tcp_wmem. По умолчанию для каждого сокета выделено 64 КБ на выходе и 87 КБ на входе. Это означает всего 300 КБ для прокси-соединения, только для буферов сокетов. Добавьте к этому 16 или 32 КБ для HAProxy, и вы увидите, что с 1 ГБ ОЗУ вы будете поддерживать только 3000 подключений.

Изменив настройки по умолчанию tcp_rmem и tcp_wmem (средний параметр), вы можете получить намного меньше памяти. Я получаю хорошие результаты с такими низкими значениями, как 4096 для буфера записи и 7300 или 16060 в tcp_rmem (5 или 11 сегментов TCP). Вы можете изменить эти настройки без перезапуска, однако они будут применяться только к новым соединениям.

Если вы предпочитаете не трогать sysctls слишком много, последняя версия HAProxy, 1.4-dev8, позволяет вам настраивать эти параметры из глобальной конфигурации и для каждой стороны (клиента или сервера).

Надеюсь, это поможет!

В Out of socket memory error часто вводит в заблуждение. В большинстве случаев на серверах с выходом в Интернет это не указать на любую проблему, связанную с нехваткой памяти. Как я объяснил более подробно в сообщение в блоге, наиболее частая причина - количество "сиротских" розеток. Сиротский сокет - это сокет, не связанный с файловым дескриптором. В определенных обстоятельствах ядро ​​выдаст Out of socket memory error даже если вы в 2 или 4 раза отошли от лимита (/proc/sys/net/ipv4/tcp_max_orphans). Это часто случается в службах с выходом в Интернет и является нормальным явлением. Правильный курс действий в этом случае - настроить tcp_max_orphans быть как минимум в 4 раза больше сирот, которых вы обычно видите с пиковым трафиком.

Не слушайте никаких советов, которые рекомендуют тюнинг tcp_mem или tcp_rmem или tcp_wmem если только ты не действительно знаю, что делаешь. Те, кто дает такие советы, обычно этого не делают. Их вуду часто не подходит для вашего окружения и не решит вашу проблему. Может быть, даже хуже.

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

net.ipv4.tcp_rmem = 4096 16777216 33554432
net.ipv4.tcp_wmem = 4096 16777216 33554432
net.ipv4.tcp_mem = 4096 16777216 33554432
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.core.netdev_max_backlog = 30000
net.core.netdev_max_backlog = 30000