Доброго времени суток!
Недавно я заинтересовался вопросом, на каких технологиях можно построить информационную систему, которая бы отвечала на более-менее простые запросы от клиентов, но максимально быстро и надёжно.
Порыскав немного в интернетах, однозначного ответа я разумеется не нашел, по этому решил сделать собственный небольшой тест.
Задачу я сформулировал следующим образом:
Изначально планировалось протестировать большое количество вариантов, а именно:
самописный сервер на с++
nginx + php
nginx + самописный модуль
apache + php
apache + самописный модуль
что — то самописное на .NET
однако, как любому уважающему себя сисадмину, мне стало лень и я ограничился лишь nginx + php и apache + php, в надежде что остальные эксперименты сделаю позже (ну или после Ваших комментариев к этой статье они будут не нужны)
Как базу данных я использовал MySQL.
В таблице я сделал 3 контрольные точки:
1. Время создание записи (с точностью до миллисекунд)
2. Время окончание транзакции (с точностью до миллисекунд)
3. Время создание записи (с точностью до секунд)
3 контрольная точка нужна для того, что бы можно было понять сколько записей создается в секунду.
Итого, база получилась примерно такая:
Как сервер, единственное что у меня было под рукой, это один из последних aspire one, с процессором Атом, 2 ядерный, 4 поточный, и установленный на него 10 убунтой:
Подключён он к домашнему рутеру (canyon, модель за 40 баксов примерно, 2 летней давности), 100 мегабитным соединением, проводом.
Как ботов для создание нагрузки я использовал следующие машины:
2 ноутбука с core duo (один старенький делл, другой старенький fujitsu), подключичные проводом в тот же рутер
1 ноут бук с i5 (новый делл) подключенный по wi-fi, тоже в тот же рутер.
Все настройки были произведены исходя из инструкций в первых ссылках гугла, так что ни о какой специфической оптимизации речи нет.
На всех ноута был установлен windows 7, по этому самым простым вариантом мне показалось наваять бота на c#, который в цикле создавал нужное количество потоков и начинал фигачить «транзакции».
Основной код бота выглядит следующим образом:
Небольшой скриптик на PHP, который, собственно делает всё что мне надо, я реализовал так:
Тонкости скрипта и бота не столько интересны, по этому, я думаю, что не стоит заострять на них внимание, а особо пытливые умы всё сами поймут, без особого труда.
По этому приступлю сразу к результатам теста
Понимая, что тест абсолютно не обьективнен, начиная от того что на десктопной убунте такие вещи не делаются, заканчивая тем, что нужно было использовать нормальный свич, я всё же ожидал иных результатов. То что я увидел меня сильно удивило. А именно:
Запрос вида:
Показал, что среднее количество обрабатываемых сессий: 205 штук, за среднее время: 0.025 секунды.
(Сессией здесь, и далее, я называю время между созданием записью от первого запроса и обновлением записи при втором запросе от потока).
Убунта показывала, что все ядра были нагружены равномерно, примерно на 80%, трафик на убунте шёл со скоростью 400 кб в секунду, при чём, при отключении одного из ноут буков ситуация не менялась вообще, в связи с чем, у меня появилась гипотеза что тормозит рутер.
При тех же запросах я наблюдал следующую картину:
Это означает, что количество обрабатываемых запросов в секунду было порядка 255, что больше чем на nginx, время обработки одного запроса не увеличилось, и так же осталось равным 0.025 секунды.
Все остальные характеристики остались теми же
Честно говоря, тяжело сделать какие то выводы из этого, т.к. верить что апач быстрее nginx я не хочу. Возможно, тормоза nginx'а связаны с необходимостью использования fastcgi, и есть способ настроить его для работы с php лучше, однако сходу я не нашёл как это сделать, так что, уважаемые хабрчани, возможно, Вы сделайте какие то выводы (например, что мой эксперимент вообще не представляет никакой ценности из за субъективных параметров), либо примите его результаты как есть.
В любом случае, спасибо за удалённое время :)
P.S. Вспоминая классиков: nginx, давай, до свидааание.
Недавно я заинтересовался вопросом, на каких технологиях можно построить информационную систему, которая бы отвечала на более-менее простые запросы от клиентов, но максимально быстро и надёжно.
Порыскав немного в интернетах, однозначного ответа я разумеется не нашел, по этому решил сделать собственный небольшой тест.
Задача
Задачу я сформулировал следующим образом:
- Клиент должен послать серверу запрос с какими то параметрами
- Сервер должен положить параметры в базу данных
- Сервер должен выплюнуть назад ID базы записи
- Клиент должен инициировать новую TCP сессию, запросить уже созданную запись
- После этого сервер помечает, что транзакция исполнена
Тесты
Изначально планировалось протестировать большое количество вариантов, а именно:
самописный сервер на с++
nginx + php
nginx + самописный модуль
apache + php
apache + самописный модуль
что — то самописное на .NET
однако, как любому уважающему себя сисадмину, мне стало лень и я ограничился лишь nginx + php и apache + php, в надежде что остальные эксперименты сделаю позже (ну или после Ваших комментариев к этой статье они будут не нужны)
Как базу данных я использовал MySQL.
База
В таблице я сделал 3 контрольные точки:
1. Время создание записи (с точностью до миллисекунд)
2. Время окончание транзакции (с точностью до миллисекунд)
3. Время создание записи (с точностью до секунд)
3 контрольная точка нужна для того, что бы можно было понять сколько записей создается в секунду.
Итого, база получилась примерно такая:
create table clients (id int not null auto_increment, amount double not null, hash char(32), Primary key (id));
alter table clients add cr_time char(100);
alter table clients add ps_time char(100);
alter table clients add column sec_time TIMESTAMP default NOW();
Инфраструктура
Как сервер, единственное что у меня было под рукой, это один из последних aspire one, с процессором Атом, 2 ядерный, 4 поточный, и установленный на него 10 убунтой:
root@aspire-1-laptop:/etc# cat /proc/version
Linux version 2.6.32-41-generic (buildd@vernadsky) (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1) ) #89-Ubuntu SMP Fri Apr 27 22:22:09 UTC 2012
Подключён он к домашнему рутеру (canyon, модель за 40 баксов примерно, 2 летней давности), 100 мегабитным соединением, проводом.
Как ботов для создание нагрузки я использовал следующие машины:
2 ноутбука с core duo (один старенький делл, другой старенький fujitsu), подключичные проводом в тот же рутер
1 ноут бук с i5 (новый делл) подключенный по wi-fi, тоже в тот же рутер.
Все настройки были произведены исходя из инструкций в первых ссылках гугла, так что ни о какой специфической оптимизации речи нет.
Бот
На всех ноута был установлен windows 7, по этому самым простым вариантом мне показалось наваять бота на c#, который в цикле создавал нужное количество потоков и начинал фигачить «транзакции».
Основной код бота выглядит следующим образом:
public void beginTransaction()
{
while (true)
{
string response = this.createRecord();
string id = response.Substring(0, response.IndexOf('|'));
string final = this.updateRequest(id);
StringReader strReader = new StringReader(response);
StringReader strReader2 = new StringReader(final);
}
}
public void start()
{
for (int i = 0; i < int.Parse(this.textBox1.Text); i++)
{
this.richTextBox2.BeginInvoke((MethodInvoker)(() => this.richTextBox2.AppendText("thread started \n")));
Thread oThread = new Thread(new ThreadStart(beginTransaction));
oThread.Start();
while (!oThread.IsAlive) ;
}
}
Веб часть
Небольшой скриптик на PHP, который, собственно делает всё что мне надо, я реализовал так:
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
mysql_pconnect('localhost','root','qwerty') or die(mysql_error());
mysql_select_db('test') or die(mysql_error());
if (isset($_REQUEST['id'])){
if (trim($_REQUEST['id'])!=''){
// echo 'ktulhu fhtagn';
$result = mysql_query('select * from clients where id = "'.addslashes($_REQUEST['id']).'";') or die(mysql_error());
$time = microtime();
$query = sprintf("update clients set ps_time = '%s' where id = '%s'",
mysql_real_escape_string($time),
mysql_real_escape_string($_REQUEST['id']));
mysql_query($query) or die(mysql_error());
echo $time;
} else{
$time = microtime();
$amount = $_REQUEST['amount'];
$hash = $_REQUEST['hash'];
$query = sprintf("INSERT INTO clients (amount,hash,cr_time)
VALUES
('%s','%s','%s');",
mysql_real_escape_string($_REQUEST['amount']),
mysql_real_escape_string($_REQUEST['hash']),
mysql_real_escape_string($time));
mysql_query($query) or die(mysql_error());
$id = mysql_insert_id();
echo $id." | ".$time;
}
}
?>
Тонкости скрипта и бота не столько интересны, по этому, я думаю, что не стоит заострять на них внимание, а особо пытливые умы всё сами поймут, без особого труда.
По этому приступлю сразу к результатам теста
Результаты
Понимая, что тест абсолютно не обьективнен, начиная от того что на десктопной убунте такие вещи не делаются, заканчивая тем, что нужно было использовать нормальный свич, я всё же ожидал иных результатов. То что я увидел меня сильно удивило. А именно:
nginx
Запрос вида:
select count(*) from clients group by sec_time order by sec_time desc limit 0,20;
Показал, что среднее количество обрабатываемых сессий: 205 штук, за среднее время: 0.025 секунды.
(Сессией здесь, и далее, я называю время между созданием записью от первого запроса и обновлением записи при втором запросе от потока).
| 205 |
| 200 |
| 202 |
| 208 |
| 155930 | 0 | K | 0.36527600 1339369721 | 0.38711300 1339369721 | 2012-06-11 02:08:41 |
| 155929 | 0 | K | 0.36156500 1339369721 | 0.38884600 1339369721 | 2012-06-11 02:08:41 |
Убунта показывала, что все ядра были нагружены равномерно, примерно на 80%, трафик на убунте шёл со скоростью 400 кб в секунду, при чём, при отключении одного из ноут буков ситуация не менялась вообще, в связи с чем, у меня появилась гипотеза что тормозит рутер.
apache
При тех же запросах я наблюдал следующую картину:
| 255 |
| 247 |
| 257 |
| 190582 | 0.102561082738713 | G | 0.46013900 1339370133 | 0.48647400 1339370133 | 2012-06-11 02:15:33 |
| 190581 | 0.266181369901719 | W | 0.45496900 1339370133 | 0.47832300 1339370133 | 2012-06-11 02:15:33 |
Это означает, что количество обрабатываемых запросов в секунду было порядка 255, что больше чем на nginx, время обработки одного запроса не увеличилось, и так же осталось равным 0.025 секунды.
Все остальные характеристики остались теми же
Голые выводы
Честно говоря, тяжело сделать какие то выводы из этого, т.к. верить что апач быстрее nginx я не хочу. Возможно, тормоза nginx'а связаны с необходимостью использования fastcgi, и есть способ настроить его для работы с php лучше, однако сходу я не нашёл как это сделать, так что, уважаемые хабрчани, возможно, Вы сделайте какие то выводы (например, что мой эксперимент вообще не представляет никакой ценности из за субъективных параметров), либо примите его результаты как есть.
В любом случае, спасибо за удалённое время :)
P.S. Вспоминая классиков: nginx, давай, до свидааание.