Плохо сбалансированный сокет принимает ядро Linux 3.2 против ядра 2.6
Я запускаю довольно крупномасштабное приложение Node.js 0.8.8 с использованием Cluster с 16 рабочими процессами на 16-процессорной коробке с гиперпоточностью (таким образом, 32 логических ядра). Мы обнаруживаем, что после перехода на ядро Linux 3.2.0 (с 2.6.32) балансировка входящих запросов между рабочими дочерними процессами кажется сильно взвешенной до 5 или около того процессов, а остальные 11 вообще не выполняют большой работы. Это может быть более эффективным для пропускной способности, но, по-видимому, увеличивает задержку запросов и не является оптимальным для нас, потому что многие из них являются долгоживущими соединениями веб-сокетов, которые могут начать выполнять работу одновременно.
Все дочерние процессы принимают на сокете (используя epoll), и хотя эта проблема исправлена в узле 0.9 (https://github.com/bnoordhuis/libuv/commit/be2a2176ce25d6a4190b10acd1de9fd53f7a6275), это исправление, похоже, не помогает наши тесты. Кто-нибудь знает о параметрах настройки ядра или опциях сборки, которые могут помочь, или нам лучше вернуться к ядру 2.6 или распределить нагрузку между рабочими процессами, используя другой подход?
Мы свели его к простому тесту HTTP Siege, хотя учтите, что он выполняется с 12 процессорами на 12-ядерном блоке с гиперпоточностью (то есть 24 логических ядра) и с 12 рабочими процессами, принимающими на сокете, в отличие от наших 16 ПРОЦЫ в производстве.
HTTP Siege с Node 0.9.3 на Debian Squeeze с ядром 2.6.32 на голом железе:
reqs pid
146 2818
139 2820
211 2821
306 2823
129 2825
166 2827
138 2829
134 2831
227 2833
134 2835
129 2837
138 2838
То же самое, кроме ядра 3.2.0:
reqs pid
99 3207
186 3209
42 3210
131 3212
34 3214
53 3216
39 3218
54 3220
33 3222
931 3224
345 3226
312 3228
1 ответ
Не полагайтесь на множественное принятие сокетов ОС для балансировки нагрузки между процессами веб-сервера.
Поведение ядер Linux здесь отличается от версии к версии, и мы увидели особенно несбалансированное поведение с ядром 3.2, которое в более поздних версиях оказалось несколько более сбалансированным. например, 3.6.
Мы работали в предположении, что должен быть способ заставить Linux делать что-то вроде циклического перебора, но с этим было множество проблем, в том числе:
- Ядро Linux 2.6 показало что-то вроде поведения циклического перебора на голом металле (дисбалансы были около 3-к-1), ядро Linux 3.2 - нет (дисбалансы 10-к-1), и ядро 3.6.10 снова казалось нормальным Мы не пытались делить пополам на фактические изменения.
- Независимо от используемой версии ядра или параметров сборки поведение, которое мы наблюдали на экземпляре HVM с 32 логическими ядрами в веб-сервисах Amazon, было строго ориентировано на один процесс; могут возникнуть проблемы с принятием сокета Xen: https://serverfault.com/questions/272483/why-is-tcp-accept-performance-so-bad-under-xen
Вы можете увидеть наши тесты очень подробно по проблеме github, которую мы использовали, чтобы переписываться с отличной командой Node.js, начиная примерно здесь: https://github.com/joyent/node/issues/3241
Этот разговор заканчивается тем, что команда Node.js указывает, что они серьезно рассматривают возможность реализации явного циклического перебора в Cluster, и начинает проблему для этого: https://github.com/joyent/node/issues/4435, а также с Trello. команда (это мы) перешла к нашему плану восстановления, который заключался в использовании локального процесса HAProxy для прокси через 16 портов на каждом сервере с экземпляром кластера с двумя рабочими процессами, работающим на каждом порту (для быстрого переключения при сбое на уровне принятия в случае сбоя или зависания процесса). Этот план работает прекрасно, с значительно меньшими изменениями в задержке запросов и более низкой средней задержкой.
Здесь можно сказать намного больше, и я НЕ предпринял шагов по рассылке списка рассылки ядра Linux, так как было неясно, действительно ли это проблема ядра Xen или Linux или просто неверное ожидание множественного принятия поведение с нашей стороны.
Я хотел бы получить ответ от эксперта по множественному принятию, но мы возвращаемся к тому, что мы можем построить, используя компоненты, которые мы понимаем лучше. Если кто-нибудь напишет лучший ответ, я был бы рад принять его вместо моего.