<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Insight IT</title><link>https://www.insight-it.ru/</link><description></description><atom:link href="https://www.insight-it.ru/tag/tomcat/feed/index.xml" rel="self"></atom:link><lastBuildDate>Tue, 22 Mar 2011 00:17:00 +0300</lastBuildDate><item><title>Архитектура Одноклассников</title><link>https://www.insight-it.ru//highload/2011/arkhitektura-odnoklassnikov/</link><description>&lt;p&gt;Сегодня представители &lt;a href="https://www.insight-it.ru/goto/2c99aef2/" rel="nofollow" target="_blank" title="http://www.odnoklassniki.ru"&gt;Одноклассников&lt;/a&gt;
рассказали о накопленном за 5 лет опыте по поддержанию высоконагруженного
проекта. Была опубликована довольно детальная информация о том, как
устроена эта социальная сеть для аудитории "постарше". Далее можно
прочитать мою версию материала, либо перейти на оригинал &lt;a href="https://www.insight-it.ru/goto/b762a864/" rel="nofollow" target="_blank" title="http://habrahabr.ru/company/odnoklassniki/blog/115881/"&gt;по сссылке&lt;/a&gt;.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2 id="platforma"&gt;Платформа&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/tag/windows/"&gt;Windows&lt;/a&gt; и &lt;a href="/tag/opensuse/"&gt;openSUSE&lt;/a&gt; - основные
    операционные системы&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/java/"&gt;Java&lt;/a&gt; - основной язык программирования&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/c/"&gt;С/С++&lt;/a&gt; - для некоторых модулей&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/gwt/"&gt;GWT&lt;/a&gt; - реализация динамического веб-интерфейса&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/tomcat/"&gt;Apache Tomcat&lt;/a&gt; - сервера приложений&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/jboss/"&gt;JBoss 4&lt;/a&gt; - сервера бизнес-логики&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/lvs/"&gt;LVS&lt;/a&gt; и &lt;a href="/tag/ipvs/"&gt;IPVS&lt;/a&gt; - балансировка нагрузки&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/mssql/"&gt;MS SQL 2005 и 2008&lt;/a&gt; - основная СУБД&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/berkleydb/"&gt;BerkleyDB&lt;/a&gt; - дополнительная СУБД&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/lucene/"&gt;Apache Lucene&lt;/a&gt; - индексация и поиск текстовой
    информации&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="statistika"&gt;Статистика&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;До 2.8 млн. пользователей онлайн в часы пик&lt;/li&gt;
&lt;li&gt;7,5 миллиардов запросов в день (150 000 запросов в секунду в часы
    пик)&lt;/li&gt;
&lt;li&gt;2 400 серверов и систем хранения данных, из которых 150 являются
    веб-серверами&lt;/li&gt;
&lt;li&gt;Сетевой трафик в час пик: 32 Gb/s&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="oborudovanie"&gt;Оборудование&lt;/h2&gt;
&lt;p&gt;Сервера используются двухпроцессорные с 4 ядрами, объемом памяти от 4 до
48 Гб. В зависимости от роли сервера данные хранятся либо в памяти, либо
на дисках, либо на внешних системах хранения данных.&lt;/p&gt;
&lt;p&gt;Все оборудование размещено в 3 датацентрах, объединенных в оптическое
кольцо. На данный момент на каждом из маршрутов пропускная способность
составляет 30Гбит/с. Каждый из маршрутов состоит из физически
независимых друг от друга оптоволоконных пар, которые агрегируются в
общую &amp;ldquo;трубу&amp;rdquo; на корневых маршрутизаторах.&lt;/p&gt;
&lt;p&gt;Сеть физически разделена на внутреннюю и внешнюю, разные интерфейсы
серверов подключены в разные коммутаторы и работают в разных сетях. По
внешней сети HTTP сервера, общаются с Интернетом, по внутренней сети все
сервера общаются между собой.&amp;nbsp;Топология внутренней сети &amp;ndash; звезда.
Сервера подключены в L2 коммутаторы (access switches), которые, в свою
очередь, подключены как минимум двумя гигабитными линками к aggregation
стеку маршрутизаторов. Каждый линк идет к отдельному коммутатору в
стеке. Для того, чтобы эта схема работала, используется
протокол&amp;nbsp;&lt;a href="https://www.insight-it.ru/goto/a03e0548/" rel="nofollow" target="_blank" title="http://ru.wikipedia.org/wiki/RSTP"&gt;RSTP&lt;/a&gt;. При необходимости,
подключения access коммутаторов к agregation стеку осуществляются более
чем двумя линками с использованием link aggregation портов.&amp;nbsp;Aggregation
коммутаторы подключены 10Гб линками в корневые маршрутизаторы, которые
обеспечивают как связь между датацентрами, так и связь с внешним
миром.&amp;nbsp;Используются коммутаторы и маршрутизаторы от компании Cisco.&lt;/p&gt;
&lt;p&gt;Для связи с внешним миром используются прямые подключения с несколькими
крупнейшими операторами связи, общий сетевой&amp;nbsp;трафик в часы пик доходит
до 32Гбит/с.&lt;/p&gt;
&lt;h2 id="arkhitektura"&gt;Архитектура&lt;/h2&gt;
&lt;p&gt;Архитектура проекта имеет традиционную многоуровневую структуру:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;презентационный уровень;&lt;/li&gt;
&lt;li&gt;уровень бизнес-логики;&lt;/li&gt;
&lt;li&gt;уровень кэширования;&lt;/li&gt;
&lt;li&gt;уровень баз данных;&lt;/li&gt;
&lt;li&gt;уровень инфраструктуры (логирование, конфигурация и мониторинг).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Код проекта в целом написан на Java, но есть исключения в виде модулей
для кэширования на C и C++.
Java был выбран так как он является удобным языком для разработки,
доступно множество наработок в различных сферах, библиотек и opensource
проектов.&lt;/p&gt;
&lt;h3 id="prezentatsionnyi-uroven"&gt;Презентационный уровень&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Используем собственный фреймворк, позволяющий строить композицию
    страниц на языке Jаvа, с использованием собственные GUI фабрик (для
    оформления текста, списков, таблиц и портлетов).&lt;/li&gt;
&lt;li&gt;Страницы состоят из независимых блоков (обычно портлетов), что
    позволяет обновлять информацию на них частями с помощью AJAX
    запросов.&lt;/li&gt;
&lt;li&gt;При данном подходе одновременно обеспечивается минимум перезагрузок
    страниц для пользователей с включенным JavaScript, так и полная
    работоспособность сайта для пользователей, у которых он отключен.&lt;/li&gt;
&lt;li&gt;Google Web Toolkit используется для реализации функциональные
    компонент, таких как Сообщения, Обсуждения и Оповещения, а также все
    динамических элементов (меню шорткатов, метки на фотографиях,
    сортировка фотографий,&amp;nbsp;ротация подарков и.т.д.).&amp;nbsp;В GWT используются
    UIBinder и HTMLPanel для создания интерфейсов.&lt;/li&gt;
&lt;li&gt;Кешируются все внешние ресурсы (Expires и Cache-Control заголовки).
    CSS и JavaScript файлы минимизируются и сжимаются (gzip).&lt;/li&gt;
&lt;li&gt;Для уменьшения количества HTTP запросов с браузера, все JavaScript и
    CSS файлы объединяются в один. Маленькие графические изображения
    объединяются в спрайты.&lt;/li&gt;
&lt;li&gt;При загрузке страницы скачиваются только те ресурсы, которые на
    самом деле необходимы для начала работы.&lt;/li&gt;
&lt;li&gt;Никаких универсальных CSS селекторов. Стараются не использовать
    типовые селекторы (по имени тэга), что повышает скорость отрисовки
    страниц внутри браузера.&lt;/li&gt;
&lt;li&gt;Если необходимы CSS expressions, то пишутся &amp;laquo;одноразовые&amp;raquo;. По
    возможности избегаются фильтры.&lt;/li&gt;
&lt;li&gt;Кешируется обращения к DOM дереву, а так же свойства элементов,
    приводящие к reflow. Обновляется DOM дерево в &amp;laquo;оффлайне&amp;raquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="uroven-biznes-logiki_1"&gt;Уровень бизнес-логики&lt;/h2&gt;
&lt;p&gt;На уровне бизнес логики располагаются около 25 типов серверов и
компонентов, общающихся между собой через удаленные интерфейсы. Каждую
секунду происходит около 3 миллионов удаленных запросов между этими
модулями.
Сервера на уровне бизнес логики разбиты на группы. Каждая группа
обрабатывает различные события. Есть механизм маршрутизации событий, то
есть любое событие или группу событий можно выделить и направить на
обработку на определенную группу серверов.&amp;nbsp;При общении серверов между
собой используется свое решение, основанное на&amp;nbsp;&lt;a href="https://www.insight-it.ru/goto/cba3bf92/" rel="nofollow" target="_blank" title="http://jbossremoting.jboss.org/"&gt;JBoss
Remoting&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="uroven-keshirovaniia"&gt;Уровень кэширования&lt;/h2&gt;
&lt;p&gt;Для кэширования данных используется самописный модуль
odnoklassniki-cache. Он предоставляет возможность хранения данных в
памяти средствами Java Unsafe. Кэшируются все данные, к которым
происходит частое обращение, например: профили пользователей, списки
участников сообществ, информация о самих сообществах, граф связей
пользователей и групп, праздники, мета информация о фотографиях и многое
другое.Для хранения больших объемов данных в памяти используется память
Java off heap memory для снятия ненужной нагрузки с сборщика
мусора.&amp;nbsp;Кеши могут использовать локальный диск для хранения данных, что
превращает их в высокопроизводительный сервер БД.&amp;nbsp;Кеш сервера, кроме
обычных операций ключ-значение, могут выполнять запросы по данным,
хранящимся в памяти, минимизируют таким образом передачу данных по сети.
Используется map-reduce для выполнения запросов и операций на кластере.
В особо сложных случаях, например для реализации запросов по социальному
графу, используется язык C. Это помогает повысить производительность.&lt;/p&gt;
&lt;p&gt;Данные распределяются между кластерами кеш серверов, а также
используется репликация партиций для обеспечения надежности.&amp;nbsp;Иногда
требования к быстродействию настолько велики, что используются локальные
короткоживущие кеши данных полученных с кеш серверов, расположенные
непосредственно в памяти серверов бизнес логики.&lt;/p&gt;
&lt;p&gt;Для примера, один сервер, кэширующий граф связей пользователей, в час
пик может обработать около 16 600 запросов в секунду. Процессоры при
этом заняты до 7%, максимальный load average за 5 минут &amp;mdash; 1.2.
Количество вершин графа - более 85 миллионов, связей 2.5 миллиарда. В
памяти граф занимает 30 GB.&lt;/p&gt;
&lt;h2 id="uroven-baz-dannykh"&gt;Уровень баз данных&lt;/h2&gt;
&lt;p&gt;Суммарный объем данных без резервирования составляет 160Тб. Используются
два решения для хранения данных: MS SQL и BerkeleyDB. Данные хранятся в
нескольких копиях, в зависимости от их типа от двух до четырех. Полное
резервное копирование всех данных осуществляется раз в сутки, плюс
каждые 15 минут делаются резервные копии новых данных. В результате
максимально возможная потеря данных составляет 15 минут.&lt;/p&gt;
&lt;p&gt;Сервера с MS SQL объединены в failover кластера, при выходе из строя
одного из серверов, находящийся в режиме ожидания сервер берет на себя
его функции. Общение с MS SQL происходит посредством JDBC драйверов.&lt;/p&gt;
&lt;p&gt;Используются как вертикальное, так и горизонтальное разбиение данных,
т.е. разные группы таблиц располагаются на разных серверах (вертикальное
партиционирование), а данные больших таблицы дополнительно
распределяются между серверами (горизонтальное партиционирование).
Встроенный в СУБД аппарат партиционирования не используется &amp;mdash; весь
процесс реализован на уровне бизнес-логики.&amp;nbsp;Распределенные транзакции не
используются &amp;mdash; всё только в пределах одного сервера. Для обеспечения
целостности, связанные данные помещаются на один сервер или, если это
невозможно, дополнительно разрабатывается логика обеспечения целостности
данных.&amp;nbsp;В запросах к БД не используются JOIN даже среди локальных таблиц
для минимизации нагрузки на CPU. Вместо этого используется
денормализация данных или JOIN происходят на уровне бизнес сервисов, что
позволяет осуществлять JOIN как с данными из баз данных, так и с данными
из кэша.&amp;nbsp;При проектировании структуры данных не используются внешние
ключи, хранимые процедуры и триггеры. Опять же для снижения потребления
вычислительных ресурсов на серверах баз данных.
SQL операторы DELETE также используются с осторожностью &amp;mdash; это самая
тяжелая операция. Данные удаляются чаще всего через маркер: запись
сначала отмечается как удаленная, а потом удаляется окончательно с
помощью фонового процесса.&amp;nbsp;Широко используются индексы, как обычные, так
и кластерные. Последние для оптимизации наиболее высокочастотных
запросов в таблицу.&lt;/p&gt;
&lt;p&gt;Используется C реализация BerkleyDB версии 4.5. Для работы с BerkleydDB
используется своя библиотека, позволяющая организовывать двухнодовые
master-slave кластера с использованием родной BDB репликация. Запись
происходит только в master, чтение происходит с обеих нод. Данные
хранятся в tmpfs, transaction логи сохраняются на дисках. Резервная
копия логов делается каждые 15 минут. Сервера одного кластера размещены
на разных лучах питания дабы не потерять обе копии одновременно. Помимо
прочего, BerkleyDB используется и в роли очереди заданий.&lt;/p&gt;
&lt;p&gt;Внутри системы используется взвешенный round robin, а также вертикальное
и горизонтальное разбиение данных как на уровне СУБД, так и на уровне
кэширования.&lt;/p&gt;
&lt;p&gt;В разработке новое решение для хранения данных, так как необходим еще
более быстрый и надежный доступ к данным.&lt;/p&gt;
&lt;h2 id="uroven-infrastruktury"&gt;Уровень инфраструктуры&lt;/h2&gt;
&lt;p&gt;Для агрегации статистики используется собственная библиотека, основанная
на log4j. Сохраняется такая информация, как количество вызовов, среднее,
максимальное и минимальное время выполнения, количество ошибок. Данные
сохраняются во временные базы, но раз в минуту данные переносятся из них
в общий склад данных (data warehouse), а временные базы очищаются. Сам
склад реализован на базе решений от Microsoft: MS SQL 2008 и сиситема
генерации отчетов Reporting Services. Он расположен на 13 серверах,
находящихся в отдельной от production среде. Некоторые из них отвечают
за статистику в реальном времени, а некоторые за ведение и
предоставление доступа к архиву. Общий объем статистических данных
составляет 13Тб.&amp;nbsp;Планируется внедрение многомерного анализа статистики
на основе OLAP.&lt;/p&gt;
&lt;p&gt;Управление сервисами происходит через самописную централизованную
систему конфигурации. Через веб-интерфейс доступно изменение
расположения портлетов, конфигурации кластеров, изменение логики
сервисов и прочее. Вся конфигурация сохраняется в базе данных. Каждый из
серверов периодически проверяет, есть ли обновления для приложений,
которые на нем запущены, и, если есть, применяет их.&lt;/p&gt;
&lt;p&gt;Мониторинг логически разделен на две части:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Мониторинг сервисов и компонентов&lt;/li&gt;
&lt;li&gt;Мониторинг ресурсов, оборудования и сети&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Система мониторинга сервисов также самописная и основывается на
оперативных данных с упомянутого выше склада. Мониторинг ресурсов и
здоровья оборудования же онован на Zabbix, а статистика по
использованию ресурсов серверов и сети накапливаетя в Cacti.&amp;nbsp;Для
предпринятия мер по устранению чрезвычайных ситуаций работают дежурные,
которые следят за всеми основными параметрами.&amp;nbsp;Оповещения о наиболее
критичных аномалиях приходят по смс, остальные оповещения отсылаются по
емейлу.&lt;/p&gt;
&lt;h2 id="komanda"&gt;Команда&lt;/h2&gt;
&lt;p&gt;Над проектом работают около 70 технических специалистов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;40 разработчиков;&lt;/li&gt;
&lt;li&gt;20 системных администраторов и инженеров;&lt;/li&gt;
&lt;li&gt;8 тестеров.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Все разработчики разделены на небольшие команды до 3х человек. Каждая из
команд работает автономно и разрабатывает либо какой-то новый сервис,
либо работает над улучшением существующих. В каждой команде есть
технический лидер или архитектор, который ответственен за архитектуру
сервиса, выбор технологий и подходов. На разных этапах к команде могут
примыкать дизайнеры, тестеры и системные администраторы.&lt;/p&gt;
&lt;p&gt;Разработка ведется итерациями в несколько недель. Как пример жизненного
цикла разработки можно привести 3х недельный цикл:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;определение архитектуры;&lt;/li&gt;
&lt;li&gt;разработка, тестирование на компьютерах разработчиков;&lt;/li&gt;
&lt;li&gt;тестирование на pre-production среде, релиз на production среду.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Практически весь новый функционал делается &amp;laquo;отключаемым&amp;raquo;, типичный
процесс запуска новой функциональной возможности:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Функционал разрабатывается и попадает в production релиз;&lt;/li&gt;
&lt;li&gt;Через централизованную систему конфигурации функционал включается
    для небольшой части пользователей;&lt;/li&gt;
&lt;li&gt;Анализируется статистика активности пользователей, нагрузка на
    инфраструктуру;&lt;/li&gt;
&lt;li&gt;Если предыдущий этап прошел успешно, функционал включается
    постепенно для все большей аудитории;&lt;/li&gt;
&lt;li&gt;Если в процессе запуска собранная статистика выглядет
    неудовлетворительно, либо непозволительно вырастает нагрузка на
    инфраструктуру, то функционал отключается, анализируются причины,
    исправляются ошибки, происходит оптимизация и все повторяется с
    начала.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="podvodim-itogi"&gt;Подводим итоги&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;В отличии от остальных популярных социальных сетей в Одноклассниках
    используются технологии, рассчитанные в первую очередь на
    корпоративный рынок, начиная от обоих СУБД и заканчивая
    операционными системами.&lt;/li&gt;
&lt;li&gt;Во многом этот факт обуславливает комплексный подход к генерации
    пользовательского интерфейса, не слишком высокую производительность
    и многие другие особенности этой социальной сети.&lt;/li&gt;
&lt;li&gt;Использование "тяжелых" технологий с самого начала оставило
    Одноклассники с большим количеством доставшегося по наследству от
    ранних версий устаревшего кода и купленных давно лицензий на
    проприетарный софт, которые выступают в роли оков, от которых
    довольно сложно избавиться.&lt;/li&gt;
&lt;li&gt;Возможно эти факторы и являются одними из основных препятствий на
    пути к завоеванию большей доли рынка и быстрому развитию платформы
    как в функциональном, так и техническом плане.&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Tue, 22 Mar 2011 00:17:00 +0300</pubDate><guid>tag:www.insight-it.ru,2011-03-22:highload/2011/arkhitektura-odnoklassnikov/</guid><category>BerkleyDB</category><category>C. GWT</category><category>IPVS</category><category>Java</category><category>Jboss</category><category>Lucene</category><category>LVS</category><category>MSSQL</category><category>openSUSE</category><category>Tomcat</category><category>Windows</category><category>Архитектура Одноклассников</category><category>Масштабируемость</category><category>Одноклассники</category></item><item><title>Архитектура LinkedIn</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-linkedin/</link><description>&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/801d7bb4/" rel="nofollow" target="_blank" title="https://www.linkedin.com"&gt;LinkedIn&lt;/a&gt; является крупнейшей в мире
социальной сетью для профессионалов. Популярность этого проекта может
быть далека, от более общетематических социальных сетей, таких как,
скажем Facebook, но, тем не менее, нагрузка на серверную часть проекта
создается пользователями серьезная. О том как этот проект с ней
справляется и пойдет речь далее.
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="predislovie"&gt;Предисловие&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Сообщение о публикации двух презентаций c JavaOne 2008 о LinkedIn и их
&lt;a href="https://www.insight-it.ru/goto/36e64126/" rel="nofollow" target="_blank" title="http://hurvitz.org/blog/2008/06/linkedin-architecture"&gt;обобщении&lt;/a&gt; от
Overn Hurvitz пронеслось по русскоязычным новостным ресурсам уже
достаточно давно, но время черкнуть пару строк обо всем этом нашлось у
меня только сейчас.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/aef5ee94/" rel="nofollow" target="_blank" title="http://www.slideshare.net/linkedin/linkedins-communication-architecture"&gt;LinkedIn - A Professional Social Network Built with Java&amp;trade; Technologies and Agile Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/515b891c/" rel="nofollow" target="_blank" title="http://www.slideshare.net/linkedin/linked-in-javaone-2008-tech-session-comm"&gt;LinkedIn Communication Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="statistika"&gt;Статистика&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;22 миллиона пользователей;&lt;/li&gt;
&lt;li&gt;4+ миллиона уникальных посетителей в день;&lt;/li&gt;
&lt;li&gt;40 миллионов просмотров страниц в день;&lt;/li&gt;
&lt;li&gt;2 миллиона поисковых запросов в день;&lt;/li&gt;
&lt;li&gt;ежедневно отправляются 250 тысяч приглашений;&lt;/li&gt;
&lt;li&gt;1 миллион ответов в день;&lt;/li&gt;
&lt;li&gt;2 миллиона электронных сообщений ежедневно.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="platforma"&gt;Платформа&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/tag/solaris/"&gt;Solaris&lt;/a&gt; (как x86, так и SPARC)&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/tomcat/"&gt;Tomcat&lt;/a&gt; и &lt;a href="/tag/jetty/"&gt;Jetty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/oracle/"&gt;Oracle&lt;/a&gt; и &lt;a href="/tag/mysql/"&gt;MySQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Никакого ORM&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/activemq/"&gt;ActiveMQ&lt;/a&gt; для JMS&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/lucene/"&gt;Lucene&lt;/a&gt; в качестве основы для поиска&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/spring/"&gt;Spring&lt;/a&gt; в роли "клея"&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="servernaia-arkhitektura"&gt;Серверная архитектура&lt;/h3&gt;
&lt;h4&gt;2003-2005&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;одно монолитное веб-приложение;&lt;/li&gt;
&lt;li&gt;одна общая база данных;&lt;/li&gt;
&lt;li&gt;сетевой граф кэшируется в памяти в "Облаке";&lt;/li&gt;
&lt;li&gt;поиск пользователей реализован с помощью &lt;a href="/tag/lucene/"&gt;Lucene&lt;/a&gt;, он
    работал на той же машине, что и "Облако", так как поиск был
    отфильтрован в соответствии с сетью пользователя, таким образом было
    удобно совмещать эти две функции на одной машине;&lt;/li&gt;
&lt;li&gt;веб-приложение напрямую обновляет базу данных, а она, в свою
    очередь, обновляет "Облако".&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2006&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Добавлена репликация для уменьшения нагрузки на основную базу
    данных. Реплики предоставляют данные в режиме "только для чтения", а
    репликация ведется в асинхронном режиме с помощью дополнительного
    компонента под названием Databus, с его появлением обновление данных
    стало выглядеть следующим образом:&lt;ul&gt;
&lt;li&gt;сначала какие-либо изменения происходят в веб-приложении;&lt;/li&gt;
&lt;li&gt;веб-приложение обновляет основную базу данных;&lt;/li&gt;
&lt;li&gt;она, в свою очередь, отправляет обновления на Databus;&lt;/li&gt;
&lt;li&gt;далее уже Databus обновляет: реплики, Облако и поисковый индекс.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Поиск был вынесен на отдельный сервер.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2008&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;веб-приложение само по себе практически ничего не делает: бизнес
    логика распределена по отдельным сервисам;&lt;/li&gt;
&lt;li&gt;веб-приложение все так же предоставляет пользователям графический
    интерфейс, но для его генерации она теперь вызывает сервисы;&lt;/li&gt;
&lt;li&gt;каждый сервис имеет свою специфическую базу данных (т.е.
    вертикальное сегментирование);&lt;/li&gt;
&lt;li&gt;такой подход позволяет другим приложениям (помимо основного)
    получать доступ к LinkedIn, такие приложения были созданы для
    работодателей, рекламных служб, и так далее.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="oblako"&gt;Облако&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;"Облаком" в LinkedIn называют сервер, который кэширует весь граф
    социальной сети в памяти;&lt;/li&gt;
&lt;li&gt;его размеры: 22 миллиона вершин и 120 миллионов ребер;&lt;/li&gt;
&lt;li&gt;занимает 12GB оперативной памяти;&lt;/li&gt;
&lt;li&gt;одновременно держится в памяти в 40 экземплярах;&lt;/li&gt;
&lt;li&gt;построение Облака из данных, в дисковой системе, занимает 8 часов;&lt;/li&gt;
&lt;li&gt;обновления происходят в режиме реального времени с помощью Databus;&lt;/li&gt;
&lt;li&gt;во время остановки данные записываются на диск;&lt;/li&gt;
&lt;li&gt;кэш реализован с помощью C++, а доступ предоставляется по JNI;&lt;/li&gt;
&lt;li&gt;они выбрали именно C++ так как требовалось использовать минимум
    оперативной памяти, а также, задержки, связанные с Garbage
    Collection, были неприемлемыми.&lt;/li&gt;
&lt;li&gt;размещение всех данных в памяти является ограничением, но, как
    удалось выяснить в LinkedIn, разбиение графов на части - не самая
    тривиальная задача.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Облако кэширует целиком весь граф социальной сети LinkedIn, но на
практике же пользователям требуется видеть его со своей точки зрения.
Данная задача является вычислительно сложной, по-этому она выполняется
лишь один раз при создании новой сессии, а затем система поддерживает
результат в кэше. Такой подход требует 2 MB оперативной памяти на
каждого активного пользователя. В течении сессии такой кэш обновляется
только если сам пользователь сделал какие-либо изменения в нем, если же
изменение вызвано другими пользователями - владелец сессии не заметит
изменений.&lt;/p&gt;
&lt;p&gt;Помимо этого используется кэширование профилей пользователей средствами
&lt;a href="/tag/ehcache/"&gt;EHcache&lt;/a&gt;. Одновременно в памяти хранится до 2 миллионов
профилей (из 22 миллионов). Изначально планировалось использовать
алгоритм &lt;abbr title="Least Frequently Used"&gt;LFU&lt;/abbr&gt;, но оказалось,
что иногда &lt;a href="/tag/ehcache/"&gt;EHcache&lt;/a&gt; зависал секунд на 30 во время
перерасчета &lt;abbr title="Least Frequently Used"&gt;LFU&lt;/abbr&gt;, таким
образом было принято решение о использовании вместо него алгоритма
&lt;abbr title="Least Recently Used"&gt;LRU&lt;/abbr&gt;.&lt;/p&gt;
&lt;h3 id="arkhitektura-kommunikatsii"&gt;Архитектура коммуникации&lt;/h3&gt;
&lt;p&gt;Как известно, пользователи практически любой социальной сети генерируют
огромное количество сообщений в единицу времени, причем каждый тип
сообщений обычно требует индивидуального подхода, но в целом их можно
разделить на две категории: постоянные и временные. В LinkedIn
разработчики построили по отдельному сервису, для обработки каждой из
этих категорий. Каждый из них определенно заслуживает отдельного
внимания, так как общего в них мало.&lt;/p&gt;
&lt;h4&gt;Сервис постоянных сообщений&lt;/h4&gt;
&lt;p&gt;Этот коммуникационный сервис выполняет все операции, связанные с
постоянными сообщениями: приватными сообщениями и электронной почтой.
Перед ним ставится вполне тривиальный ряд задач: доставлять сообщения
получателям и сохранять их на постоянной основе, но на самом деле этим
все не ограничивается: должны также поддерживаться, скажем, доставка
сообщений с задержкой, массовые рассылки, отмена отправки сообщения,
возможность добавления в сообщения какого-либо интерактивного контента.
Реализован он был примерно следующим образом:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;вся система работает асинхронно и активно использует JMS;&lt;/li&gt;
&lt;li&gt;клиенты отправляют сообщения так же через JMS;&lt;/li&gt;
&lt;li&gt;далее сообщения перенаправляются с помощью сервиса маршрутизации в
    соответствующий почтовый ящик или напрямую в обработку электронной
    почты;&lt;/li&gt;
&lt;li&gt;доставка сообщений происходит как с помощью Pull (клиенты
    запрашивают свои сообщения), так и с использованием Push (т.е.
    отправки сообщений);&lt;/li&gt;
&lt;li&gt;помимо этого используется &lt;a href="/tag/spring/"&gt;Spring&lt;/a&gt; с их собственными
    закрытыми расширениями, использующими HTTP-RPC.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Приемы, способствующие масштабируемости&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Функциональное сегментирование:&lt;/strong&gt; отправленные, полученные,
    архивные сообщения. &lt;em&gt;(т.е. вертикальное сегментирование)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Классовое сегментирование:&lt;/strong&gt; пользовательские, гостевые,
    корпоративные почтовые ящики.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сегментирование по диапазонам:&lt;/strong&gt; по идентификаторам пользователей
    или по лексикографическим диапазонам самих сообщений. &lt;em&gt;(т.е.
    горизонтальное сегментирование)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Асинхронное выполнение операций&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Сервис сетевых обновлений&lt;/h4&gt;
&lt;p&gt;Этот сервис обеспечивает работу любых временных уведомлений, например,
вызванных изменением статуса пользователей в контакт-листах. Такие
сообщения должны с течением времени удаляться из-за быстрой потери
актуальности, а также должна поддерживаться группировка и приоритезация
сообщений. Функционирование этого сервиса оказалось не настолько
очевидно, по сравнению с предыдущим, так что до итогового варианта было
перепробовано масса менее удачных решений, но обо всем по порядку.&lt;/p&gt;
&lt;h5&gt;Изначальная архитектура (до 2007 года)&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;используется много серверов, которые могут содержать обновления;&lt;/li&gt;
&lt;li&gt;клиенты отправляют запросы на каждый сервис отдельно: вопросы,
    обновления профилей и т.д.&lt;/li&gt;
&lt;li&gt;на сбор всех данных требовалось относительно много времени.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В 2008 году вся эта система поэтапно эволюционировала собственно в сам
сервис сетевых обновлений:&lt;/p&gt;
&lt;h5&gt;Первая итерация&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;клиент отправляет единственный запрос сервису сетевых обновлений;&lt;/li&gt;
&lt;li&gt;этот сервис в свою очередь параллельно отправляет всем остальным сервисам соответствующие запросы.&lt;/li&gt;
&lt;li&gt;результаты агрегируются и все вместе возвращаются клиенту;&lt;/li&gt;
&lt;li&gt;весь процесс основывается на Pull.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Вторая итерация&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;стал использоваться метод Push: каждый раз, когда происходит
    какое-либо событие, они помещаются в пользовательский "почтовый
    ящик", в момент запроса пользователя ему возвращается просто
    содержимое, уже ожидающее своего звездного часа в специально том
    самом "ящике";&lt;/li&gt;
&lt;li&gt;такой подход сильно ускоряет процесс чтения, так как на тот
    момент данные уже готовы;&lt;/li&gt;
&lt;li&gt;с другой стороны, какая-то часть данных может так никогда и не
    понадобиться, что приводит к бесполезным передвижениям данных и
    лишнему используемому дисковому пространству;&lt;/li&gt;
&lt;li&gt;небольшая часть обработки данных все же производится уже в
    момент запроса пользователя (например, объединение нескольких
    обновлений от определенного пользователя в одно);&lt;/li&gt;
&lt;li&gt;обновления хранятся в &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ах: по одному &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'у на каждый тип
    обновления для каждого пользователя (то есть в сумму около 15 &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ов на каждого пользователя);&lt;/li&gt;
&lt;li&gt;сначала использовался размер &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ов равный 8 KB,
    что было явно больше требуемого и приводило к существенному
    количеству неиспользуемого дискового пространства.&lt;/li&gt;
&lt;li&gt;вместо &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ов можно
    было бы использовать дополнительные таблици по одной на каждый
    тип обновлений, но в этом случае пришлось бы постоянно удалять
    из них устаревшие записи, что было бы чрезвычайно неэффективно.&lt;/li&gt;
&lt;li&gt;в дополнение к этому использовался &lt;abbr title="Java Management eXtensions"&gt;JMX&lt;/abbr&gt; для
    мониторинга и изменения конфигурации в реальном времени, что
    оказалось очень удобным и полезным.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Третья итерация&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Цель: повысить производительность путем сокращения количества
    обновлений &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ов,
    так как они требуют много вычислительных ресурсов.&lt;/li&gt;
&lt;li&gt;Был добавлен буфер: колонки в таблицах типа &lt;code&gt;varchar(4000)&lt;/code&gt;, в
    которых данные помещались изначально. При полном заполнении
    ячейки данные перемещаются в &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;; это позволило
    на порядок сократить количество их обновлений.&lt;/li&gt;
&lt;li&gt;Уменьшен размер самих сообщений об обновлениях.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="i-naposledok-paru-sovetov-ot-linkedin"&gt;И напоследок пару советов от LinkedIn&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;нельзя бесконечно долго ограничиваться одной базой данных:
    используйте много баз данных как с вертикальным, так и с
    горизонтальным сегментированием данных;&lt;/li&gt;
&lt;li&gt;забудьте о ссылочной целостности и кросс-серверных JOIN'ах;&lt;/li&gt;
&lt;li&gt;забудьте о 100% целостности данных;&lt;/li&gt;
&lt;li&gt;при большом масштабе издержки могут стать проблемой: оборудование,
    базы данных, лицензии, системы хранения данных, электроэнергия и так
    далее;&lt;/li&gt;
&lt;li&gt;как только вы станете достаточно крупны и популярны, спаммеры и
    прочие злые люди не заставят себя долго ждать;&lt;/li&gt;
&lt;li&gt;не забывайте про кэширование!!!&lt;/li&gt;
&lt;li&gt;используйте асинхронные потоки данных;&lt;/li&gt;
&lt;li&gt;аналитика и построение отчетов может стать непростой задачей,
    постарайтесь задуматься о них заранее в процессе планирования
    системы;&lt;/li&gt;
&lt;li&gt;имейте всегда ввиду, что Ваша система может упасть в любой момент;&lt;/li&gt;
&lt;li&gt;не стоит недооценивать траекторию своего роста.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ps"&gt;P.S.&lt;/h3&gt;
&lt;p&gt;Когда уже закончил переводить в голову пришла мысль, что если читателям
будет интересно взглянуть на оригинальные презентации (хотябы ради
иллюстрационного материала, который там вполне нагляден), то было бы
проще сделать это прямо здесь, так что вот, для Вашего же удобства:&lt;/p&gt;
&lt;div class="video-container"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/key/uHbsRNnQFZwThD" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" width="425"&gt; &lt;/iframe&gt;&lt;/div&gt;
&lt;div class="video-container"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/key/16CML2N96CDeWv" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" width="425"&gt; &lt;/iframe&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Кстати если Вы еще не успели подписаться на &lt;a href="/feed/"&gt;RSS&lt;/a&gt; - сейчас
самое время!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 11 Sep 2008 04:00:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-09-11:highload/2008/arkhitektura-linkedin/</guid><category>ActiveMQ</category><category>C++</category><category>EHcache</category><category>Java</category><category>Jetty</category><category>LinkedIn</category><category>Lucene</category><category>MySQL</category><category>Oracle</category><category>Solaris</category><category>Spring</category><category>Tomcat</category><category>архитектура</category><category>архитектура LinkedIn</category><category>Масштабируемость</category></item><item><title>Архитектура Mailinator</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-mailinator/</link><description>&lt;p&gt;Ваш пьяный друг когда-либо вдохновлял Вас на создание первого в своем
роде интернет-сервиса, который пришелся бы по вкусу миллионам
пользователей и при этом неприхотливо обрабатывал миллиарды электронных
писем ежегодно? Именно так Paul Tyma и создал Mailinator.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/43449c5a/" rel="nofollow" target="_blank" title="http://www.mailinator.com"&gt;Mailinator&lt;/a&gt; представляет собой бесплатный,
не требующий инсталляции, сервис для разрушения планов злобных спаммеров
путем предоставления регистрации "одноразовых" почтовых адресов. Если Вы
не не будете публиковать в Сети свой настоящий интернет-адрес - спаммеру
не будут слать вам письма, вместо этого они будут спамить Mailinator :-)&lt;/p&gt;
&lt;p&gt;Как же Mailinator справляется со своей ролью анти-спам супергероя?
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="istochniki-informatsiia"&gt;Источники информация&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Да-да, это снова перевод
&lt;a href="https://www.insight-it.ru/goto/1b9578f1/" rel="nofollow" target="_blank" title="http://highscalability.com/mailinator-architecture"&gt;статьи&lt;/a&gt; от
&lt;a href="https://www.insight-it.ru/goto/f3f1b405/" rel="nofollow" target="_blank" title="http://highscalability.com/user/todd-hoff"&gt;Todd&lt;/a&gt;'а (цифры правда не
первой свежести, но все же). На что-то более глобальное я в ближайшее
время способен не буду, в основном благодаря незаметно подкравшейся
сессии и, отчасти, работе.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/fd89ec4b/" rel="nofollow" target="_blank" title="http://mailinator.blogspot.com/2007/01/architecture-of-mailinator.html"&gt;The Architecture of Mailinator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/a94e81a2/" rel="nofollow" target="_blank" title="http://mailinator.blogspot.com/2007/02/mailinators-2006-stats.html"&gt;Mailinator's 2006 Stats&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="platforma"&gt;Платформа&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/tag/linux/"&gt;Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/tomcat/"&gt;Tomcat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/java/"&gt;Java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="statistika"&gt;Статистика&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Сервис обработал: 1.29 миллиардов электронных писем за 2007 год.
    450.74 миллионов за 2006. 280.68 миллионов за 2005.&lt;/li&gt;
&lt;li&gt;В период пиковых нагрузок обрабатывается 6.5 миллионов электронных
    писем в сутки или 4513 сообщений в минуту или 75 в секунду.&lt;/li&gt;
&lt;li&gt;Mailinator работает на всего одном весьма средненьком компьютере с
    AMD Athlon 2GHz процессором, 1 GB оперативной памяти (которая
    используется не целиком) и низкопроизводительным IDE жестким диском
    объемом 80 GB. И она в общем-то загружена далеко не полностью.&lt;/li&gt;
&lt;li&gt;Mailinator работает месяцами без присмотра и теряется очень
    небольшое количество сообщений, даже при постоянных спам-атаках и
    высоких пиковых нагрузках.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="arkhitektura"&gt;Архитектура&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Так как система бесплатна, она не должна быть идеальной. Таким
    образом основные цели:&lt;ul&gt;
&lt;li&gt;Создание системы, которая ценит выживание превыше всего, даже
пользователей. Основным ключом является именно выживание, так как
Mailinator вынужден ежедневно отражать спам-атаки.&lt;/li&gt;
&lt;li&gt;Предоставить пользователям 99,99% доступность и точность данных.
Более высокие гарантии будут существенно менее практичными и
приведут к большим затратам. И так как сервис бесплатен, этот
небольшой риск для пользователей становится просто частью правил
игры.&lt;/li&gt;
&lt;li&gt;Поддержка следующей модели сервиса: пользователь регистрируется
где-то, заходит в Mailinator, жмет на пришедшую ссылку и забывает об
этом. Это означает, что письма не должны храниться постоянно. Они
могут размещаться в оперативной памяти, так как являются временными
(живут три-четыре часа). Если Вам нужен обычный настоящий почтовый
ящик - воспользуйтесь любым другим соответствующим сервисом.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Изначально письма обрабатывались следующим образом:&lt;ul&gt;
&lt;li&gt;Sendmail получал письмо в общий ящик на диске.&lt;/li&gt;
&lt;li&gt;Java-приложение доставало сообщение используя IMAP и/или POP (с
течением времени это менялось) и удаляло их.&lt;/li&gt;
&lt;li&gt;Система загружала все письма в память и оставляла их там.&lt;/li&gt;
&lt;li&gt;Наиболее старые сообщения вытеснялись как только накапливался
лимит в 20000 сообщений.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Данный принцип работал вполне неплохо:&lt;ul&gt;
&lt;li&gt;Он стабилен и работал месяцами без каких-либо проблем.&lt;/li&gt;
&lt;li&gt;Использовался практически весь гигабайт оперативной памяти.&lt;/li&gt;
&lt;li&gt;Проблемы начались, когда количество сообщений в сутки начало
превышать 800000. Система начала давать сбои из-за использования
жесткого диска между Mailinator и email подсистемой.&lt;/li&gt;
&lt;li&gt;Наиболее старые сообщения вытеснялись как только накапливался
лимит в 20000 сообщений.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Новая архитектура:&lt;ul&gt;
&lt;li&gt;Идея заключалась в отказе от временного хранения данных на жестком
диске путем полного переписывания всей системы с нуля.&lt;/li&gt;
&lt;li&gt;Веб-приложение, почтовый сервер и все хранилище писем
функционируют в рамках одной JVM.&lt;/li&gt;
&lt;li&gt;Sendmail был заменен на специально написанный для этого проекта
SMTP сервер. Так как природа Mailinator не требовала полноценного
SMTP сервера. Mailinator не отправляет писем, основная цель -
принимать или отвергать входящие письма. Это является недостатком
многоуровневой архитектуры. Она часто является залогом успеха в
процессе масштабирования веб-приложения, но порой она может и
наоборот полностью убить всю производительность благодаря неверному
принятию ответственных решений. Решение о создании собственного SMTP
сервера было достаточно интересным и смелым, многие другие
руководители проектов вместо этого просто добавили бы дополнительное
оборудование в систему. Это не было бы ошибкой, но, согласитесь,
создание своего собственного решения задачи - намного более
интересный подход.&lt;/li&gt;
&lt;li&gt;Сейчас Mailinator получает почту напрямую, обрабатывает ее и
хранит в оперативной памяти. Жесткие диски полностью обходятся и
практически не используются.&lt;/li&gt;
&lt;li&gt;Основное их применение - хранение сообщений в случае остановки
сервиса для того, чтобы они могли быть восстановлены при запуске.&lt;/li&gt;
&lt;li&gt;Ведение логов было отключено.&lt;/li&gt;
&lt;li&gt;Система использует менее 300 потоков. Это оказалось вполне
достаточно.&lt;/li&gt;
&lt;li&gt;При принятии сообщения, система пропускает его через набор
фильтров и хранит его в памяти только в том случае, если все фильтры
были успешно пройдены.&lt;/li&gt;
&lt;li&gt;Каждый почтовый адрес ограничен только 10 письмами, так что
популярные адреса вроде joe@mailinator.com не могут "взорвать"
систему.&lt;/li&gt;
&lt;li&gt;Письма не могут превышать 100 kb, а все приложения автоматически
уничтожаются. Это позволяет существенно сэкономить в плане
используемой оперативной памяти..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Электронные письма сжимаются в оперативной памяти:&lt;ul&gt;
&lt;li&gt;99% писем никто даже не открывает, компрессия позволяет сэкономить
место в оперативной памяти. Письмо разжимается в исходное состояние
только если кто-то решает его открыть.&lt;/li&gt;
&lt;li&gt;Mailinator может хранить около 80000 писем в оперативной памяти,
используя лишь 300 MB памяти, по сравнению с 20000 писем, занимающих
1 GB без использования компрессии.&lt;/li&gt;
&lt;li&gt;С таким подходом к хранению писем, они живут в среднем 3-4 часа.&lt;/li&gt;
&lt;li&gt;В память поместится и 200000 писем, но на практике это и не
требуется.&lt;/li&gt;
&lt;li&gt;Оперативная память ценна, а процессорное время - вовсе нет. Именно
из-за этого используется компрессия для экономии памяти и
использования излишков вычислительных мощностей.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mailinator не гарантирует анонимность или приватность:&lt;ul&gt;
&lt;li&gt;Любой пользователь может получить доступ к любому почтовому ящику.&lt;/li&gt;
&lt;li&gt;Отказ от ограничений доступа делает схему работы системы намного
более простой.&lt;/li&gt;
&lt;li&gt;Со стороны пользователя такой подход очень прост, так как не
требуется абсолютно никакой регистрации. Когда сайт требует ввести
почтовый адрес достаточно лишь просто ввести любой адрес Mailinator.
Вам не нужно создавать отдельный аккаунт. Банальный ввод адреса
создает почтовый ящик. Все просто.&lt;/li&gt;
&lt;li&gt;На практике же, не смотря на вышесказанное, пользователи все же
получают изрядную степень приватности.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Стремление к выживанию требует агрессивной борьбы со спамом:&lt;ul&gt;
&lt;li&gt;Mailinator не имеет ничего против спама, но так как спама приходит
нереально много, когда он подвергает риску работоспособность сервиса
приходится его фильтровать.&lt;/li&gt;
&lt;li&gt;Этот факт привел к правилу: если Вы делаете что-то (получаете спам
или что-то еще), что мешает работе системы - Ваши письма не будут
приниматься и Вы можете быть временно заблокированы.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Для успешного приема письмо должно пройти следующую цепочку
    фильтров:&lt;ul&gt;
&lt;li&gt;Все письма, которые не смогли быть доставлены, отклоняются.&lt;/li&gt;
&lt;li&gt;При слишком большом количестве писем с одного IP они перестают
приниматься.&lt;/li&gt;
&lt;li&gt;Слишком много писем с одинаковой темой не принимаются.&lt;/li&gt;
&lt;li&gt;Письма, содержащие в заголовках запрещенные сервисом слова, также
не попадают в почтовые ящики.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Выживание в условиях наплыва писем с одного IP адреса:&lt;ul&gt;
&lt;li&gt;Для этого типа фильтрации используется AgingHashMap. Когда сервис
получает очередное письмо, IP помещается в массив и счетчик,
соответствующий этому ключу, увеличивается на единицу в момент
получения каждого последующего письма с этого IP.&lt;/li&gt;
&lt;li&gt;Спустя определенное время без получения писем с IP,
соответствующие ему счетчик обнуляется.&lt;/li&gt;
&lt;li&gt;Когда счетчик достигает определенного порога, IP блокируется,
предотвращая поток сообщений.&lt;/li&gt;
&lt;li&gt;Этим простым методом пользуются многие интернет-ресурсы для защиты
различных своих компонентов, например комментариев. В роли хранилища
для такого массива при распределенном функционировании системы часто
используют &lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Защита от "зомби" атак:&lt;ul&gt;
&lt;li&gt;Спам может приходить и с больших координированных сетей с разными
IP адресами, как раз участников таких сетей и называют "зомби".
Одинаковые письма приходят со множества разных адресов, так что
защита по IP адресам становится бессильна.&lt;/li&gt;
&lt;li&gt;Этот фильтр несколько более сложный, чем блокировка по IP, так как
требуется достать из письма строку с заголовком, да и их сравнение -
несколько ресурсоемкая задача.&lt;/li&gt;
&lt;li&gt;Когда около 20 писем с одинаковыми темами приходят в течении 2
минут, этот заголовок блокируется на час.&lt;/li&gt;
&lt;li&gt;Что интересно, Mailinator не хранит заблокированные темы вечно,
так как это значило бы, что этот список неуклонно рос и приходилось
бы вечно отслеживать соответствия с ним. Это никак не приемлемо для
мимолетной природы Mailinator. Более комплексные алгоритмы защиты от
спама нужны лишь только если ставятся цели с более жесткой борьбой
со спама, для Mailinator же данный вариант - наиболее эффективный.&lt;/li&gt;
&lt;li&gt;Этим фильтром блокируется около 9% писем.&lt;/li&gt;
&lt;li&gt;Mailinator фильтрует сообщения только по теме и IP, так что
системе не приходится прочитывать и анализировать все письмо
целиком. Это позволяет неплохо сэкономить на вычислительных ресурсах
при достаточно эффективной итоговой фильтрации.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Для уменьшения угрозы DDoS атак:&lt;ul&gt;
&lt;li&gt;Все соединения, неактивные какое-то время обрываются.&lt;/li&gt;
&lt;li&gt;Mailinator отвечает отправителям писем очень медленно, 10, 20 или
даже 30 секунд, даже для небольших объемов данных. Это замедляет
работу спаммеров, пытающихся отправлять спам как можно быстрее, и
заставляет их лишний раз задуматься о целесообразности отправки
снова спама на этот адрес. Период ожидания уменьшается во время
повышенных нагрузок на сервис, так что письма не теряются из-за
этого.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="podvodim-itogi"&gt;Подводим итоги&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Идеальность - всего лишь ловушка.&lt;/strong&gt; Как много систем были
    кардинально усложнены лишь для того, чтобы достичь 100%-го
    результата во всех аспектах. Если Вы участвовали в подобных
    совещаниях, Вы понимаете о чем идет речь. О нет, мы не можем сделать
    этого, так как есть 0,01% шанс, что что-то пойдет не так. Лучше
    спросите себя: насколько неидеальными можно позволить себе быть,
    чтобы все равно оставаться достаточно неплохим сервисом?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;То, что Вы отвергаете, ничуть не менее важно, чем то, что Вы
    оставляете в системе.&lt;/strong&gt; Существует масса концепций по построению
    архитектуры системы. Нужно не только выбрать подходящие, но и
    отказаться от тех, которые излишни.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Знайте предназначение своей системы и разрабатывайте ее в
    соответствии с этим.&lt;/strong&gt; Быть всем для всех значит быть ничем для
    никого. Временное хранение электронных писем, позволяя небольшой
    части спама пробиться через фильтры, в совокупности с не 100%
    временем работы системы производят достаточно хорошее впечатление на
    пользователей. Построение собственного SMTP-сервера необходимо лишь
    в случае, если у Вас есть весомые аргументы в пользу того, что он
    Вам необходим. Далеко не факт, что такая идея придет в голову,
    возможно выбор пал бы и на более тривиальное решение, связанное
    просто с добавлением дополнительного оборудования.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Постарайтесь как можно быстрее свести механизм работы системы к
    наиболее общему случаю.&lt;/strong&gt; Очень большой процент писем отвергается,
    так что это оправданно сделать это как можно раньше, чтобы
    минимизировать ресурсы, требуемые для их обработки. Найдите способ
    сделать это как можно быстрее в отношении наиболее частых случаев.
    то очень часто становится важным компонентом стратегии
    масштабирования.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Эффективность часто означает "постройте это самостоятельно".&lt;/strong&gt;
    Готовые решения обычно решают большой спектр задач, но на практике
    часто нужна лишь небольшая часть функционала, в таких случаях можно
    написать небольшой компонент с нуля самостоятельно, чтобы он мог
    выполнять только нужные функции, но более эффективно.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Небольшое количество сбоев - вполне допустимо.&lt;/strong&gt; Все
    заблокированные адреса не должны быть запомнены навечно. Позвольте
    этим спискам генерироваться на основе локальных данных, а не
    глобального состояния. Это очень простая и эффективная архитектура.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/tag/java/"&gt;Java&lt;/a&gt; совсем не обязательно должна быть медленной.&lt;/strong&gt;
    На эту тему сказано уже достаточно.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Избегайте работы с жесткими дисками.&lt;/strong&gt; Многие приложения требуют
    работы с дисковой системой, но очень часто именно она оказывается
    узким местом в системе. Можете ли Вы обойтись без него, используя
    более креативные подходы к архитектуре системы?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ограничте использование ресурсов.&lt;/strong&gt; Задайте рамки для размеров
    почтовых ящиков и других подобных элементов системы, это позволит
    избежать неконтролируемых скачков нагрузок. Неограниченное
    использование ресурсов недопустимо при ограниченности ресурсов.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сжимайте данные.&lt;/strong&gt; Компрессия данных может стать неплохим
    достижением в попытках сэкономить оперативную память. Можно
    сократить использование памяти вдвое с лишь небольшой дополнительной
    нагрузкой, связанной с компрессией и декомпрессией информации. Если
    обмен данными происходит локально, достаточно лишь закодировать
    данные и предоставить API для доступа к данным без полной
    декомпрессии.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Используйте фиксированные объемы ресурсов для обработки запросов.&lt;/strong&gt; Многие приложения не могут контролировать используемые
    ресурсы, в частности - оперативную память, таким образом они могут
    порой давать сбой при использовании излишне больших ее объемов. Для
    более стабильной работы стоит ограничить используемые ресурсы и
    откладывать выполнение новых задач пока они используются полностью.
    Для управление доступом к ресурсам можно использовать определенную
    логику в зависимости от ситуации: по времени, по приоритету,
    "честный" доступ, но так как ресурсы ограничены, система несколько
    ослабнет под серьезной нагрузкой.&lt;/li&gt;
&lt;li&gt;Если данные не хранятся длительное время, они не могут стать
    причиной возбуждения судебного дела о нарушении чьих-либо прав.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Пользуйтесь тем, что знаете лучше всего.&lt;/strong&gt; Этот урок не раз
    оправдывал себя. Paul знал Java лучше, чем что-либо еще, именно
    по-этому он заставил приложение на этом языке работать и выполнить
    все поставленные задачи.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Найдите свои собственные Mailinator'ы.&lt;/strong&gt; Конечно, Mailinator
    является очень небольшой системой. В более крупной системе этот
    проект был бы лишь небольшой дополнительной возможностью, но такие
    системы обычно состоят просто из нескольких подпроектов размером с
    Mailinator. А что если подойти к разработке некоторых из них так же
    как и к Mailinator?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;KISS работает, правда довольно редко.&lt;/strong&gt; Простота систем часто
    обсуждается, но практические примеры появляются достаточно редко.
    Чаще всего разговор остается на уровне: твоя система сложная, а
    моя - простая, просто так как она моя. Mailinator является хорошим
    примером простой архитектуры системы.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Надежность является функцией архитектуры системы.&lt;/strong&gt; Для построения
    системы, эффективно использующей память и выживающей серьезные атаки
    спаммеров, потребовалось серьезно подойти к каждому уровню ее
    архитектуры.&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Tue, 24 Jun 2008 18:17:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-06-24:highload/2008/arkhitektura-mailinator/</guid><category>Java</category><category>Linux</category><category>online</category><category>Tomcat</category><category>архитектура</category><category>архитектура Mailinator</category><category>электронная почта</category></item></channel></rss>