Я запускаю крошечный веб-сервер масштаба под Apache + PHP + MySQL на данный момент и хотел бы изучить вариант использования NodeJS. Сервер буквально выполняет две вещи:
- Подавать некоторые статические файлы (ресурсы HTML/CSS/изображения и т.д.)
- Запросить базу данных (выбрать и вставить только, не обновлять и не удалять)
Однако я столкнулся с некоторой проблемой производительности, и я пытаюсь выяснить, где проблема. Чтобы изолировать проблему, я создал минимальное приложение NodeJS, которое запускает запрос к MySQL и возвращает 50 строк данных в виде JSON. Ниже мой код:
var express = require('express');
var compression = require('compression');
var mysql = require('mysql');
var db = mysql.createPool({
host: <host>,
user: <user>,
password: <password>,
database: <database>,
debug: false
});
var app = express();
app.use(compression());
app.get('/data', function(req, res) {
var sql = 'SELECT column_1, column_2 FROM table';
db.query(sql, function (error, rows, fields) {
if (error) throw error;
res.json(rows);
});
});
app.listen(3000, function () {
console.log("Running on port 3000.");
});
Используя ApacheBench для запуска 1000 запросов на уровне concurrency 1 (чтобы не помешать однопоточному приложению Node), результат выглядит следующим образом:
Concurrency Level: 1
Time taken for tests: 10.377 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 3057000 bytes
HTML transferred: 2829000 bytes
Requests per second: 96.37 [#/sec] (mean)
Time per request: 10.377 [ms] (mean)
Time per request: 10.377 [ms] (mean, across all concurrent requests)
Transfer rate: 287.69 [Kbytes/sec] received
Для сравнения ниже мой код в PHP:
<?php
$hostname = <host>;
$username = <user>;
$password = <password>;
$database = <database>;
try {
$db_handler = new PDO('mysql:host=' . $hostname . ';dbname=' . $database, $username, $password);
} catch (PDOException $e) {
throw new Exception('[ERROR] Unable to connect to the database.');
}
$sql = 'SELECT column_1, column_2 FROM table';
$statement = $db_handler->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$statement->execute();
$rows = array();
while ($row = $statement->fetch(PDO::FETCH_ASSOC)){
$rows[] = $row;
}
print json_encode($rows);
$db_handler = null;
?>
И результат ApacheBench:
Concurrency Level: 1
Time taken for tests: 6.726 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 3023000 bytes
HTML transferred: 2829000 bytes
Requests per second: 148.68 [#/sec] (mean)
Time per request: 6.726 [ms] (mean)
Time per request: 6.726 [ms] (mean, across all concurrent requests)
Transfer rate: 438.92 [Kbytes/sec] received
Из приведенного выше результата видно, что PHP намного быстрее, чем NodeJS. Рассогласование еще шире, если запущен более сложный запрос (разница может быть в 20 раз, например, 20 мс против 400 мс), или если уровень concurrency увеличен.
Я попытался добавить до 4 рабочих (я запускаю сервер на Raspberry Pi 2, который имеет 4 ядра), в приложение Node и посмотреть, помогает ли он, к сожалению, он все еще не близок к результату в PHP. Не могли бы вы посоветовать, что я мог сделать неправильно? Или NodeJS просто не лучший выбор для того, чего я пытаюсь достичь?
[EDITED]
Большое спасибо за ваши комментарии. Похоже, что большинство людей подозревают, что проблема вызвана драйвером NodeJS MySQL. Я также сделал немного больше тестирования, чтобы убедиться, что это так, и я случайно нашел что-то действительно интересное.
Запустив такое же приложение Node на другом ПК (Core 2 Duo E7200), но подключившись к тому же MySQL на малине Pi, результат на самом деле вполне приличный:
Concurrency Level: 1
Time taken for tests: 2.705 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 3057000 bytes
HTML transferred: 2829000 bytes
Requests per second: 369.71 [#/sec] (mean)
Time per request: 2.705 [ms] (mean)
Time per request: 2.705 [ms] (mean, across all concurrent requests)
Transfer rate: 1103.72 [Kbytes/sec] received
И для сравнения, я также запустил сервер Apache на этом ПК, подключившись к тому же MySQL на малине Pi, а ниже - результат:
Concurrency Level: 1
Time taken for tests: 6.297 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 3034000 bytes
HTML transferred: 2829000 bytes
Requests per second: 158.80 [#/sec] (mean)
Time per request: 6.297 [ms] (mean)
Time per request: 6.297 [ms] (mean, across all concurrent requests)
Transfer rate: 470.50 [Kbytes/sec] received
Как итог, ниже приведен результат, который я получил до сих пор. Только часть веб-сервера отличается, в то время как база данных всегда MySQL на малине Pi:
Server Time Taken
Node (Pi) 10.337s
PHP (Pi) 6.726s
Node (PC) 2.705s
PHP (PC) 6.297s
Результат для PHP кажется более или менее одинаковым на обоих серверах, в то время как для NodeJS много. Основываясь на приведенном выше результате, мне кажется, что NodeJS более чувствителен к производительности процессора или, другими словами, к интенсивному процессору? (Версия NodeJS, которую я использую, - v6.9.4, только FYI)