PHP

индекс
206,76

PHP и SimpleDB. Проблемы скорости соединения.

Здравствуйте! В этой заметке хочу рассказать о практическом опыте использования связки PHP и SimpleDB и проблемах, которые могут возникнуть в плане общей производительности соединения на начальных этапах разработки.

Не так давно один из наших клиентов, в связи с резким ростом аудитории захотел избежать проблем горизонтального масштабирования путем использования служб Amazon WS — Amazon EC2 и Amazon SimpleDB.
Прежде всего, клиента волновала производительно базы данных на собственном сервере в виду роста контента, генерируемого пользователями.
Мы перевели структуру и данные клиента в структуру SimpleDB базы данных, взяли Instance Debian-а на EC2 и стали тестировать.
После внедрения и тестирования, мы неожиданно выяснили, что время выполнения скриптов достигает 100 мс, в то время как на сервере заказчика изначальное время выполнения до перехода на SimpleDB составляло 15.
О том что случилось и как мы с этим боролись — ниже.


Итак, время выполнения — 100 мс. Что с этим делать и откуда это взялось?

Прежде всего мы впервые применили XHProf — PHP профилировщик от Facebook о котором много услышали не так давно — и вот наконец то довелось использовать его в деле.

Профилирование в XHProf заключается в установке модуля и включении
xhprof_enable(); — в начале скрипта
и
$xhprof_data = xhprof_disable(); в конце.

Более подобную информацию об использовании XHProf можно прочитать на странице документации по адресу http://mirror.facebook.com/facebook/xhprof/doc.html
(к сожалению, в настоящий момент XHProf компилируется только под Linux и FreeBSD — MacOSX и Windows версии еще не реализованы)

Первичный анализ показал что львиную долю времени занимает не выполнение запроса к SimpleDB — о чем мы думали, а собственно процесс соединения с ней для передачи запроса.

Для того чтобы объяснить причины — нужно объяснить технологию работы библиотеки SimpleDB и базой данных.

В отличие от классических баз даных, сервер SimpleDB принимает данные не по собственному протоколу основанному на tcp/ip, а в рамках HTTP-протокола. Запрос передается в виде POST-данных на URL службы, ответом от службы — в XML формате — является результат выполненного запроса.

PHP-клиент SimpleDB от Amazon использует fsockopen для передачи каждого запроса к базе, и получив ответ закрывает соединение. Затем, посредством класса DOMDocument и XPath — происходит разбор ответа и окончательное получение данных.

Первым делом, мы заглянули внутрь классов SimpleDB и начали пошагово вести борьбу за милисекунды.
0. Профилировщик показал долгую работу класса Mock. Этот класс, предназанченый для UNIT-тестирования подключается и в production-коде.
Комментирование подключение класса позволило выйграть 15 мс.

Итого время выполнения: 85 мс.

1. класс Client. Класс реализует собственно процесс соединения с базой — оттуда мы и решили копать.
Прежде всего мы решили проверить — как именно соединяется класс с базой.
if ($socket = @fsockopen($scheme . $url['host'], $port, $errno, $errstr, 10))
что же передается за URL?
взглянем немного выше…
private $_config = array ('ServiceURL' => 'https://sdb.amazonaws.com'
… так-так-так, а сколько же времени уйдет на DNS-resolving.
Заменив днс-имя на айпи адрес получаем выигрыш в 20 мс.

Итого: 65 мс.

Что делать если IP-адрес изменится?
Мы создали программу, которая регулярно опрашивала днс на предмет айпи-адреса указанного сервера с целью записать IP в конфиг SimpleDB класса. Программу поставили в крон.

3.
switch ($url['scheme']) {
case 'https':
$scheme = 'ssl://';
$port = $port === null ? 443 : $port;
break;
default:
$scheme = '';
$port = $port === null ? 80 : $port;
}

Ребята, что это?
По умолчанию соединение устанавливается через SSL. Что будет если мы заменим https на http в конфигурационной строке? — Выигрыш в 30 мс.

Итого время выполнения 35 мс.

4. Что же еще мы можем сделать? Естественно мы используем PHP-акселераторы в production-среде — может быть структура классов подойдет для одного но не подойдет для другого?
Замена Eaccelerator на XCache успеха не принесла, но вернувшись к профилировщику мы увидели что очень большое количество времени тратится на require_once функции — подключалось 32 класса из папки Model.
cat * >includes.php
дальше нужно было отключить реквайры из SimpleDB класса подключив их уровнем выше.
удаление их из Client.php прошло совершенно безболезенно, однако кода мы перешли к Model.php мы увидели следующее
require_once (CLASSES_DIR.''.str_replace('_', DIRECTORY_SEPARATOR, $fieldType[0]) . ".php");
Интересно, как к этому относились PHP-акселераторы? И чего мы достигнем теперь?
Экономия — 15 мс.

Итого время выполнения — 20 мс.

5. Дальнейшая оптимизация кода привела к удалению одного из двух запросов к SimpleDB от уровня логики приложения.
Таким образом мы достигли скорости в 15 мс., что уже устраивало и нас и клиента — для этапа тестирования работоспособности сервисов.

Таким образом мы вспомнили славные времена экономии машинного времени, узнали в работе профилировщик XHProf (рекомендуем всем), а так же поняли — что практически не понятно как живут люди использующие SimpleDB на высоких нагрузках и использующие предлагаемые по умолчанию классы клиентов.
Если такие есть — просьба ответить, мы будем рады обменяться опытом и информацией.

Куда можно копать дальше?

Из оставшегося — мы планируем заменить обработку DOMDocument на SimpleXML и отказаться от XPath в выборках — это явно не лучшее, что можно использовать для разбора данных которые возвращает БД.

Мы планируем для запросов-выборок устанавливать Keep-Alive соединения для того, чтобы не устанавливать соединение на каждый запрос.

Продакшен-тестирование на высокой нагрузке ожидается через неделю.
Ждите отчета!
+48
6 апреля 2009, 16:43
44

комментарии (35)

НЛО прилетело и опубликовало эту надпись здесь
+3
naoise #
это да, в данном случае мы хотели добиться минимального времени ожидания до соединения — выяснить чего можно добиться при оптимизации.
теперь мы как раз думаем как получить минимальный таймаут при работе с ссл-ем.
будем копать в сторону DOMDocument
+3
Honeyman #
Вот насчет отключения SSL это вы очень зря… повесят гденибудь бяку на сетке и все… все ваши данные благополучно буду сливатся на чужие харды.

Которая сумеет снифить чужие данные между чужими инстансами EC2 и чужими инстансами SimpleDB? Тогда, наверное, Amazon AWS-ного CTO уволят без выходного пособия.
0
naoise #
Ну никогда не стоит забывать о рядовых сотрудниках пусть даже и известрного провайдера, которые все-таки люди, со своими слабостями и ошибками.
Из банков уплывают номера пластиковых карт, рассекретить ключ сервиса гораздо проще ;)
+1
Honeyman #
+1
naoise #
О да, я не прав, спасибо за исправление)
По сниферрным данным исходных ключей конечно же не восстановить, в этом их суть.
Другое дело что собственно данные могут подключить, но это конечно скорее вопрос того насколько эти данные конфиденциальны.
0
SeLarin #
Лично я согласен. Но в любом случае «каска на войне лишней не будет» :)
НЛО прилетело и опубликовало эту надпись здесь
+1
Honeyman #
И как все эти захватывающие истории в стиле раннего Ван Эйка относятся к описанной выше вполне конкретной ситуации — перехват трафика от чужого EC2 к чужому SimpleDB? Вы собираетесь копать лопатой кабель под датацентром Amazon? Или из излучения нескольких десятков тысяч серверов в датацентре выделять излучение одного конкретного, с желаемым EC2-инстансом?

Будучи последовательным, надо признать себе. Или ты доверяешь хостеру, или ты строишь свой собственный датацентр.
НЛО прилетело и опубликовало эту надпись здесь
0
Honeyman #
Хостер отвечает за хранимую информацию. За передаваемую информацию никто не отвечает.


Я тут уже упоминал про документик developer.amazonwebservices.com/connect/entry.jspa?externalID=1697 — за что отвечает Амазон. У меня такое впечатление, что я говорю про вполне себе конкретный Амазон, а вы говорите про абстрактных средней паршивости хостеров в вакууме.
НЛО прилетело и опубликовало эту надпись здесь
0
Honeyman #
Так что я не понимаю что вы так с этим Амазон носитесь??

Потому что вот вам картинка, про что сейчас идёт речь:

Amazon EC2 -> Amazon SimpleDB.

Сумеете повесить между двумя звеньями этой цепи сниф — пишите. Сразу в Amazon. Готов поспорить, зарплата после этого у вас изменится кардинально.
+3
jahson #
При всём этом ты забыл сказать, что xhprof будет работать на FreeBSD / Linux, а на маке, или например винде, он будет ругаться. Это пишут и в описании в pecl — но не все могут заметить.

Пойду ставить FreeBSD параллельно osx )
+1
naoise #
большое спасибо за замечание! обязательно сейчас это добавлю!
НЛО прилетело и опубликовало эту надпись здесь
0
SamDark #
Разрабатываться приложение может на маке или под виндой и там же хочется погонять профайлер.
0
jahson #
Можно пока и xdebug обойтись, пока пилят версию для osx )
+2
jahson #
Эээ. Пиджин? Оке.
Мая работать на маканама, сервер не ставить, не-е-е. Мая хотеть иметь возможность делать локальнама, патаму заводить nginx + mysql + php-fpm + memcache + memcachedb + xcache + sphinx на маканама. Всё работать нормальнама.
Но не всё радужный. Getopt только в php 5.3 будет отвязанама от реализации в OS, поэтому оченно хотеть ставит FreeBSD в Parallels (или Virtualbox) чтобы можно было работать нормальнама, да и заодно поднять опыт установки и настройки фряхи, чтобы быть умелее и умнее. Вот ещё и xhprof причинама, чтобы поставить в виртуалкунама.
0
jahson #
Нет, ну гетопт конечно можно нарисовать самому — и отвязаться от него до 5.3. Но остальное в силе — особенно про поднятие опыта.
0
Honeyman #
Фряху ставить? а она у вас поддерживается?? Поставте себе лучше Дебиан или РХЕЛ.

Одно другому не мешает. Debian/kFreeBSD :)
0
Arekus #
А это принципиально ответ передавать в XML? Не хотите попробовать JSON?
0
naoise #
это делаем не мы — Amazon
Мы бы сами с радостью бы получали все в JSON — кстати так мы и поступаем на собственных проектах предоставляющих внешнее апи.
Но эти Amazon в данном случае предпочитает именно XML — почему — загадка для нас.
В целом мы пока поняли что SimpleDB Амазон позиционирует именно для БОЛЬШИХ баз, когда время коннекта уже не так критично по сравнению с общей производительностью на большой посещаемости
0
svdesign #
Заменять имя домена на IP адрес это зря, резолвинг доменных имен кешится на уровне ОС. Использовать Keep-Alive даст наибольшую прибавку в производительности, может даже следует написать собственный класс в котором использовать одно соединение ($socket = @fsockopen) для нескольких запросов к SimpleDB.
0
naoise #
Да, спасибо большое за замечание, в погоне за миллисекундами мы уже и забыли о DNS-кэшах операционки. Надо в целом будет проверить нам как оно работает в конкретном случае — они ведь используют Round Robin — надеюсь все будет хорошо.
А Keep-Alive да именно так! И плюс еще DOMDocument-SimpleXML
0
AmdY #
DOMDocument-SimpleXML
не забудьте о CDATE
0
Q_Zma #
fsokopen можно ещё заменить на pfsokopen
0
zerkms #
round robin глупый и не учитывает загрузку узлов. не верю, что у амазона он.
0
DaemonI #
У меня на sdb.amazonaws.com резолвится всегда и везде один и тот же адрес.
0
zerkms #
ну мопед не мой :-)
я лишь попросил прокомментировать ситуацию автора коммента выше :-)
0
egorinsk #
>> … так-так-так, а сколько же времени уйдет на DNS-resolving.
> Заменив днс-имя на айпи адрес получаем выигрыш в 20 мс.

Неужели в Линуксе не кешируются ДНС-записи???? Позор!

Кстати, для профайлинга удобно использовать Xdebug. Резултаты можно просмотреть в норамлоьном GUI — WinCacheGrind.

0
DaemonI #
dhcpd3 кеширует все что угодно. Очень странно, что столько много времени уходило не резолв. Ведь кешировать DNS должны серваки провайдера.
0
DaemonI #
Извините, оговорился, bind9.
0
egorinsk #
Очевидно, 20 мс проходили в ожидании ответа от вечно занятых серваков. В любом случае, хранить маленький кеш на локальной машине выгоднее чем ждать ответа из сети.
0
Myarh #
А обещанный отчет о результатах продакшен-тестирования будет?
Очень интересно посмотреть.
Заранее спасибо!

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