Обзор системной архитектуры социальной сети Campus.ru
Представляю Вашему вниманию обзор высокоуровневой системной архитектуры социальной сети 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, PL\Proxy и другие средства. Если у кого-то есть практический опыт и желание им поделиться – буду очень рад.
В следующей статье, если поддержите, я планирую рассказать об управлении проектом «Кампус» и о нашей команде ☺
Спасибо за внимание!
Технический директор ООО «Креатив Медиа»
Сергей Седов
Опубликовано с разрешения Генерального директора компании ООО «Креатив Медиа» Ивана Соколова
Социальная сеть 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, PL\Proxy и другие средства. Если у кого-то есть практический опыт и желание им поделиться – буду очень рад.
В следующей статье, если поддержите, я планирую рассказать об управлении проектом «Кампус» и о нашей команде ☺
Спасибо за внимание!
Технический директор ООО «Креатив Медиа»
Сергей Седов
Опубликовано с разрешения Генерального директора компании ООО «Креатив Медиа» Ивана Соколова
комментарии (133)
Вопрос — а что Вы рассматривали в качестве альтернативы Tapestry, если рассматривали?
Hibernate Shards сейчас еще сырой, было бы интересно прочесть ваше мнение по поводу его применимости.
Буду ждать новостей от вас по этой теме на Хабре.
Да, с шардингом будем ближе к делу обмозговывать что к чему, возможно как-нибудь PL\Proxy красиво обойдемся.
Спасибо за +1 :)
К примеру, там вместо рекурсивного обхода дерева компонент реализован обход оптимизированного автомата состояний, что дает дает существенный выигрыш. Смотрите его блог — Speeding up Tapestry 5.1
С другой стороны, для относительно небольшой аудитории (приблизительное использование HttpSession на пользователя 10-200 килобайт) и сайта со сложной динамической структурой, Wicket очень хорош.
По большому счету, мы еще оптимизацией не занимались, но когда руки дойдут, будем рассматривать переход на Jetty как один из путей оптимизации.
Скажите, а на какие конкретно нагрузки вы сейчас рассчитываете?
При дальнейшем увеличении нагрузки на серверах приложений сильно возрастали накладные расходы на сборку мусора, и потихоньку начинали копиться очереди запросов. Так что еще есть что тюнинговать, но пока это для нас не первоприоритетная задача, так как таких нагрузок у нас еще нет, а реальный профиль нагрузки скорее всего будет существенно отличаться от нашего синтетического. Ждем реальную статистику.
По поводу sticky session, у вас используется, потому что вы храните информацию залогиненого пользователя в сессии томката? Если так то я бы отказался от этого, потому что как показывает практика хранение объектов в сессии ведет к неспособности приложения жить под нагрузкой.
По синтетическому тесту — не соглашусь, у нас он более жестокий, нежели пользователи. Практически все сценарии — на обновление данных, хотя в реальности люди гораздо больше читают и качают, чем пишут и загружают.
У нас в сессии лежит минимум данных, в основном аутентификационная информация. В подавляющем большинстве случаев у нас используется активационный контекст Tapestry, позволяющий хранить состояние в URL.
Сколько по вашем оценкам это одновременных пользователей?
Сложно жесткий синтетический тест перевести в реальных пользователей, так вот навскидку даже и не скажу. Со временем соберем статистику запросов, усредним и тогда подсчитаем :)
Руководство это заказчики? Просто обычно «сразу делать хорошо и надолго» от инвесторов редко услышишь.
Да, нам действительно повезло с инвесторами :)
ну или хотя бы планируемый срок окупаемости?
можете разгласить, когда вы планируете получить прибыль?
На что обратить внимание при осмотре?
Начнем с простого:
1. Расписания на кампусе выглядят в виде добавления событий, что неправильно.
Scribbler: редактирование расписаний вынесено в отдельную сущность сайта.
2. Загружать можно файлы объемом не более 30Мб, а что делать если вдруг нужно выложить видео-лекцию?
Scribbler: рабочий стол.
3. Wiki-учебник ведет на какой то сайт letopisi.ru, вот этого я не понимаю, зачем, лучше было бы убрать этот пункт, до тех пор пока не запрогали что то внутри проекта.
Scribbler: коллективная работа с документами есть, что будет потом не могу сказать, но будет круто.
4. На сайте есть что нибудь повесомей кампусов (сообществ)?
Scribbler: Основная еденица — группа, сообщеста — круг людей по интересам.
5. Как мне отследить активность друзей?
Scribbler: Лента активности
6. Какова миссия проекта campus.ru, создавать кампусы?Scribbler: помочь студенту в учебе, в плане учебы
7. Работа — это джоб сервис или ссылки на сайты с работой?
Scribbler: будет джоб сервис.
В общем архитектура сайта, наверно, и отличная, но я не понимаю, какова цель проекта.
Был такой проект studbox.ru, но он почему-то теперь закрыт, решал больше задач, чем в данный момент campus.ru, надеюсь, со временем функционал пополнится.
Java, конечно, тоже хорошо, тоже думали начинать программировать на этом языке, но если очень сильно постараться, то можно найти хороших PHP-программистов, что облегчит разработку и поддержку проекта.
по поводу Dojo, благодаря тому, что в нем дофигища всего готово, он тяжелый, потому стоило бы взглянуть в сторону mootools или jquery, и самим дописать, то, что нужно.
Я не хочу говорить, что кампус плохой, просто смотрю на факты, это просто мое личное мнение.
З.Ы. И зачем такой большой прелоадер?!
мыло в личку.
На другие почтовые сервера все доходит без проблем.
И раз уж от скриблеров тоже ничего не пришло — думается мне, что действительно что то с DNS на вашем сервере.
Странно, он обычные письма ходят нормально. Да и от проектов разных тоже. Но если удобно — можете переписать ящик на devgru@mail.ru
1. Расписания на кампусе выглядят в виде добавления событий, что неправильно.
Scribbler: редактирование расписаний вынесено в отдельную сущность сайта.
Campus: планируем доделать, у Вас действительно интерфейс для забивания расписания удобнее
2. Загружать можно файлы объемом не более 30Мб, а что делать если вдруг нужно выложить видео-лекцию?
Scribbler: рабочий стол.
Campus: Нужно будет просто нам об этом сказать, пока никто не жаловался. Ограничение выставлено искусственно.
3. Wiki-учебник ведет на какой то сайт letopisi.ru, вот этого я не понимаю, зачем, лучше было бы убрать этот пункт, до тех пор пока не запрогали что то внутри проекта.
Scribbler: коллективная работа с документами есть, что будет потом не могу сказать, но будет круто.
Campus: А зачем изобретать велосипед? letopisi.ru — тоже наш проект, а Wiki — удобная и привычная всем среда для коллективного творчества. А я могу рассказать, что мы, когда дойдут руки, наверное интегрируемся с Google Apps, но востребованность этой фичи пока минимальная. Мы обычно планируем функционал исходя из этого критерия.
4. На сайте есть что нибудь повесомей кампусов (сообществ)?
Scribbler: Основная еденица — группа, сообщеста — круг людей по интересам.
Campus: Весомее?? Не понял вопрос. А что у Вас тяжелее — группа или сообщество? У нас есть учебные заведения, например.
5. Как мне отследить активность друзей?
Scribbler: Лента активности
Campus: Тоже. «Что нового»
6. Какова миссия проекта campus.ru, создавать кампусы?
Scribbler: помочь студенту в учебе, в плане учебы
Campus: помощь в построении карьеры, начиная со школьной скамьи. Я же говорил, что мы на разных полях играем.
7. Работа — это джоб сервис или ссылки на сайты с работой?
Scribbler: будет джоб сервис.
Campus: можно сказать что пока ссылки с на партнерский сайт. Тоже когда-нибудь доведем до ума, если будет потребность.
В общем архитектура сайта, наверно, и отличная, но я не понимаю, какова цель проекта.
Campus: Спасибо, см. п.6
Был такой проект studbox.ru, но он почему-то теперь закрыт, решал больше задач, чем в данный момент campus.ru, надеюсь, со временем функционал пополнится.
Campus: конечно! но действуем мы не по принципу чтобы сделать максимальное кол-во фич, а по принципу — делаем то, что требуется для достижения бизнес-задачи в данный момент времени (agile)
Java, конечно, тоже хорошо, тоже думали начинать программировать на этом языке, но если очень сильно постараться, то можно найти хороших PHP-программистов, что облегчит разработку и поддержку проекта.
Campus: конечно можно, ведь язык — это просто инструмент, главное — профессионализм команды. И на бейсике, я уверен, можно очень неплохой код писать.
по поводу Dojo, благодаря тому, что в нем дофигища всего готово, он тяжелый, потому стоило бы взглянуть в сторону mootools или jquery, и самим дописать, то, что нужно.
Campus: Тут у Вас какая-то подмена понятий получается. DOJO — фреймворк, jQuery и mootools — библиотеки. Почитайте обзоры. А самим дописывать, см. пословицу время=деньги.
Я не хочу говорить, что кампус плохой, просто смотрю на факты, это просто мое личное мнение.
Campus: Спасибо за Ваше мнение! Конечно, никому не надо говорить, что он плохой, живите в позитивной парадигме с менталитетом достаточности! ;)
З.Ы. И зачем такой большой прелоадер?!
Campus: Так получилось :)
habrahabr.ru/blogs/web_optimizator/
на какой-нибудь Java-фреймворк? Или придется писать сишный модуль к nginx?
многие фреймворки (например, GWT) делают многое из этого сами.
для остальных подойдёт просто servlet filter, который нужно будет подключить в web.xml оптимизируемого приложения
но не думаю, что для Java-приложений подобная оптимизация будет действительно эффективной — как правило они либо «правильные» с самого начала (пишут опытные люди), либо сильно «испорчены» тяжеловесными фреймворками вроде Seam.
Опять же, если перед Tomcat'ом поставить Apache/AJP13, то часть apache-оптимизаций может сработать сразу
показалась длинной
мой адблок блокировал аяксовый запрос, suggest названия вуза вроде
проверка свободности логина должна быть при его вводе, а не где-то в заднице
рабочий стол:
слишком много блоков на «рабочем столе», какая-та глупая тень у них и слишком большие промежутки между ними
слишком большие заголовки
зачем нужно было делать пункты меню «мои ....» жирным?
анимированная реклама — ппц
юзерпики по умолчанию не понравились
в верхнем меню есть галочки, но меню не выпадают
«Профиль заполнен на», непонятная тень у чисел с процентами
не нашел хелпа
Покажите мне хоть что-то для начала, заинтересуйте меня, заинтригуйте хотя бы и тогда я, возможно, зарегистрируюсь и даже, возможно, вернусь на ваш ресурс… а так — я его просто закрыл.
# Обменивайся
учебными материалами
# Не пропускай
события! Учебные
или личные.
# Общайся с друзьями,
не покидая сайт.
# Ищи работу
по специальности.
# Твои фото-, видео-,
и аудиогалереи.
Было-бы разумно сделать ссылками на какие-нибудь демки хотябы… А так только раздражает что пытаешься по ним тыкать а они не реагируют(
Допустим: gr*(6Rjhoi*&$%@_hto3&$%a.
Да, я параноик.
А ещё жутко вымораживает ограничение длины логина странными минимумами и максимумами, основанными по всей видимости на том, что у авторов ник не слишком длинный и не слишком короткий.
Ограничение логина так же из-за сервисов, где он используется (фотохостинг, файловый хостинг, календарный сервер и т.д).
>Мы можем горизонтально масштабироваться без остановки сервиса по мере необходимости.
Вы пробовали? ;)
Пробовали, конечно.
PS Название блога.
т.е. у нас нет, к примеру, запросов, выполняемых на сервере, которые меняют сиквенс.
Не могли бы вы объяснить откуда эти данные, и как вы это проверяли?
Как уже говорилось выше — 279к 1!!! файл css — это жестоко :(
Общий вес стартовой страницы почти 1мб — это чересчур для того, что на ней есть. Оно конечно закешируется, но все же…
У меня пропадет желание регистрироваться в ожидании стартовой страницы.
Вынесите загрузку javascript и css в другое место.
P.S. вот так и появляются легенды о тормозах Java веб-приложений.
Насколько обоснованно было бы использовать Java EE в Вашем случае, как считаете?
У вас есть Tomcat, который контейнер сервлетов, есть JMS и Hibernate. В тексте я заметил, что вы упоминали авторизацию (которая всяко имеет отношение к JAAS). Хотел узнать, не складываются ли эти вещи в Java EE :)
Сильно не пинайте, я недавно в Java EE, вот и стараюсь разобраться :)
Использовать «классический» стек JEE (JSF+EJB) мы изначально не стали, из соображений плохого разделения верстки и презентационной логики, отсутствия IoC, да и, что греха таить, из соображений производительности. Tapestry 5 — ощутимо быстрее и менее ресурсоемка чем JSF. См. производительность Tapestry vs Seam.
П.С. Spring Security не имеет отношения к JAAS. Spring Serurity может использовать JAAS.
P.S. Давайте делиться мыслями, дружить, осознавая, что мы не конкуренты — воздуха и интернета на всех хватит! :)
Думаю, что с таким подходом будущее окажется действительно светлым
как-то пытался сетапить вовзу на 64х битную фрю, намучался, в итоге падучее оказалось, в интернетах пишут, что жава на фре плоха, а на 64х битной фре — еще хуже
сейчас — октябрь '11
проект — «все»?