Добрый день! Недавно я заинтересовался вопросом, какие технологии можно использовать для построения информационной системы, которая бы отвечала на более-менее простые запросы клиентов, но максимально быстро и надежно.
Немного порывшись в Интернете, однозначного ответа я явно не нашел, поэтому решил провести свой небольшой тест.
Задача
Я сформулировал задачу следующим образом:- Клиент должен отправить запрос на сервер с некоторыми параметрами
- Сервер должен поместить параметры в базу данных
- Сервер должен вернуть идентификатор базы записей.
- Клиент должен инициировать новый сеанс TCP, запросить уже созданную запись.
- После этого сервер отмечает, что транзакция завершена.
Тесты
Изначально планировалось протестировать большое количество вариантов, а именно: собственный сервер на C++ Нгинкс + PHP nginx + собственный модуль апач + PHP Apache + специальный модуль что-то самодельное в .
NET
однако, как любой уважающий себя сисадмин, я поленился и ограничился Нгинкс + PHP И апач + 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, с процессором Atom, 2 ядрами, 4 потоками и установленной на нем Ubuntu 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
Подключен к домашнему роутеру (Каньон, модель за 40 баксов, года 2 назад), соединение 100 мегабит, провод. В качестве ботов для создания нагрузки я использовал следующие машины: 2 ноутбука с Core Duo (один старый Dell, другой старый Fujitsu), подключенных кабелем к одному маршрутизатору 1 ноут с i5 (новый Dell) подключенный по Wi-Fi, тоже к тому же роутеру.
Все настройки делались по инструкции в первых ссылках Google , так что ни о какой конкретной оптимизации речи не идет.
Бот
На всех ноутбуках была установлена 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;
}
}
?>
Тонкости скрипта и бота не так интересны, поэтому думаю, что не стоит на них заострять внимание, а особо пытливые умы все поймут сами, без особого труда.
Итак, перейду непосредственно к результатам испытаний.
Результаты
Понимая, что тест совершенно не объективен, начиная с того, что на десктопной Ubuntu подобные вещи не делаются, заканчивая тем, что нужно было использовать обычный свитч, я все же ожидал других результатов.То, что я увидел, меня сильно удивило.
А именно:
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 |
Ubuntu показала, что все ядра загружены равномерно, примерно на 80%, трафик на Ubuntu шёл со скоростью 400 кб в секунду, а при выключении одного из ноутбуков ситуация вообще не менялась, и поэтому, я была гипотеза, что роутер медленный.
апач
С теми же запросами я наблюдал следующую картину: | 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 секунды.
Все остальные характеристики остаются прежними
Голые выводы
Честно говоря, сложно сделать из этого какие-то выводы, потому что.не хочется верить, что Apache быстрее Nginx. Возможно тормоза nginx связаны с необходимостью использования fastcgi, и есть лучший способ настроить его для работы с php, но я не сразу нашел как это сделать, так что, уважаемые хабры, возможно, вы сможете сделать какие-то выводы( например, что мой эксперимент вообще не имеет никакой ценности из-за субъективных параметров), или принять его результаты как есть.
В любом случае, спасибо, что уделили время :) P.S. Вспоминая классику: nginx, давай, до свидания.
Теги: #Nginx #Администрирование сервера #Apache #ubuntu #стресс-тест
-
Руководство 2.0
19 Oct, 24 -
Как Я Ночью Продавал Холодильник
19 Oct, 24 -
Страна Слепых
19 Oct, 24