node.js, mongodb, redis, погіршення продуктивності ubuntu у виробництві, оперативна пам'ять безкоштовна, процесор 100%


11

Як випливає з назви запитання, мені важко зрозуміти, що можна покращити в моєму додатку (або налаштованому на ОС, ubuntu) для досягнення прийнятної продуктивності. Але спочатку я поясню архітектуру:

Передній сервер - це 8-ядерна машина з 8 гігами оперативної пам’яті під керуванням Ubuntu 12.04. Додаток написано повністю у javascript та працює у node.js v 0.8.22 (оскільки деякі модулі, схоже, скаржаться на новіші версії вузла), я використовую nginx 1.4 для проксі-трафіку http від порту 80 та 443 до 8 працівників вузлів, якими керує і почав використовувати вузол кластера api. Я використовую останню версію socket.io 0.9.14, щоб обробляти з'єднання веб-сокетів, в яких я ввімкнув лише веб-розетки та xhr-опитування як доступні транспортні засоби. На цій машині я також запускаю екземпляр Redis (2.2)

Я зберігаю стійкі дані (наприклад, користувачі та результати) на другому сервері в mongodb (3.6) з 4gigs ОЗУ та 2 ядрами.

Додаток виробляється з декількох місяців (він працював на одній коробці до декількох тижнів тому) і ним користуються близько 18 тисяч користувачів на день. Це завжди добре працювало, окрім одного головного питання: зниження рівня продуктивності. З використанням кількість процесорів, використовуваних кожним процесом, зростає, поки він не встановить статут працівника (який більше не подаватиме запити). Я тимчасово вирішив це, перевіряючи процесор, який використовує кожен працівник щохвилини, і перезапускати його, якщо він досягає 98%. Тому тут проблема в основному процесорі, а не оперативній пам'яті. Оперативна пам’ять вже не є проблемою, оскільки я оновив до socket.io 0.9.14 (у попередній версії просочувалася пам'ять), тому я сумніваюся, що це проблема витоку пам'яті, тим більше, що зараз це процесор, який досить швидко зростає ( Я повинен перезапустити кожного працівника приблизно 10-12 разів на день!). Оперативна пам’ять, яка використовується, також зростає, якщо чесно, але дуже повільно, 1 концерт кожні 2-3 дні використання, і дивно, що він не виходить, навіть коли я повністю перезавантажую всю програму. Він випускається, лише якщо я перезавантажую сервер! цього я насправді не можу зрозуміти ...

Зараз я виявив nodefly, що дивовижно, тому я нарешті можу побачити, що відбувається на моєму виробничому сервері, і я збираю дані вже через пару днів. Якщо хтось хоче бачити діаграми, я можу надати вам доступ, але в основному я бачу, що у мене між 80 і 200 одночасними з'єднаннями! Я очікував, що node.js обробить тисячі, а не сотні запитів. Також середній час відгуку для http-трафіку коливається між 500 і 1500 мілісекундами, що, на мою думку, дійсно багато. Крім того, в цей самий момент з 1300 користувачами в Інтернеті це вихід "ss -s":

Total: 5013 (kernel 5533)
TCP:   8047 (estab 4788, closed 3097, orphaned 139, synrecv 0, timewait 3097/0), ports 0

Transport Total     IP        IPv6
*         5533      -         -
RAW       0         0         0
UDP       0         0         0
TCP       4950      4948      2
INET      4950      4948      2
FRAG      0         0         0

що свідчить про те, що у мене дуже багато закритих зв’язків за часом. Я збільшив максимально відкриті файли до 999999, ось вихід ulimit -a:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 63724
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 999999
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 63724
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Тому я подумав, що проблема може полягати в http-трафіку, який з певних причин насичує наявні порти / сокети (?), Але одне не має для мене сенсу: чому коли я перезавантажую робітників, і всі клієнти знову підключаються протягом декількох секунд, навантаження на центральний процесор працівника знижується до 1% і здатна належним чином обслуговувати запити, поки воно не насититься приблизно через 1 годину (у піковий час)?

Я в основному javascript-програміст, а не адміністратор sys, тому я не знаю, скільки навантажень я повинен очікувати для роботи зі своїми серверами, але, безумовно, він не працює так, як слід. Додаток є стабільним інакше, і ця остання проблема заважає мені відправляти готові мобільні версії програми, оскільки, очевидно, вони принесуть більше навантаження і, врешті-решт, завершать роботу всього!

Сподіваюсь, є щось очевидне, що я роблю неправильно, і хтось допоможе це помітити ... сміливо запитайте мене за додатковою інформацією, і мені шкода за тривалість питання, але це було потрібно, я вірю ... Спасибі заздалегідь!


Чи є спосіб отримати щось на кшталт дампа потоку з node.js? Напевно, є кілька ниток у нескінченній петлі. Також для чого насправді використовується процесор? Що ви бачите, topколи використання процесора близько 100%?
rvs

CPU повністю використовується nodejs, коли я запускаю верх, я бачу, як вузлові процеси приймають усі процесори. Не впевнений, як я можу вивести дамп потоку з вузла, щоб бути чесним ...
Franjanko

Інша річ, що більша частина процесорного часу, здається, йде в систему, а не в користувацький час
Franjanko

Хтось принаймні знає, скільки одночасних з'єднань я маю змогу обробляти із серверами, які у мене є? на даний момент я підтримую 200 одночасних з'єднань макс. Це допоможе мені оцінити, наскільки я далекий від оптимальної конфігурації ... дякую.
Фран’янко

Відповіді:


10

Після кількох днів напружених випробувань та помилок я радий сказати, що зрозумів, де знаходиться вузьке місце, і опублікую його тут, щоб інші люди могли отримати користь від моїх висновків.

Проблема полягає в підключеннях pub / sub, якими я користувався з socket.io, і зокрема в RedisStore, який використовує socket.io для обробки міжпроцесорного зв’язку екземплярів сокета.

Зрозумівши, що я можу легко реалізувати свою власну версію pub / sub, використовуючи redis, я вирішив спробувати її і вилучив redisStore з socket.io, залишивши його в сховищі пам'яті за замовчуванням (мені не потрібно транслювати на всі підключені клієнти, але лише між двома різними користувачами, підключеними, можливо, в різних процесах)

Спочатку я оголосив лише 2 глобальних Redis-з'єднання x для обробки pub / sub на кожному підключеному клієнті, і додаток використовував менше ресурсів, але на мене все ще впливало постійне зростання використання процесора, тому мало що змінилося. Але тоді я вирішив спробувати створити 2 нових підключення до redis, щоб кожен клієнт обробляв їх паб / підпорядкування лише на своїх сесіях, а потім закрив з'єднання, коли користувач відключився. Потім після одного дня використання у виробництві процесор все ще знаходився на рівні 0-5% ... бінго! жоден процес не перезапускається, немає помилок, з продуктивністю, яку я очікував. Тепер я можу сказати, що node.js гойдається і я радий обрати його для створення цього додатка.

На щастя, redis був розроблений для обробки багатьох одночасних з'єднань (інакше по mongo), і за замовчуванням він встановлений у 10k, що залишає місце для близько 5k одночасних користувачів, на одному екземплярі redis, що для мене зараз достатньо, але я ' я читав, що його можна підключити до одночасних підключень 64k, тому ця архітектура повинна бути достатньо міцною, я вважаю.

У цей момент я думав здійснити якийсь пул з'єднань для того, щоб переробити його, трохи оптимізувати його, але не впевнений, чи це не призведе до того, що події pub / sub породжуватимуться на з'єднаннях, якщо кожен з них не буде щоразу руйнується та відтворюється для їх очищення.

У будь-якому випадку, дякую за ваші відповіді, і мені буде цікаво дізнатися, що ви думаєте, і якщо у вас є якісь інші пропозиції.

Ура.


2
У мене з’являється та сама проблема в моєму виробничому додатку, що також є новим для ролі адміністратора сервера. Я стежу за тим, що ви робили в концепції, але у мене є питання, як це зробити - можливо, ви могли б надати посилання на якийсь ресурс у прийнятій відповіді? Або просто надати більше інформації? Зокрема, про "Але тоді я вирішив спробувати створити 2 нових з'єднання для перегляду кожного клієнта, щоб обробляти паб / підпорядкування лише на своїх сесіях, а потім закрити з'єднання, коли користувач відключиться".
toblerpwn

2

У вас є якийсь вихідний код для скидання? Можливо, підключення до бази даних не закриті? Процеси очікування HTTP-з'єднань, які ніколи не закриваються.

Чи можете ви розмістити журнали?

Зробіть ps -ef і переконайтесь, що все ще не працює. Я бачив, як веб-процеси залишають зомбі, які не загинуть, поки ви не вб'єте -9. Іноді відключення не працює або працює не повністю, і ці потоки або процеси будуть містити оперативну пам'ять, а іноді і процесор.

Це може бути нескінченний цикл десь у коді або збій, який тримає на вершині db-з'єднання.

Які модулі NPM використовуються? Чи всі вони останні?

Ви ловите винятки? Дивіться: http://geoff.greer.fm/2012/06/10/nodejs-dealing-with-errors/ Дивіться: /programming/10122245/capture-node-js-crash-reason

Загальні поради:

http://clock.co.uk/tech-blogs/preventing-http-raise-hangup-error-on-destroyed-socket-write-from-crashing-your-nodejs-server

http://blog.nodejitsu.com/keep-a-nodejs-server-up-with-forever

http://hectorcorrea.com/blog/running-a-node-js-web-site-in-production-a-beginners-guide

/programming/1911015/how-to-debug-node-js-applications

https://github.com/dannycoates/node-inspector

http://elegantcode.com/2011/01/14/taking-baby-steps-with-node-js-debugging-with-node-inspector/


1

Не відповідь сама по собі, оскільки ваше запитання - це скоріше казка, ніж питання однозначної відповіді.

Тільки кажучи про те, що я успішно створив сервер node.js з socket.io обробкою понад 1 мільйон стійких з'єднань із середньою корисною навантаженням повідомлення в 700 байтів.

Картка мережевого інтерфейсу на 1 Гбіт / с насичувалась на початку, і я бачив багато очікування від публікації подій для всіх клієнтів.

Видалення nginx з ролі проксі також повернуло дорогоцінну пам'ять, оскільки досягти одного мільйона стійких з'єднань лише з одним сервером - це важка робота з налаштування параметрів конфігурацій, додатків та налаштування ОС. Майте на увазі, що це можливо лише з великою кількістю оперативної пам’яті (близько 1М підключення веб-розетки з’їдає близько 16 Гб оперативної пам’яті, з node.js, я думаю, що використання sock.js було б ідеально підходить для низького обсягу пам’яті, але поки що socket.io споживає стільки).

Це посилання стало моєю відправною точкою для досягнення обсягу з'єднань із вузлом. Окрім того, що це програма Erlang, вся настройка ОС є значною мірою агностичною програмою, і вона повинна бути корисною для всіх, хто має на меті багато стійких зв’язків (веб-розетки або тривалі опитування).

HTH,

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.