Pull to refresh
313.36
Конференции Олега Бунина (Онтико)
Конференции Олега Бунина

Нагрузочное тестирование: Node.JS vs phpDaemon

Reading time 3 min
Views 22K
При работе над одним из проектов перед нами встала задача реализации переписки между зарегистрированными пользователями. По своей сути – это должен быть чат, но одновременно общаться в нём можно только с одним собеседником.

Потенциальная нагрузка, которую должен выдерживать такой чат — около 10000 одновременных keep-alive соединений. Каждое новое сообщение должно записываться в основную базу данных, а так же в «быструю», задача которой хранить в себе лишь актуальную часть переписок между пользователями, то есть служить своеобразным «временным» хранилищем, из которого сообщения будут сразу доставляться адресату.

Для решения этой задачи хорошо подходит MongoDB. Поскольку в ней хорошо отлажен процесс репликации, мы можем отдельным демоном периодически опрашивать таблицу local.oplog.$main на предмет наличия в ней новых сообщений, и, если таковые имеются, сразу доставлять их по адресу в формате JSON. Для устойчивой работы под нагрузкой, таких демонов будет несколько, к каждому из которых будут подключены несколько тысяч переписчиков.

И здесь перед нами встал выбор, что использовать в качестве «быстрого сервера», на котором будет размещены демоны? Для этого мы протестировали два решения: на основе phpDaemon и на основе Node.JS.

Итак, для начала, полная архитектура чата:

Полная структура чата
Рис. 1. Полная структура чата
  1. Каждый новый клиент, входящий в переписку устанавливает соединение с одним из «быстрых» серверов (phpDaemon или Node.js) и от него же будет получать сообщения.
  2. При отправке на основной сервер нового сообщения, оно записывается в постоянную базу данных (MySQL), а так же в некую «быструю» базу данных (в данном случае MongoDB), где будет храниться только актуальная переписка, например за последние сутки.
  3. Master MongoDB записывает изменения в коллекцию local.oplog.$main для репликации.
  4. «Быстрые сервера» в это время ведут опрос «быстрой» базы на предмет наличия в ней новых сообщений, и, если такие есть, отправляют их тому клиенту, которому они адресованы.

В нашем тестовом варианте не будет постоянной базы данных, а так же авторизации пользователей. Будет только один «быстрый сервер», который будет забирать новые сообщения из коллекции и рассылать всем активным в данный момент клиентам (рис 2).

Упрощенная структура чата
Рис. 2. Упрощенная структура чата

Составы играющих сегодня команд:

Команда Node.js
  1. Node.js (http://nodejs.org)
  2. Библиотека Socket.IO для установления соединений между клиентом и Node.js (http://socket.io)
  3. Библиотека Node-mongo-native от christkv для работы с MongoDB из Node.js (https://github.com/christkv/node-mongodb-native)
  4. Ну и файл oplog.js из той же библиотеки для опроса MongoDB на предмет наличия новых сообщения (https://github.com/christkv/node-mongodb-native/blob/master/examples/oplog.js)

Команда phpDaemon
  1. phpDaemon (http://phpdaemon.net)
  2. Скрипты из состава phpDaemon для установки соединения между клиентом и сервером (https://github.com/kakserpom/phpdaemon/tree/master/clientside-connectors/websocket)
  3. Для работы с MongoDB так же будем использовать встроенные возможности phpDaemon
  4. Для опроса базы будет использоваться немного измененное нами приложение MongoNode (https://github.com/kakserpom/phpdaemon/blob/master/app-servers/MongoNode.php), которое не пишет изменения в Memcache, а отправляет их всем подключенным пользователям.

Судья встречи Apache Benchmark.

Итак, мы запускаем один из демонов, который ведет polling MongoDB, а так же «общается» с пришедшими клиентами. С помощью утилиты Apache Benchmark с другой машины подключаем несколько keep-alive клиентов (время тестирования 20 секунд). В это время сторонней формой начинаем записывать в MongoDB сообщения. Для каждого демона и каждого числа keep-alive соединений делаем по 5 итераций, потом усредняем полученные данные и видим результат.

Демон
Complete requests
Requests per second
Time per request, ms
(across all concurrent requests)
Min
request, ms
Max Request, ms
10 keep-alive соединений
phpDaemon
1147
54.36
18.440
21
7116
Node.JS
1285
64
15.618
16
9064
100 keep-alive соединений
phpDaemon
1543
75.15
13.313
22
12889
Node.JS
1284
64.12
15.765
17
13347
500 keep-alive соединений
phpDaemon
1365
67.73
14.824
15
15174
Node.JS
1236
61.71
16.611
23
16078
1000 keep-alive соединений
phpDaemon
1159
56.99
17.680
19
13103
Node.JS
1528
75.02
13.354
17
16785

Красным цветом отмечены «лучшие показатели»

Как мы видим, на небольшом числе одновременных соединений (10), чат на основе Node.JS работает лучше. Обрабатывается большее число запросов, соответсвенно сокращается время на обработку одного запроса. Правда, phpDaemon имеет меньшую длительность самого долгого запроса, что, правда, не слишком принципиально.

При увеличении числа соединений до 100, а затем и 500 картина изменилась. Вперед по показателям вышел уже phpDaemon.

А при 1000 keep-alive соединений показатели phpDaemona упали, а Node.JS наоборот возросли, что в итоге дало довольно сильный разрыв.
Tags:
Hubs:
+25
Comments 55
Comments Comments 55

Articles

Information

Website
www.ontico.ru
Registered
Founded
Employees
11–30 employees
Location
Россия