Сравнительный анализ производительности node.js (кластера) с пулами mysql: Lighttpd + PHP? - PullRequest
7 голосов
/ 05 октября 2011

Edit (2): Теперь используется db-mysql с модулем generic-pool.Уровень ошибок значительно снизился и колеблется на уровне 13%, но пропускная способность все еще составляет около 100 рек / сек.

Edit (1): После того, как кто-то предположил, что ORDER BY RAND () вызоветMySQL, чтобы быть медленным, я удалил это предложение из запроса.Node.js теперь колеблется около 100 запросов в секунду, но сервер все равно сообщает «Ошибка подключения: слишком много подключений».

Node.js или Lighttpd с PHP?

Вы, вероятно, видели много «HelloМировой "бенчмаркинг node.js ... но тесты" hello world ", даже те, которые были задержаны на 2 секунды на запрос, даже близко не подходят к реальному использованию производства.Я также выполнил эти варианты тестов «Hello World» с использованием node.js и увидел пропускную способность около 800 рэк / сек с частотой ошибок 0,01%.Однако я решил провести несколько более реалистичных тестов.

Возможно, мои тесты не завершены, скорее всего, что-то ДЕЙСТВИТЕЛЬНО неверно в файле node.js или в моем тестовом коде, и если вы эксперт по node.jsПожалуйста, помогите мне написать несколько лучших тестов.Мои результаты опубликованы ниже.Для тестирования я использовал Apache JMeter.

Контрольный пример и технические характеристики системы

Тест довольно прост.MySQL запрос на количество пользователей упорядочен в случайном порядке.Имя пользователя первого пользователя извлекается и отображается.Подключение к базе данных mysql осуществляется через сокет unix.ОС FreeBSD 8+.8 ГБ ОЗУ.Процессор Intel Xeon Quad Core 2.x Ghz.Я немного настроил настройки Lighttpd еще до того, как наткнулся на node.js.

Настройки Apache JMeter

Количество потоков (пользователей): 5000 Я считаю, что это число одновременныхсоединения

Период разгона (в секундах): 1

Количество циклов: 10 Это количество запросов на пользователя

ApacheКонечные результаты JMeter

Label                  | # Samples | Average  | Min   | Max      | Std. Dev. | Error % | Throughput | KB/sec | Avg. Bytes

HTTP Requests Lighttpd | 49918     | 2060ms   | 29ms  | 84790ms  | 5524      | 19.47%  | 583.3/sec  | 211.79 | 371.8

HTTP Requests Node.js  | 13767     | 106569ms | 295ms | 292311ms | 91764     | 78.86%  | 44.6/sec   | 79.16  | 1816

Итоги Выводы

Node.js был настолько плох, что мне пришлось рано останавливать тест.[ Исправлено Проверено полностью]

Node.js сообщает об ошибке «СОЕДИНЕНИЕ: слишком много подключений» на сервере.[ Исправлено ]

Большую часть времени Lighttpd имел пропускную способность около 1200 рэк / сек.

Однако, node.js имел пропускную способность около 29 рэк / сек.сек.[ Исправлено Теперь на 100req / sec]

Это код, который я использовал для node.js (Использование пулов MySQL)

var cluster = require('cluster'), http = require('http'), mysql = require('db-mysql'), generic_pool = require('generic-pool');

var pool = generic_pool.Pool({
    name: 'mysql',
    max: 10,
    create: function(callback) {
        new mysql.Database({
            socket: "/tmp/mysql.sock",
            user: 'root',
            password: 'password',
            database: 'v3edb2011'
        }).connect(function(err, server) {
            callback(err, this);
        });
    },
        destroy: function(db) {
        db.disconnect();
    }
});

var server = http.createServer(function(request, response) {  
    response.writeHead(200, {"Content-Type": "text/html"});  
    pool.acquire(function(err, db) {
        if (err) {
            return response.end("CONNECTION error: " + err);
        }

        db.query('SELECT * FROM tb_users').execute(function(err, rows, columns) {
            pool.release(db);

            if (err) {
                return response.end("QUERY ERROR: " + err);
            }
            response.write(rows.length + ' ROWS found using node.js<br />');
            response.end(rows[0]["username"]);
        });
    });   
});

cluster(server)
  .set('workers', 5)
  .listen(8080);

Это код, который яиспользуется для PHP (Lighttpd + FastCGI)

<?php
  $conn = new mysqli('localhost', 'root', 'password', 'v3edb2011');
  if($conn) {
    $result = $conn->query('SELECT * FROM tb_users ORDER BY RAND()');
    if($result) {
      echo ($result->num_rows).' ROWS found using Lighttpd + PHP (FastCGI)<br />';
      $row = $result->fetch_assoc();
      echo $row['username'];
    } else {
      echo 'Error : DB Query';
    }
  } else {
    echo 'Error : DB Connection';
  }
?>

Ответы [ 7 ]

5 голосов
/ 30 мая 2012

Это плохое сравнение. В node.js вы выбираете всю таблицу и помещаете ее в массив. В php ваш единственный разбор первого ряда. Таким образом, чем больше ваша таблица, тем медленнее будет выглядеть узел. Если бы вы заставили php использовать mysqli_fetch_all, это было бы похожим сравнением. Хотя db-mysql должен быть быстрым, он не очень полнофункциональный и не имеет возможности сделать это справедливым сравнением. Использование другого модуля node.js, такого как node-mysql-libmysqlclient, должно позволить вам обрабатывать только первую строку.

4 голосов
/ 30 октября 2011

100 подключений является настройкой по умолчанию для максимального количества подключений MySQL.

Так что ваши подключения не используются повторно для разных запросов. Возможно, у вас уже есть один запрос на каждое соединение.

Возможно, используемая вами библиотека MySQL nodejs не будет ставить запросы в очередь на том же соединении MySQL, но попытаться открыть другое соединение и завершиться ошибкой.

2 голосов
/ 03 июля 2012

Поправьте меня, если я ошибаюсь, но я чувствую, что вы что-то упускаете: Node использует один процесс для обработки каждого запроса (и обрабатывает их через события, все тот же процесс), в то время как php получает новый процесс (поток ) за каждый запрос.

Проблема в том, что один процесс от узла привязывается к одному ядру ЦП, а PHP масштабируется со всеми четырьмя ядрами через многопоточность. Я бы сказал, что с процессором Quad Core 2.x ГГц PHP определенно имел бы значительное преимущество перед Node, только благодаря возможности использовать дополнительные ресурсы.

Существует еще одно обсуждение , дающее некоторую информацию о том, как масштабировать Node для нескольких ядер, но это должно быть сделано явно посредством кодирования. Опять же, поправьте меня, если я ошибаюсь, но я не вижу такого кода в приведенном выше примере.

Я довольно новичок в Node, но надеюсь, это поможет вам улучшить ваш тест:)

1 голос
/ 27 июня 2012

Вы включили APC с PHP?

Можете ли вы попытаться включить постоянные соединения с PHP? например

$conn = new mysqli('p:localhost', 'root', 'password', 'v3edb2011');
0 голосов
/ 05 сентября 2012

Одна вещь, на которую следует обратить внимание, - это драйвер - производительность базы данных может сильно зависеть от конкретного используемого вами драйвера. Самый популярный драйвер mysql и наиболее активно поддерживаемый - https://github.com/felixge/node-mysql.. Возможно, при этом получатся разные результаты.

Но если вы застряли на 100 соединениях, похоже, что соединения не закрываются должным образом. Я мог бы добавить оператор console.log в событие уничтожения пула, чтобы убедиться, что оно действительно выполняется.

0 голосов
/ 26 июня 2012

Это плохой тест, это должен быть простой «привет мир», так как тысячи тестов, доказывающих, что nodejs является самым быстрым из всех серверов «привет мир»: D

0 голосов
/ 29 декабря 2011

Разве вы не используете 10 максимальных соединений MySQL в Node.js и 5000 максимальных соединений MySQL через PHP?

Пока вы выполняете свои тесты в любой из систем, я бы посмотрел на «SHOW FULL PROCESSLIST» MySQL.

...