| Представляю Вашему вниманию обзор высокоуровневой системной архитектуры социальной сети www.campus.ru,
разработки компании ООО «Креатив Медиа». На мой взгляд, данный материал
интересен тем, что позволяет оценить применимость рассмотренных
подходов и технологий в разработке интернет-ресурсов. По крайней мере,
когда наша компания начинала проект «Кампус», мне очень не хватало
подобной информации.
Социальная сеть Campus.ru помогает школьникам и студентам в построении
их будущей карьеры путем проведения специальных конкурсов от крупных
компаний-работодателей, организации прохождения производственных
практик и обучающих семинаров, а также посредством необходимого
функционала для общения, обмена информации и удовлетворения других
учебных нужды – например, составления учебного расписания. Функционал
Campus.ru преимущественно пересекается с функционалом привычных для нас
социальных сетей: зарегистрированные пользователи могут общаться,
собираться в сообщества, писать в блоги, размещать фотографии и т.д.
Однако, поскольку данная социальная сеть изначально ориентировалась на
школьников и студентов, некоторые вещи были реализованы специально с
учетом потребностей учащихся, например, «Учебный портфель» – папка для
хранения материалов, или «Планер» – сервис для составления учебного
расписания.
Обзор системной архитектуры начнем с информации о том, что Campus.ru
реализован на платформе Java. Судя по общей статистике, выбор платформы
Java в качестве инструмента реализации медийного Web-ресурса является
достаточно нестандартным решением, однако я выбрал именно эту платформу
исходя из следующих соображений:
• Мой предыдущий опыт разработки высоконагруженных, отказоустойчивых,
горизонтально масштабируемых приложений на Java был успешен.
• Java-сообществом накоплена огромная кодовая база качественных
библиотек и фреймворков с открытым исходным кодом, практически на все
случаи жизни.
• При формировании проектной команды «с нуля» найти на рынке труда
нескольких подходящих Java-разработчиков, обладающих необходимым
уровнем квалификации, опытом командной работы и знаниями в области
понимания архитектуры программного обеспечения (ОПП, Design Patterns)
проще, чем, например, для работы с Ruby (т.к. этот язык, по опыту
коллег, еще не достаточно широко распространен), или c PHP (по
собственному опыту, слишком много низкоквалифицированных кадров, на
отсев которых уходят без преувеличения месяцы).
Предполагая язвительные комментарии, касающиеся производительности
Java-приложений, замечу, что, принимая решение в пользу Java, я ясно
осознавал, что JVM – не самый быстрый и экономичный интерпретатор.
Однако, во-первых, JVM 6.0 действительно достаточно производителен для
нужд Web-приложения, а во-вторых, труд программистов сейчас дороже
стоимости железа, поэтому подолгу изобретать дорогие «велосипеды»,
которые позволяют выиграть 5%-10% производительности, для стартапа было
бы неразумно. Я придерживаюсь принципа «лучше быстро работать с
минимумом кода и красивой архитектурой, чем сэкономить 10% железа и
увязнуть в отладке».
Основным фреймворком проекта стал Tapestry 5. Выбор в пользу Tapestry 5 был сделан по ряду причин, основными из которых являются:
• Tapestry позволяет полностью разделить верстку и презентационную
логику. Нет необходимости добавлять в HTML специальные теги, не
интерпретируемые браузером, как в JSP. Это особенно важно, т.к.
Web-проект в большинстве случаев подразумевает сложную верстку,
которая, как правило, выполняется и поддерживается отдельным
специалистом. Кстати, в плане оптимизации верстки мы старались
соблюдать best practice.
• Содержит ряд архитектурных решений, нацеленных на высокопроизводительную работу, например, таких как Page Pool.
• Адекватная и стройная архитектура фреймворка, позволяющая
сосредоточиться на бизнес-логике приложения, а не на его конфигурации и
интегрировании компонентов друг с другом, благодаря широкому
использованию аннотаций и соглашений о наименовании, а также
встроенному IoC.
Поскольку ранее опыта работы с Tapestry 5 ни у кого из нас не было, в
первую очередь был написан тестовый прототип приложения и выполнено его
нагрузочное тестирование утилитой JMeter.
Тестирование показало быстрое время отклика, стабильную утилизацию
аппаратной платформы и отсутствие блокировок, после чего решение об
использовании Tapestry 5 было окончательно утверждено.
Исходя из сказанного выше, внутренняя архитектура Web-приложения
Campus.ru продиктована правилами разработки приложений под фреймворк
Tapestry 5.
Кроме Tapestry, наше Web-приложение использует следующие библиотеки:
• DOJO 1.0 – Javascript framework с AJAX
Выбор DOJO в качестве основного Javascript-фреймворка был продиктован
наличием в нем большого количества готовых элементов управления, в том
числе виджетов, а также тем, что DOJO позволяет выполнять все стилевое
преобразование компонентов на стороне клиента. При этом при первом
обращении к ресурсу загружается и кэшируются в браузере все необходимые
CSS- и Java-cкрипты, а затем с сервера грузятся только HTML-страницы с
разметкой минимального объема. Это значительно сокращает трафик и
нагрузку на сервер.
Кроме того, что немаловажно, у команды уже был опыт работы с DOJO ☺ Из
трудностей – интеграционную часть DOJO-Tapestry пришлось изобретать
самостоятельно; в перспективе планируем оформить ее в виде open
source-проекта и выложить в открытый доступ.
• SwfUpload 2 – Javascript компонент для загрузки файлов на сервер.
• Hibernate 3 – ORM Framework. Tapestry 5 прозрачно интегрируется с Hibernate. Для маппинга сущностей пользуемся аннотациями.
• Hibernate Search 3
– движок полнотекстового поиска на базе Lucene. Позволяет индексировать
содержимое сущностей Hibernate, удобно конфигурируется аннотациями в
сущностях. Может работать в кластере.
• Spring Security 2.0
– система аутентификации и авторизации, прозрачно интегрируется с
Tapestry 5, конфигурируется аннотациями. Имеет широкие возможности, но
подходящего нам механизма ACL для наложения персональных прав доступа
пользователя к объектам предметной области не нашлось, пришлось
придумывать свой. Планируем в перспективе выложить в виде open source
проекта.
• Quartz 1.6
– планировщик для выполнения фоновых и асинхронных операций. Длительные
операции, такие как рассылка почты, обработка файла на сервере, и пр.
мы стараемся реализовать в виде асинхронно выполняющегося действия,
чтобы не блокировать интерфейс пользователя на долгое время.
При удачном стечении обстоятельств количество пользователей (т.е.
количество запросов) социальной сети и объем связанных с пользователями
данных растет лавинообразно. В связи с этим очень важно было обеспечить
горизотальное масштабирование системы, а также достаточный уровень ее
отказоустойчивости. Эти цели были достигнуты как за счет наличия
избыточных аппаратных серверов для критических узлов системы, так и за
счет использования специального программного обеспечения на уровне ОС:
haproxy, hartbeat и пр. Так что аварий и болезней роста мы почти не
боимся ☺
Кстати, о программном обеспечении. В своей инфраструктуре Кампус использует:
• Nginx 0.6
– балансировщик нагрузки (HTTP-запросов) и HTTP-сервер для отдачи
статического контента (Javascript, CSS, иконки и пр.). Балансировка
HTTP-запросов на сервера приложений Tomcat настроена таким образом,
чтобы в течение одной сессии все запросы от одного пользователя
попадали бы на один экземпляр сервера Tomcat. Такая настройка
балансировки нагрузки называется sticky session. Это сделано для того
чтобы не реплицировать сессии пользователей между серверами Tomcat.
Плюс – экономия ресурсов и линейное горизонтальное масштабирование.
Минус – в случае отказа сервера, пользователю придется перелогиниться
на ресурсе.
• JDK 6 – набор средств разработки и виртуальная java-машина (JVM), на базе которой работает сервер J2EE-приложений.
• Tomcat 6
– сервер J2EE-приложений (J2EE контейнер для Web-приложений). Под его
управлением работает приложение Campus.ru. Мы не объединяли сервера
Tomcat в кластер из соображений сохранения возможностей линейного
горизонтального масштабирования на этом уровне.
• PostgreSQL 8.3
– версионная СУБД. Выбирали между MySQL и PostgreSQL. Остановились на
Postgres, проанализировав различные обзоры, блоги специалистов и
наличие утилит для кластеризации СУБД.
• PgPool-II 3.4
– балансировщик нагрузки и репликатор данных, используется для
объединения в кластер двух серверов PostgreSQL. Запросы на изменение
данных одновременно направляются на оба сервера БД, а запросы на чтение
– на один из серверов по очереди. Таким образом, нагрузка
распределяется между двумя машинами.
• PgBouncer 1.3
– легковесная система управления пулами соединений для PostgreSQL.
Одновременная обработка запросов пользователей большим количеством
серверов приложений требует поддержки большого количества соединений с
БД. PgBouncer тратит на поддержание каждого соединения около 2 Кб
памяти, и существенно снимает нагрузку с СУБД PostgreSQL. Таким
образом, JDBC-пулы на серверах Tomcat настроены на соединение с
PgBouncer, а не с PgPool. Дополнительным плюсом является то, что в
случае кратковременной недоступности БД (например, при быстром
перезапуске) PgBouncer будет продолжать попытки осуществить соединение
с БД, и если это получится до наступления установленного тайм-аута, то
сервера приложений даже не узнают о том, что БД была временно
недоступна.
• ActiveMQ 5.2
– JMS-сервер. Используется для асинхронного обмена JMS-сообщениями в
системе полнотекстового поиска Hibernate Search, сконфигурированной в
режиме JMS Master/Slave configuration (подробности здесь). Также используется для обмена информацией с подсистемой асинхронного выполнения задач на базе фреймворка Quartz.
• Sendmail – всем известный почтовый сервер. Используем для рассылок.
• Zabbix 1.6
– система мониторинга системной инфраструктуры. Осуществляет мониторинг
состояния JVM, Tomcat по протоколу JMX через интерфейсы MBeans.
Бесплатно мониторит до 30 хостов.
• Smssend
– пакет для FreeBSD, позволяющий отправлять SMS. Используем для
отправки SMS-сообщений системному администратору о проблемах на ресурсе.
• Chandler Server
– Open source Web-приложение, представляющее собой календарный сервер,
общающийся с внешним миром по открытому протоколу CalDav. Чтобы не
изобретать велосипед, мы используем данный сервер в нашем сервисе
«Планер» для хранения расписаний событий пользователей и сообществ.
• Amazone S3
– используется для надежного хранения файлов пользователей. Кроме того,
использование данного сервиса помогает снять нагрузку с серверов
приложений, т.к. файлы скачиваются пользователями напрямую с серверов
Амазона. Метаданные файлов при этом хранятся в БД «Кампуса».
Для работы с Амазоном есть клиентское Java API. Сервис платный, но для организации не дорогой. Если решите организовывать что-то подобное своими силами, рекомендую MogileFS, к ней тоже есть Java API.
• Fotki.com – фото-хостинг наших партнеров, обеспечивающий хранение и
конвертирование фотографий, загружаемых пользователями в фотоальбомы.
Загрузка фотографий в браузер опять же происходит напрямую с серверов
фотохостинга, что снимает нагрузку с серверов приложений Campus.ru.
Если бы пришлось конвертировать фото самим, я бы, наверное, смотрел в
сторону ImageMagick, Java API также прилагается.
Все вместе это работает следующим образом:
1) Запрос пользователя попадает на сервер балансировщика нагрузки.
Nginx проверяет, есть ли в запросе заголовок, содержащий информацию о
привязке пользователя к одному из серверов Tomcat. Если нет, то такой
заголовок добавляется, и запрос перенаправляется на соответствующий
сервер Tomcat. Первично сервер выбирается по принципу round-robin. Этот
механизм обеспечивает sticky session.
2) На сервере Tomcat генерируется динамический контент для
HTML-страницы, по сути – только данные, с минимальной стилевой
разметкой. Если для генерации страницы требуются данные из БД,
приложение Campus.ru берет соединение из JDBC-пула данного сервера.
Соединения в JDBC-пуле осуществляются с PgBouncer, который, в свою
очередь, устанавливает соединение с PgPool, а PgPool – с PostgreSQL.
Поскольку процесс установки соединений в JDBC-пуле происходит сразу при
старте сервера Tomcat, то во время работы приложения получение
соединения из пула работает очень быстро.
3) Если запрос пользователя меняет участвующую в полнотексовом поиске
информацию, то приложение отправляет JMS-сообщение поисковому серверу
Master Node, отвечающему за синхронизацию полнотекстовых индексов на
каждом из узлов кластера.
4) Контент HTML-страницы возвращается в браузер пользователя. После
этого браузер пользователя начинает загружать статический контент
(Javascript, CSS, изображения) с сервера Nginx, если этот контент еще
не закэширован браузером, а также фотографии и аватары с внешних
серверов фотохостинга.
5) Браузер пользователя применяет CSS- и Javascript-преобразования к
загруженному DOM-дереву и в итоге отрисовывает пользователю готовую
страницу.
Данная схема позволяет, во-первых, снизить нагрузку на сервер
приложений и минимизировать трафик, а, во-вторых, ускорить общую
загрузку страницы за счет преодоления ограничения браузера,
позволяющего загружать данные только по четырем потокам одновременно с
одного ресурса. Обратной стороной медали является побочный эффект,
наблюдаемый на старых браузерах типа IE 6, которые не успевают
применить все динамические стилевые преобразования к странице до
момента ее отображения, из-за чего пользователь может наблюдать, как
кривая страничка у него на глазах превращается в красивую. Кроме того,
первоначальная загрузка всех CSS- и Java-скриптов на медленных каналах
может потребовать некоторого времени.
Кстати, тут вспомнилась проблема с обновлением закэшированного
статического контента (CSS, JS) в браузере пользователя. Для ее решения
мы добавляем в URL статического ресурса номер его версии. Если в
скрипты вносятся изменения, меняется номер их версии в URL, и браузер
выкачивает с сервера обновленные файлы.
Чтобы сказанное выше легче уложилось в голове, на рисунке изображена
высокоуровневая диаграмма развертывания Web-приложения Campus.ru. Чтобы
не усложнять диаграмму, некоторые связи между компонентами не
изображены.
Figure 1. Диаграмма развертывания Campus.ru
Опыт показывает, что JVM эффективно работает с объемами памяти до 2 Гб,
с учетом рекомендации, говорящей, что на каждый экземпляр JVM на
сервере должно приходиться, по меньшей мере, два ядра процессора. Из
этих соображений, на каждом аппаратном сервере были развернуты по 4
экземпляра серверов приложений Tomcat. В каждом контейнере Tomcat были
развернуты Web-приложения Campus и Chandler. Нагручное тестирование
показало, что при произведенных настройках GC, данная конфигурация
позволяет практически линейно утилизировать аппаратные ресурсы при
росте нагрузки и выдавать при этом приемлемый результат по времени
отклика.
На всех аппаратных серверах приложения работают под управлением ОС
FreeBSD 7.1. Выбор в пользу FreeBSD, а не Linux, был сделан потому, что
при прочих равных, все Линуксы имеют свои особенности, и системным
администраторам было бы сложнее передавать знания друг другу. У нас в
компании все проекты пока работают на FreeBSD, поэтому он стал нечто
вроде корпоративного стандарта. Из минусов FreeBSD в Java-проекте – Sun
не выпускает JDK для FreeBSD, а порты под FreeBSD запаздывают
относительно обновлений Sun. Также в портах JDK есть не все отладочные
утилиты.
Отказоустойчивость на серверах-балансировщиках нагрузки реализована посредством утилиты HAProxy.
Аппаратные сервера «Кампуса» имеют следующую конфигурацию:
1) Сервера для балансировки нагрузки и отдачи статического контента:
CPU Intel Xeon Dual Core 2.67GHz RAM DDR 2 8Gb HDD 4xSAS 73gb 15000 rpm
2) Сервера для развертывания Web-приложения:
CPU 2xIntel Xeon Quad Core 2.66GHz RAM DDR 2 16Gb HDD 4xSATA 300gb 15000 rpm
Главный принцип при выборе сервера для Web-приложения – чем больше ядер/процессоров и оперативной памяти – тем лучше.
3) Сервера для БД:
CPU 2xIntel Xeon Quad Core 2.66 GHz RAM DDR 2 16Gb HDD 8xSAS 147gb 15000 rpm
Главный принцип при выборе сервера для БД с расчетом на работу с
большими объемами данных – чем больше дисков и чем они быстрее, тем
лучше. Обязательно наличие аппаратного RAID. Затем по приоритетам идет
оперативная память, за ними – процессоры.
Сервера хостятся в дата-центре крупного московского интернет-провайдера за аппаратным файрволом от Cisco.
В заключение хочется сказать, что, несморя на большие объемы
проделанной работы, нам еще есть что совершенствовать. Например, в
связи с выходом IE 8 мы наметили болезненный переход на DOJO 1.3. Также
мы планируем сделать верстку сайта более легкой (убрав тени,
полупрозрачность и лишние округлости) в связи с тем, что учащиеся в
регионах по факту имеют в школах/вузах канал в 128Кбит/сек и IЕ 6. В
самых ближайших планах реализовать кэширование данных на базе
проверенного распределенного кэша Memcached.
Также у нас на сегодняшний день не решен вопрос шардинга данных, если
вдруг объем данных начнет угрожающе расти. Поэтому в перспективе мы
намерены исследовать Hibernate Shards, PLProxy и другие средства. Если
у кого-то есть практический опыт и желание им поделиться – буду очень
рад.
В следующей статье, если поддержите, я планирую рассказать об управлении проектом «Кампус» и о нашей команде ☺
Спасибо за внимание!
Технический директор ООО «Креатив Медиа»
Сергей Седов
Опубликовано с разрешения Генерального директора компании ООО «Креатив Медиа» Ивана Соколова
|
|