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

30

Сегодня у нас была небольшая проблема с отказоустойчивостью на одной из наших виртуальных машин 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 с высоким трафиком?

Джефф Этвуд
источник

Ответы:

28

Я никогда не сталкивался с этой проблемой. Однако вам, вероятно, следует увеличить ширину хеш-таблицы, чтобы уменьшить ее глубину. Используя «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 socket» приходит из настроек по умолчанию в tcp_rmemи tcp_wmem. По умолчанию для каждого сокета выделено 64 КБ, а для входа - 87 КБ. Это означает всего 300 кБ для прокси-соединения, только для буферов сокетов. Добавьте к этому 16 или 32 кБ для HAProxy, и вы увидите, что с 1 ГБ ОЗУ вы будете поддерживать только 3000 соединений.

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

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

Я надеюсь, что это поможет!

Вилли Тарро
источник
8

Это 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если вы действительно не знаете , что вы делаете. Те, кто раздает эти советы, обычно этого не делают. Их вуду часто неправильно или не подходит для вашей среды и не решит вашу проблему. Это может даже сделать хуже.

Тсуна
источник
1
Когда это происходит, сообщение dmesg отличается, вы видите «слишком много потерянных сокетов». Однако я согласен с вами, что сироты могут потреблять огромное количество памяти.
Вилли Тарро
Когда вы превысите число, у /proc/sys/net/ipv4/tcp_max_orphansвас возникнет другая ошибка. Например, весь стек Stack Exchange имеет значение /proc/sys/net/ipv4/tcp_max_orphans65536 и /proc/net/sockstatприводит к TCP: inuse 2996 orphan 171 tw 15972 alloc 2998 mem 1621 - разницу, которую нельзя игнорировать.
Джефф Далгас
-4

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

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
Скотт Алан Миллер
источник
1
согласно математике Вилли, это означает, что стандартное давление памяти # (среднее число) составляет 68 ГБ ?! Раз три (rmem, wmem, mem) ??
Джефф Этвуд
10
Эти настраиваемые параметры неверны и очень часто встречаются в рабочей среде, а затем слепо копируются. У них не будет проблем с несколькими одновременными сеансами, но даже при 100 сокетах TCP вы выделите 3,2 ГБ ОЗУ. Пока задержка низкая, вы не заметите ничего подозрительного. Вам просто нужно отключить удаленный компьютер во время передачи, чтобы увидеть заполнение выходных буферов, или заморозить локальную задачу и увидеть заполнение входного буфера. Это безумие ...
Вилли Тарро
6
Джефф, это не раз три. tcp_mem находится на страницах и определяет глобальный размер. tcp_rmem и tcp_wmem находятся в байтах и ​​определяют размер для каждого сокета.
Вилли Тарро
Эти настраиваемые параметры выглядят неправильно, для одновременных серверов с небольшими данными вы не хотите резервировать столько буферов сокетов, а tcp_mem полностью отличается от r / wmem, использование одинаковых чисел на самом деле не имеет смысла (один - байты на Соединения, другой - страниц в системе)
Экес