агрегатор xml фидов

74 views
Skip to first unread message

Tim Rulanov

unread,
Aug 7, 2013, 8:43:59 AM8/7/13
to nxwe...@googlegroups.com
для определенных задач понадобилось реализовать агрегатор xml фидов, который получая запрос на фронтэнд делает десяток-другой подзапросов на другие хосты, получает ответы в xml, парсит их сортирует и финально отдает итог клиенту. 
за базу решил взять модуль ssi_filter но появились несколько вопросов

- как происходит обработка подзапросов? они выполняются в очередности добавления или выполняются параллельно?
- что если один или несколько хостов долго не ответят или разорвут соединение?
- немного непонятно что происходит с результатами вызова подзапросов. финальный ответ клиенту собирается после завершения всех запросов или сразу, в потоке пишется в сокет?

заранее спасибо, 

Yaroslav

unread,
Aug 7, 2013, 9:29:52 AM8/7/13
to nxwe...@googlegroups.com



2013/8/7 Tim Rulanov <tibe...@gmail.com>

для определенных задач понадобилось реализовать агрегатор xml фидов, который получая запрос на фронтэнд делает десяток-другой подзапросов на другие хосты, получает ответы в xml, парсит их сортирует и финально отдает итог клиенту. 
за базу решил взять модуль ssi_filter но появились несколько вопросов

- как происходит обработка подзапросов? они выполняются в очередности добавления или выполняются параллельно?

SSI-код (код, включающий директивы <!--#include -->) может поступать из разных источников: файл, прокси, питон, любой пользовательский хандлер. Может поступать сразу целиком, а может и по частям с паузами (в случае с прокси). Это важно для понимания.

SSI-фильтр начинает работать, не дожидаясь получения полного SSI-кода. Принимая очередной фрагмент данных, он сканирует его в поисках SSI-директив. Как только он их находит, он:
- отправляет клиенту как есть фрагмент текста до директивы, точнее ставит его в очередь на отправку клиенту
- формирует подзапрос в соответствии с директивой, а также ставит в очередь на отправку клиенту результат обработки этого подзапроса

Очередь отправки - это то, что называется composite stream.

Таким образом, подзапросы выполняются параллельно, причем стартуют, не дожидаясь получения полного SSI-кода.
 
- что если один или несколько хостов долго не ответят или разорвут соединение?

Это приведет к сбою подзапроса. Вместо результата неудавшегося подзапроса будет вставлена строка "<!--[ssi error]-->".
 
- немного непонятно что происходит с результатами вызова подзапросов. финальный ответ клиенту собирается после завершения всех запросов или сразу, в потоке пишется в сокет?

Сразу в потоке пишется в сокет. В порядке очереди, разумеется.

Резюме. Так как для агрегации фидов их нужно сначала собирать и парсить, модель SSI-фильтра не подходит.

Подходит модель templates_filter - вот он сначала собирает все результаты подзапросов, затем строит на их основе свой ответ.

Мнение. Лично я не стал бы решать подобную задачу на Си. Фиды можно собирать и агрегировать скриптом по крону. А результат агрегации - статический файл - можно отдавать чем угодно. Это будет не просто быстро, а очень быстро. Никаких задержек из-за отключившихся бекендов. Но данные будут чуток не актуальны. Насколько это вам критично?

Tim Rulanov

unread,
Aug 7, 2013, 2:48:07 PM8/7/13
to nxwe...@googlegroups.com
Спасибо за подробный ответ. Теперь разобраться в коде гораздо проще.


Мнение. Лично я не стал бы решать подобную задачу на Си. Фиды можно собирать и агрегировать скриптом по крону. А результат агрегации - статический файл - можно отдавать чем угодно. Это будет не просто быстро, а очень быстро. Никаких задержек из-за отключившихся бекендов. Но данные будут чуток не актуальны. Насколько это вам критично?


К сожалению производительность очень критична. Каждый запрос к xml фиду динамический, с параметром. И соответственно каждый ответ уникален. Кешировать нельзя. Скорее всего один сервер не справится с количеством запросов но и плодить излишние фермы серверов тоже не хотелось бы. Поэтому сейчас исследую возможности выжать из одной железяки по максимуму с возможностью масштабирования.

Попадалась на глаза статья на Хабре. Там упоминалось что предыдущая версия Nxweb была на основе libev, но производительность страдала. Если не секрет, что именно в libev рубило скорость работы? За последний месяц перекопал исходники многих производительных фреймворков и не только ( libevent, libev, varnish, libsxe, libuv, haproxy, redis, memcached) В голове теперь кавардак. Везде есть плюсы и минусы. Самый мрак когда слишком много лишнего кода чтобы обвернуть системные вызовы...
В Varnish нашел упоминание в комментариях что epoll криво работает под нагрузкой
/* XXX: EPOLLET (edge triggered) can cause rather Bad Things to
* XXX: happen: If NEEV+1 threads get stuck in write(), all threads
* XXX: will hang. See #644.
*/
не попадалась такая проблема?

еще интересно, насколько nxweb прожорлив к памяти? Как я понял, nxweb работает в продакшене как банерокрутилка. если не секрет, какие показатели по потреблению памяти и сколько реально соединений можно вытянуть на одном сервере?

Yaroslav

unread,
Aug 7, 2013, 5:13:50 PM8/7/13
to nxwe...@googlegroups.com



2013/8/7 Tim Rulanov <tibe...@gmail.com>

Спасибо за подробный ответ. Теперь разобраться в коде гораздо проще.


Мнение. Лично я не стал бы решать подобную задачу на Си. Фиды можно собирать и агрегировать скриптом по крону. А результат агрегации - статический файл - можно отдавать чем угодно. Это будет не просто быстро, а очень быстро. Никаких задержек из-за отключившихся бекендов. Но данные будут чуток не актуальны. Насколько это вам критично?


К сожалению производительность очень критична. Каждый запрос к xml фиду динамический, с параметром. И соответственно каждый ответ уникален. Кешировать нельзя. Скорее всего один сервер не справится с количеством запросов но и плодить излишние фермы серверов тоже не хотелось бы. Поэтому сейчас исследую возможности выжать из одной железяки по максимуму с возможностью масштабирования.


Обращения к фиду происходят так часто? Сам бог велел тогда кешировать. Действительно ли так уникальны ответы? Может, параметр можно подставить в результат уже после агрегации?
 
Попадалась на глаза статья на Хабре. Там упоминалось что предыдущая версия Nxweb была на основе libev, но производительность страдала. Если не секрет, что именно в libev рубило скорость работы? За последний месяц перекопал исходники многих производительных фреймворков и не только ( libevent, libev, varnish, libsxe, libuv, haproxy, redis, memcached) В голове теперь кавардак.

Про libev у меня только положительные отзывы. httpress до сих пор работает на нем. Я предполагал, что минусом являлось отсутствие поддержки epoll в режиме Edge Triggered, поэтому я написал свой event loop. До сих пор не уверен, что именно уход libev обеспечил новый выигрыш в скорости, так как параллельно с переписыванием обработчика событий я оптимизировал также и многое другое в nxweb.
 
Везде есть плюсы и минусы. Самый мрак когда слишком много лишнего кода чтобы обвернуть системные вызовы...
В Varnish нашел упоминание в комментариях что epoll криво работает под нагрузкой
/* XXX: EPOLLET (edge triggered) can cause rather Bad Things to
* XXX: happen: If NEEV+1 threads get stuck in write(), all threads
* XXX: will hang. See #644.
*/
не попадалась такая проблема?

Не сталкивался. Некоторые особенности обнаружились, но все они описаны в документации, и глюками не являются. Не исключено, что эти комментарии связаны с архитектурой Varnish. Быть может, она плохо вписывается в идеологию EPOLLET.
 

еще интересно, насколько nxweb прожорлив к памяти? Как я понял, nxweb работает в продакшене как банерокрутилка. если не секрет, какие показатели по потреблению памяти и сколько реально соединений можно вытянуть на одном сервере?

Одно соединение в режиме keep-alive (не обслуживающее в текущий момент запросов) требует ~2Кб; в процессе обработки запроса - минимум 3-4Кб, но может быть и намного больше в зависимости от обработчика запроса и размера ответа, буферизуемого в памяти.

Предел наступает отнюдь не из-за нехватки памяти (хотя зависит от обработчика). Кроме памяти довольно быстро заканчиваются файловые дескрипторы и TCP-порты (в IPv4 портов не может быть в принципе выделено больше 65 тыс.). Только что прогнал бенчмарк на 30 тыс. соединений с небольшим количеством ошибок. В пике наверное можно достичь 40-50 тыс., но очень сомневаюсь, что удастся держать столько постоянно.

Вообще на практике мне пока не удавалось загрузить nxweb даже до десятой части предполагаемого максимума. Недостаточно трафика. Буду рад, если кто-то попробует и поделится впечатлениями.
 

--
Вы получили это сообщение, поскольку подписаны на группу nxweb-ru.
 
Чтобы отказаться от подписки на эту группу и перестать получать из нее сообщения, отправьте электронное письмо на адрес nxweb-ru+u...@googlegroups.com.
Настройки подписки и доставки писем: https://groups.google.com/groups/opt_out.
 
 

Robert Ayrapetyan

unread,
Oct 7, 2013, 3:18:33 PM10/7/13
to nxwe...@googlegroups.com
 С удовольствием бы протестировал nxweb на большом кол-ве трафа (подозреваю, что у товарища выше его тоже предостаточно и даже источники те же :))
если вы вернете libev: все мои сервера на freebsd, там с epoll никак.

среда, 7 августа 2013 г., 14:13:50 UTC-7 пользователь Yaroslav написал:
Reply all
Reply to author
Forward
0 new messages