Как следует из названия вопроса, мне трудно понять, что можно улучшить в моем приложении (или настроить в ОС, 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) с 4 Гб оперативной памяти и 2 ядрами.
Приложение работает в течение нескольких месяцев (оно работало на одном устройстве до нескольких недель назад), и его используют около 18 000 пользователей в день. Он всегда работал очень хорошо, за исключением одной основной проблемы: снижение производительности. При использовании количество процессоров, используемых каждым процессом, увеличивается до тех пор, пока он не проработает статую рабочего (что больше не будет обслуживать запросы) Я временно решил, что каждую минуту проверяю процессор, используемый каждым работником, и перезагружаю его, если он достигает 98%. Так что проблема здесь в основном процессор, а не оперативная память. Оперативная память больше не является проблемой, так как я обновил файл socket.io 0.9.14 (более ранняя версия имела утечку памяти), поэтому я сомневаюсь, что это проблема утечки памяти, особенно потому, что теперь этот процессор растет довольно быстро ( Я должен перезапускать каждого работника примерно 10-12 раз в день!). Объем оперативной памяти растет, если честно, но очень медленно, 1 гиг каждые 2-3 дня использования, и странно то, что он не выпускается, даже когда я полностью перезагружаю все приложение. Выпускается только если я перезагружаю сервер! это я не могу понять ...
Теперь я обнаружил удивительную нодли , поэтому теперь я могу наконец увидеть, что происходит на моем производственном сервере, и я собираю данные уже пару дней. Если кто-то захочет увидеть графики, я могу дать вам доступ, но в основном я вижу, что у меня от 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, а не системный администратор, поэтому я не знаю, какую нагрузку мне следует ожидать от работы с моими серверами, но, конечно, он не работает должным образом. В противном случае приложение стабильно, и эта последняя проблема не позволяет мне отправить готовые мобильные версии приложения, поскольку, очевидно, они принесут большую нагрузку и в конечном итоге приведут к краху!
Надеюсь, что-то очевидно, что я делаю что-то не так, и кто-то поможет определить это ... не стесняйтесь спрашивать меня о дополнительной информации, и я извиняюсь за длину вопроса, но это было необходимо, я полагаю ... заранее спасибо!
top
когда использование процессора близко к 100%?Ответы:
После нескольких дней интенсивных проб и ошибок, я рад возможности сказать, что я понял, где было узкое место, и я опубликую его здесь, чтобы другие люди могли извлечь выгоду из моих выводов.
Проблема заключается в соединениях pub / sub, которые я использовал с socket.io, и, в частности, в RedisStore, который используется socket.io для обработки межпроцессного взаимодействия экземпляров сокетов.
Поняв, что я могу легко реализовать свою собственную версию pub / sub, используя redis, я решил попробовать и удалил redisStore из socket.io, оставив его с хранилищем памяти по умолчанию (мне не нужно передавать на все подключенные клиенты, но только между двумя разными пользователями, подключенными возможно в разных процессах)
Первоначально я объявил только 2 глобальных подключения redis x процесс для обработки pub / sub на каждом подключенном клиенте, и приложение использовало меньше ресурсов, но на меня все еще влиял постоянный рост использования ЦП, поэтому мало что изменилось. Но затем я решил попытаться создать 2 новых подключения к redis для каждого клиента, чтобы обрабатывать их pub / sub только в своих сеансах, а затем закрыть подключения, как только пользователь отключился. Затем, после одного дня использования в производстве, процессоры все еще были на 0-5% ... бинго! ни процесс, ни перезапуск, ни ошибок, с ожидаемой производительностью. Теперь я могу сказать, что node.js рушится и рад, что выбрал его для создания этого приложения.
К счастью, redis был разработан для обработки множества одновременных подключений (по-разному для mongo), и по умолчанию он установлен на 10k, что оставляет место для примерно 5k одновременных пользователей на одном экземпляре redis, чего на данный момент мне достаточно, но я ' Я читал, что он может поддерживать до 64 тыс. одновременных подключений, поэтому я считаю, что эта архитектура должна быть достаточно надежной.
В этот момент я думал о реализации какого-либо пула соединений для redis, чтобы немного оптимизировать его, но я не уверен, не вызовет ли это снова события pub / sub для создания соединений, если только не каждое из них уничтожается и воссоздается каждый раз, чтобы очистить их.
В любом случае, спасибо за ваши ответы, и мне будет интересно узнать, что вы думаете, и если у вас есть какие-либо другие предложения.
Приветствия.
источник
У вас есть исходный код для дампа? Может быть, соединения с базой данных не закрыты? Процессы, ожидающие соединения HTTP, которые никогда не закрываются.
Можете ли вы опубликовать несколько журналов?
Сделайте ps -ef и убедитесь, что ничего не запущено. Я видел, как веб-процессы оставляют зомби, которые не умрут, пока вы не убьете -9. Иногда завершение работы не работает или не работает полностью, и эти потоки или процессы будут содержать ОЗУ, а иногда и ЦП.
Это может быть бесконечный цикл где-то в коде или сбойный процесс, удерживающий соединение с БД.
Какие модули 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/
источник
Сам по себе это не ответ, так как ваш вопрос скорее сказка, чем вопрос с одним ответом.
Просто чтобы сказать, что я успешно построил сервер node.js с socket.io, который обрабатывает более 1 миллиона постоянных соединений со средней полезной нагрузкой сообщения в 700 байт.
Плата сетевого интерфейса на скорости 1 Гбит / с вначале насыщалась, и я видел ОЖИДАНИЕ ожидания ввода-вывода от публикации событий для всех клиентов.
Удаление nginx из роли прокси также вернуло драгоценную память, потому что для достижения миллиона постоянных соединений только с ОДНЫМ сервером требуется непростая настройка конфигов, приложений и параметров настройки ОС. Имейте в виду, что это возможно только с большим количеством оперативной памяти (около 1M подключений к веб-сокетам потребляет около 16 ГБ оперативной памяти, при использовании node.js, я думаю, что использование sock.js было бы идеальным для низкого потребления памяти, но пока, socket.io так много потребляет).
Эта ссылка была моей отправной точкой для достижения этого объема соединений с узлом. Помимо того, что это приложение Erlang, все настройки ОС в значительной степени не зависят от приложения и должны быть полезны всем, кто стремится к множеству постоянных соединений (веб-сокеты или длительный опрос).
НТН,
источник