У нас сегодня была небольшая проблема с отказоустойчивостью одной из наших виртуальных машин HAProxy. Когда мы в ней разобрались, то обнаружили следующее:
26 января 07:41:45 haproxy2 ядро: [226818.070059] __ratelimit: 10 обратных вызовов подавлено 26 января 07:41:45 haproxy2 ядро: [226818.070064] Недостаточно памяти сокета 26 января 07:41:47 ядро haproxy2: [226819.560048] Недостаточно памяти сокета 26 января 07:41:49 ядро haproxy2: [226822.030044] Недостаточно памяти сокета
Который, согласноэта ссылка, по-видимому, связано с низкими настройками по умолчанию для net.ipv4.tcp_mem
. Поэтому мы увеличили их в 4 раза от значений по умолчанию (это Ubuntu Server, не уверен, имеет ли значение разновидность Linux):
текущие значения: 45984 61312 91968 новые значения: 183936 245248 367872
После этого мы начали видеть странное сообщение об ошибке:
26 января 08:18:49 ядро haproxy1: [ 2291.579726] Слишком длинная цепочка хэшей маршрута! 26 января 08:18:49 ядро haproxy1: [ 2291.579732] Настройте 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
не кажется правильным. Но там куча настроек, и непонятно, какие из них действительно правильные.
- /proc/sys/net/ipv4/route/gc_elasticity (8)
- /proc/sys/net/ipv4/route/gc_interval (60)
- /proc/sys/net/ipv4/route/gc_min_interval (0)
- /proc/sys/net/ipv4/route/gc_timeout (300)
- /proc/sys/net/ipv4/route/secret_interval (600)
- /proc/sys/net/ipv4/route/gc_thresh (?)
- rhash_entries (параметр ядра, значение по умолчанию неизвестно?)
Мы не хотим делать маршрутизацию Linuxхудший, поэтому мы немного опасаемся вмешиваться в некоторые из этих настроек.
Может ли кто-нибудь посоветовать, какие параметры маршрутизации лучше всего настроить для экземпляра HAProxy с высоким трафиком?
решение1
Я никогда не сталкивался с этой проблемой. Однако вам, вероятно, следует увеличить ширину вашей хэш-таблицы, чтобы уменьшить ее глубину. Используя "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 для остальной системы.
Подозреваю, что ваше сообщение "out of socket memory" исходит из настроек по умолчанию в 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, позволяет вам настраивать эти параметры из глобальной конфигурации и на каждой стороне (клиент или сервер).
Надеюсь, это поможет!
решение2
Часто 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
если выДействительноЗнайте, что вы делаете. Те, кто дает такие советы, обычно этого не делают. Их вуду часто неправильно или не подходит для вашей среды и не решит вашу проблему. Это может даже ухудшить ее.
решение3
Мы регулярно настраиваем некоторые из этих параметров. Наш стандарт для высокопроизводительных торговых платформ с низкой задержкой:
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