<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title></title>
	<atom:link href="http://www.spicesoft.net/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.spicesoft.net/blog</link>
	<description></description>
	<lastBuildDate>Fri, 01 Apr 2011 16:12:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Augmented reality</title>
		<link>http://www.spicesoft.net/blog/2011/03/15/augmented-reality/</link>
		<comments>http://www.spicesoft.net/blog/2011/03/15/augmented-reality/#comments</comments>
		<pubDate>Tue, 15 Mar 2011 16:28:57 +0000</pubDate>
		<dc:creator>Berd</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.spicesoft.net/blog/?p=22</guid>
		<description><![CDATA[Originally posted on www.habrahabr.ru JavaScript Augmented Reality — тест JSARToolkit JSARToolkit это JavaScript библиотека, портированная с FLARToolkit (Flash) и предназначенная для отслеживания AR Маркеров на видео. ARToolKit преобразует данные из маркеров в 3D-координаты, используя их можно наложить изображения или 3D-объекты &#8230; <a href="http://www.spicesoft.net/blog/2011/03/15/augmented-reality/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Originally posted on www.habrahabr.ru</h2>
<h2>JavaScript Augmented Reality — тест JSARToolkit</h2>
<div><img src="http://weblog.bocoup.com/wp-content/uploads/2011/03/augmented-reality-javascript1.png" alt="Если картинка не отображается, пожалуйста, напишите об этом автору" align="center" /><br />
<a href="https://github.com/kig/JSARToolKit">JSARToolkit</a> это JavaScript библиотека, портированная с FLARToolkit (Flash) и предназначенная для отслеживания AR Маркеров на видео. ARToolKit преобразует данные из маркеров в 3D-координаты, используя их можно наложить изображения или 3D-объекты на плоскую поверхность.&nbsp;</p>
<p>Вы уже наверно видели JSARToolkit в действии на демке <a href="http://fhtr.org/">Ilmari Heikkinen</a> — <a href="https://mozillademos.org/demos/remixingreality/demo.html">Remixing Reality</a>.<br />
Демо Ilmari это часть Мозилловской “<a href="https://demos.mozilla.org/en-US/">Web O’ Wonder</a>”, — сайт, демонстрирующий новые технологии, которые будут добавлены в <a href="http://www.mozilla.com/en-US/firefox/RC/">Firefox 4</a>.</p>
</div>
<h4>Исследования HTML5 клипов</h4>
<div>Заказчик поставил нам задачу — оценить возможность использования JSARToolkit для онлайн HTML5 клипов. (Нас попросили рассмотреть только тех пользователей, которые использовали последнюю версию Firefox и Chrome)<br />
Вот некоторые из вопросов, на которые мы бы хотели ответить:<br />
— Будет ли обработка быстрой на медленных компьютерах?<br />
— Сколько AR Маркеров мы можем отследить одновременно?<br />
— На сколько быстро можно двигать маркер, чтобы он стал не отслеживаемым?<br />
— Какое наибольшее расстояние на котором камера может отследить маркер?&nbsp;</p>
<p>Ответы на эти вопросы, исходный код и демки можно найти ниже.<br />
<a name="habracut"></a></p>
</div>
<h4>Запись видео</h4>
<div>
<p><img src="http://weblog.bocoup.com/wp-content/uploads/2011/03/FlipUltraHD1.png" alt="" align="left" /> Для записи тестового видео я использовал Flip Ultra HD. Качество видео Flip Ultra HD приемлемое, учитывая то, что это не профессиональная камера. Мы знали что ничего хорошего с такой камеры мы не получим, но этого было достаточно для теста. Основная проблема такой низкокачественной камерой — неспособность переключать скорость затвора.</p>
<p>Это означало, что мы ничего не сможем поделать с размытыми AR Метками если мы будем двигаться слишком быстро. Мы были удивлены на сколько быстро мы теряем маркер, кода мы двигаемся из стороны в сторону.<br />
Тем не менее, мы уверены, что при съемке в хорошо освещенной студии с использованием камеры с высокой скоростью затвора будет очень мало не читаемых AR Меток.</p>
</div>
<h4>Печать AR Маркеров</h4>
<div><img src="http://weblog.bocoup.com/wp-content/uploads/2011/03/printed-augmented-reality-markers.png" alt="" align="left" /> Я напечатал несколько маркеров, которые шли вместе с JSARToolkit и начал снимать тестовые кадры на кухне. Я даже и не ожидал, что все заработает с первого раза, каждое видео, добавленное в библиотеку оказалось рабочим.&nbsp;</p>
<p>Некоторые результаты были не качественные, но я хочу повторить, что качество нашей камеры было плохим по сравнению с профессиональными. Мы снимали видео без фокусировки на отдельных маркерах, что могло бы добавить точность их отслеживания.</p>
</div>
<h4>Перекодирование видео в VP8 WebM</h4>
<div><img src="http://weblog.bocoup.com/wp-content/uploads/2011/03/tracking-blur-augmented-reality1.png" alt="" align="left" /> Мы записывали видео в формате H.264 Mpeg. Чтобы все работало с HTML5 video мы должны были сконвертировать видео в WebM. Первый декодер видео, который я попробовал был Ffmpeg2Theora, судя по названию он должен был кодировать видео в WebM. Однако я понял, что с Ffmpeg2Theora есть проблемы. Когда я кодировал видео под Linux оно могло не проигрываться в Windows и наоборот.&nbsp;</p>
<p>После тестов прочих кодировщиков я остановился на Miro Video Converter. К сожалению Miro не умеет обрабатывать несколько видео, но видео, которое он производит работает на всех ОС и браузерах.</p>
</div>
<h4>Создание обертки</h4>
<div>Я хотел написать простое API на основе JSARToolkit, которое можно было использовать повторно. Что-нибудь что я бы мог подключить к другой JavaScript библиотеке, например Popcorn.js. Код, который я нашел в демке Ilmari был специфичный для конкретной задачи. Так как код не изобиловал комментариями, у меня были проблемы с пониманием, что происходит. Пришлось экспериментировать. Я пришел к простому способу написания обертки для JSARToolkit.&nbsp;</p>
<p>Первый шаг в использовании обертки JSARToolkit — установка вашего трекера. Пример как это можно сделать:</p>
</div>
<pre><code>// Пример создания трекера со всеми возможными опциями
    var myTracker = jsartoolkit.tracker({
        src       : 'my-video.webm',                  // Исходник для видео
        autoplay  : true,                             // Стоит ли включить видео сразу
        repeat    : true,                             // Включить повтор
        volume    : 0,                                // Звук из видео
        target    : doc.getElementById('DOMTarget'),  // DOM element в который будет добавлен canvas
        width     : 720,                              // Ширина кадра
        height    : 360,                              // Высота кадра
        threshold : 100,                              // Настройка освещенности кадра
        ratio     : 0.5,                              // Настройка размера скрытого canvas для трекинга (1 = 1в1 как видео)
        debug     : false                             // Выводить ли отладочную информацию - для порога освещенности кадра
    });
</code></pre>
<div>
<p>Как только трекер был создан, следующим шагом стало добавления контента маркерам.<br />
Мы добавили статическое изображение, а затем и 3D объект, экспортированный из Blender3D:</p>
</div>
<pre><code>    // Добавления картинки первому маркеру
    myTracker.marker(0).image('my-image_01.png');

    // Добавление модели Blender3D
    myTracker.marker(2).model('HTML5_Logo001');
</code></pre>
<div>Этот пример показывает как обновить свойства маркера после того как он был создан:</div>
<pre><code>    // Настройка свойств маркера 0
    myTracker.marker(0)
      .scale(1)
      .axis(0, 0, 1)
      .angle(0)
      .position(0,0,0)
    ;
</code></pre>
<div>Вы также можете добавить более сложное поведение, используя JSARToolkit-Wrapper. Следующий пример демонстрирует как обновить свойства маркера в реальном времени. Этот код заставляет первый маркер крутиться и пульсировать:</div>
<pre><code>    // Анимация свойств маркера Marker_0 по таймеру
    var interval = global.setInterval( function(){
      var date    = + new Date(),
          scl     = 1.5 + (Math.sin( date/200 ) * 0.5),
          axs     = Math.cos( date/300 ),
          posX    = Math.sin( date/300 ),
          posY    = Math.cos( date/300 )
      ;

      myTracker.marker(0)
        .scale(scl)
        .axis(0, axs, 0)
        .position(posY, posX, 0)
        .angle(date / 230)
      ;
    }, 20);
</code></pre>
<div>Для доступа к видео трекера вы можете сделать что-то такое:</div>
<pre><code>    // Доступ к видео элементу трекера и установка currentTime
    myTracker.video.currentTime = 1;
</code></pre>
<h4>Ответы на вопросы</h4>
<div><img src="http://weblog.bocoup.com/wp-content/uploads/2011/03/tracking-100-augmented-reality-markers.png" alt="" />&nbsp;</p>
<p><strong>Будет ли обработка быстрой на медленных компьютерах?</strong><br />
Обработка видео и определение положения маркера очень быстрое. Я практически не заметил разницы в отслеживании 1 маркера и 100 маркеров. Основная нагрузка — наложение контента на видео.</p>
<p><strong>Сколько AR-Маркеров мы можем отследить одновременно?</strong><br />
Я отслеживал 100 маркеров одновременно без каких-либо проблем.</p>
<p><strong>На сколько быстро можно двигать маркер, чтобы он стал не отслеживаемым?</strong><br />
Все зависит от вашей камеры и как вы снимаете. Если использовать камеру с высокой скоростью затвора, такие, которые используются для записи спортивных состязаний, то мы получим минимум размытых маркеров (если вообще получим) и они будут отслеживаться очень хорошо.</p>
<p><strong>Какое наибольшее расстояние на котором камера может отследить маркер?</strong><br />
Опять все зависит от нескольких факторов — от скорости перемещения камеры/объектов и от освещения. В хорошо освещенной комнате (не профессиональной студии). У меня получилось отслеживать Маркеры с 10 метров в направлении объектива в разрешении 720р. Чем выше разрешение камеры, тем выше качество отслеживания маркеров. Одну вещь которую стоит отметить: вы можете снимать ваше видео в разрешении 1080, кэшировать результаты трекинга и уменьшить число обработок на стороне клиента. Можно покрутить ratio если что-то плохо отслеживается или threshold если кадр был плохо освещен.</p>
</div>
<h4>Заключение</h4>
<h5>Плюсы</h5>
<div>— Легко внедрить<br />
— Оптимальный алгоритм отслеживания, не нагружает процессор<br />
— Можно отслеживать по крайней мере 100 маркеров<br />
— Можно экспортировать напрямую с Blender3D<br />
— Можно накладывать любой контент: картинки, видео, 3D объекты&nbsp;</p>
</div>
<h5>Минусы</h5>
<div>— Слишком много глобальных переменных в коде исходной библиотеки<br />
— Необходимо немного подкрутить экспорт из Blender3D<br />
— Не поддерживается одновременная обработка нескольких видео<br />
— Слишком много затратных вызовов getElementById()&nbsp;</p>
<p>Необходимо поделать большую работу если вы хотите использовать эту библиотеку на продкшене или сделать её частью большой библиотеки. Но после огромного числа тестов и экспериментов, я скажу, что этот код работает потрясающе!</p>
</div>
<h4>Примеры, Тесты и ссылки</h4>
<div><a href="http://code.bocoup.com/webgl/JSARToolkit-Wrapper/JSARToolkit-Wrapper_Demo.html">JSARToolkit-Wrapper Demo</a><br />
<a href="http://code.bocoup.com/webgl/JSARToolkit-Wrapper/video-tracking-tests">JSARToolkit Video Tests</a><br />
<a href="http://code.bocoup.com/webgl/JSARToolkit-Wrapper/marker-images">JSARToolkit Marker Images</a><br />
<a href="https://github.com/Bocoup/JSARToolkit-Wrapper">JSARToolkit-Wrapper on Github</a>&nbsp;</p>
<p>Для просмотра вам необходима последняя версия Firefox 4 или Chrome.</p>
</div>
<h4>От переводчика</h4>
<div>Автор к сожалению пока не выложил демку. Применение AR в таком виде в котором он представлен в переводе не очень широкое, но с появлением <a href="http://habrahabr.ru/blogs/html5/113547/">HTML5 Device Element</a> (<a href="http://ajaxian.com/archives/video-conferencing-with-the-html5-device-element">ещё </a></div>
<div>статья)</div>
<div>Original article from <a href="http://habrahabr.ru/blogs/javascript/115485/">http://habrahabr.ru/blogs/javascript/115485/</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.spicesoft.net/blog/2011/03/15/augmented-reality/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Веб-кластер</title>
		<link>http://www.spicesoft.net/blog/2011/03/14/%d0%b2%d0%b5%d0%b1-%d0%ba%d0%bb%d0%b0%d1%81%d1%82%d0%b5%d1%80/</link>
		<comments>http://www.spicesoft.net/blog/2011/03/14/%d0%b2%d0%b5%d0%b1-%d0%ba%d0%bb%d0%b0%d1%81%d1%82%d0%b5%d1%80/#comments</comments>
		<pubDate>Mon, 14 Mar 2011 02:50:24 +0000</pubDate>
		<dc:creator>Berd</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.spicesoft.net/blog/?p=11</guid>
		<description><![CDATA[Originally posted on www.habrahabr.ru Приветствую, уважаемые сообщники! Эта статья — о том, как мы реализовали веб-кластер для новостного портала (с пиком посещений в 130 тысяч уникальных посетителей в день — это 7Тб траффика за 3 дня — выборы и 2 &#8230; <a href="http://www.spicesoft.net/blog/2011/03/14/%d0%b2%d0%b5%d0%b1-%d0%ba%d0%bb%d0%b0%d1%81%d1%82%d0%b5%d1%80/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Originally posted on www.habrahabr.ru</p>
<p>Приветствую, уважаемые сообщники!</p>
<p>Эта статья — о том, как мы реализовали веб-кластер для новостного портала (с пиком посещений в 130 тысяч уникальных посетителей в день — это 7Тб траффика за 3 дня — выборы и 2 последующих. Сейчас в среднем кластер раздаёт 35-40 Тб траффика в месяц), о том, как по-разному понимают одинаковые задачи программисты и журналисты, о том, как можно достичь одной и той же цели, идя разными путями.</p>
<p>Она будет интересна тем, кто хочет построить легко масштабируемый географически распределённый веб-кластер, не вкладывая астрономических сумм в оборудование (а по меркам телевидения — будут вообще смешные суммы).</p>
<p>Я больше чем уверен, что маркетологи, толкающие убер-решения свежевыпущенных продуктов, имеющих в своём названии слова «масштабируемый веб-кластер» или «horizontal infinite scalable web cluster», меня возненавидят.</p>
<p>Я больше чем уверен, что конкуренты наших клиентов будут удивлены простотой решения, которое мы использовали.</p>
<p><a name="habracut"></a></p>
<p>Я не буду приводить банальных конфигов, которые можно найти в любом тоториале по настройке PHP, Nginx и Firebird (у последнего, строго говоря, и настраивать-то нечего — всё работает с пол-пинка «из коробки») и вообще буду рассказывать о сути решения, а не о том, какая из версий PHP лучше.</p>
<p>Опытным проектировщикам вряд ли будет интересно — они и так всё знают, а вот тем, кто только начинает путь на нелёгком поприще проектирования систем сложнее, чем «Hello, World!» наверняка будет что подчерпнуть — решение в боевом режиме уже скоро как 2 года, при этом никаких архитектурных проблем не возникало (хотя выход из строя сразу двух жёстких дисков на двух из трёх узлов был, но никто ничего не заметил — сайты чуть-чуть медленнее открывались, чем обычно).</p>
<p>Итак, пара слов, с чего всё начиналось. Жил-был сайтик группы независимых журналистов, которые очень мечтали стать настоящим телевидением (забегая вперёд, скажу, что у них это получилось — они создали своё, вполне успешное телевидение с «блэкджеком и шл&#8230;» — далее по тексту). Страна у нас маленькая, ничего страшного не происходит (и мы этому рады), но раз в 4 года у нас традиционно проходят выборы в Парламент. Который уже традиционно никак не избирает Президента. (Не бойтесь, политики тут не будет, это просто для общего понимания момента).</p>
<p>Разумеется, в период перед выборами и немного после все интернет СМИ очень сильно колбасит. Некоторые сайты не просто лежат, они валяются, некоторые переодически пытаются выдать хотя бы строчку текста, но проблема всеобщая и известная — сайты не справляются с наплывом посетителей. Я про обычные, текстовые сайты. А у наших клиентов сайт был необычный. Дело в том, что у них было и видео — новостные сюжеты, они производили 10 гигабайт в месяц — в то время, сейчас они создают такое количество видео в день. Ко всему прочему (это последнее упоминание политики, честное слово) эти журналисты не отличались особой лояльностью к власти. Говорили и писали что хотели. Совсем обнаглели, да? Мы всегда себя позиционируем как наёмников — клиент предлагает задачу, мы предлагаем её решение. Всё остальное нас не интересует, мы соблюдаем нейтралитет.</p>
<p>Перед нами была поставлена задача — предложить решение для новостных сайтов, которое позволит не просто выстоять при наплыве 50-100 тыс посетителей, но ещё было бы и географически разбросано по миру и управлялось из мобильного бункера любой точки Вселенной планеты. Разумеется, географический разброс узлов кластера оставался за нами. В результате мы предложили следующую схему (художник из меня никакой, вы уж меня извините):</p>
<p><img src="http://habrastorage.org/storage/c291b663/b2706a7b/8bf348f8/3ed9ac8c.gif" alt="" /></p>
<p>(Это упрощённая схема на ноябрь, в дальнейшем почти все сервера перенесли к Hetzner-у, так как у Netdirekt-a в то время постоянно колбасило канал. Сейчас у них с сетью ситуация обстоит намного лучше).<br />
Обычные посетители видят один из 3-х серверов, при этом, мы сделали так, что «лёгкий» контент в виде текста и картинок все посетители из Молдовы тянули с одного их 3-х, а «тяжёлый» контент (видео) — тянули с сервера, расположенного у местного провайдера. Внешние посетители просто не видели молдавское зеркало и весь контент тянули с одного из немецких серверов.</p>
<p>Вот, что у нас получилось с посетителями в результате (каждая часть портала имеет свой счётчик):</p>
<p><img src="http://habrastorage.org/storage/879a1d8a/a6b18a37/d3e2b7e5/52b3142d.png" alt="" /></p>
<p>Эта схема позволяет сменить управляющий сервер в любой момент, сама проверяет доступность узлов кластера, легко масштабируется — в качестве резервного рассматривался и Amazon EC – более того, Amazon EC даже использовался некоторое время для видеостриминга (около 4-х месяцев), но из-за дороговизны траффика решено было всё-таки стриминг-ноды перенести к немецкому Hetzner-у.<br />
Непосредственно за 2 недели до часа «Х» мы взяли резервные сервера и держали их наготове (но пользователи их не видели, так как держать активным сервер несколько дешевле, чем использовать его в боевом режиме — только из-за траффика).</p>
<p>Как это всё работает? Очень просто — молча и круглосуточно <img src='http://www.spicesoft.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>На управляющем сервере (как я уже упоминал, у портала 2 больших «раздела»: новости в виде текста с картинками и новости в виде текстового дайджеста и видео— де-факто используется 2 сервера, но для простоты я изобразил один) есть то, что обычно именуется системой управления контентом.</p>
<p>Основная задача этого сервера — позволять журналистам добавлять новости. Раз в определённое время (3-5 минут) стартует скрипт, который создаёт… offline-копию сайта. Разумеется, генерируются только страницы, которые были изменены или которые нуждаются в перестройке из-за кроссылок и зависимостей.</p>
<p>Это очень просто реализуется при помощи генераторов (sequense) и каскадных триггеров в Firebird — процедуре требуется внести изменения только в основную страницу сайта, а каскадные триггеры обновят все зависимости, пометив каждую страницу, которая нуждается в обновлении. Пометка выставляется не в виде флага 1/0, а в виде уникального номера, получаемого на основе генератора. Скрипт создания оффлайновой версии при старте узнаёт новое значение генератора, считывает значение этого генератора от своего предыдущего запуска и пересоздаёт все страницы в полученном диапазоне. При этом, так как мы используем транзакционный механизм Firebird – скрипту глубоко наплевать, какие изменения происходят во время его выполнения — т.е. у нас всегда создаётся целостная и непротиворечивая версия сайта, что бы при этом не делали репортёры.</p>
<p>Таким образом, у нас создаётся мастер-копия портала (ну или двух порталов, если угодно — текстового и видео). Скрипт (как и сама админка) написан на PHP и для работы с Firebird использует ADODB – так что его довольно-таки просто можно перестраивать по желанию заказчика*.</p>
<p>(* Но мы собираемся избавиться от ADODB в скором времени во всех наших будущих проектах — его универсальность только вредит, так как нормального механизма работы с БД, позволяющего использовать все особенности Firebird SQL сервера (впрочем, как и остальных) там не реализовано — к примеру, невозможно перехватывать исключения при выборке из селективных процедур, нет гибкого управления транзакциями и вообще, у этих классов слишком много ИИ — я предпочитаю самостоятельно решать, когда я хочу откатить тразакцию, а когда — подтвердить.)</p>
<p>Единственное, что пришлось менять в настройках Firebird – это значение размера кэша страниц БД — так как количество подключений к БД очень небольшое (редко когда более 50-60 одновременных подключений), то и количество страниц экспериментальным путём было увеличено до 2048 (мы используем Classic вариант, для архитектуры Super это значение спокойно можно увеличить в 10 раз, так как там общий кэш страниц. В грядущей версии Firebird 3.0 разработчики обещают одну SMP-friendly архитектуру с общим кэшем, так что для неё вполне можно будет использовать большие значения для настроек страничного кэша).</p>
<p>Затем, при помощи обычного rsync-а разница изменений раскидывается по зеркалам, которые из себя представляют обычные узлы для раздачи статики на основе Nginx. Я думаю, не требуется рассказывать, на что способен 4-хядерный сервер с 12 Гигабайтами оперативки при раздаче одной только статики? <img src='http://www.spicesoft.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>При этом, 10% канала каждой ноды (это как раз 10 или 100 мегабит, в зависимости от конкретного подключения) зарезервировано для синхронизации. Синхронизация происходит в 2 этапа — сначала синхронизируется «тяжёлый» контент — картинки и видео, потом — текст (html/xml/js).</p>
<p>Иногда (при загруженных каналах от управляющего сервера к зеркалам) посетитель может увидеть маленькие несоответствия в виде негрузящихся картинок и/или видеороликов — так как используется round-robin DNS, то текст страницы пользователь может получить с одного зеркала, а ссылку на видео — с другого. Это не мешает порталу работать — текст есть всегда, а картинка или видео рано или поздно объявятся.</p>
<p>Так как на сайтах есть динамические формочки — например, подписка на рассылку новостей — то эти формочки обрабатываются отдельно выделенным сервером (он не изображён на схеме, но сути это не меняет). Даже если предположить, что все посетители одновременно ломанутся подписываться на новости и этот сервер «ляжет» — ничего страшного не случится — формы подгружаются в iframe и на доступности новостей отсутствие этих формочек никак не отражается.</p>
<p>Добавление нового узла происходит просто — сначала синхронизируется новое зеркало с основной копией (это происходит параллельно с обычным режимом работы синхронизатора), затем запись добавляется в DNS и… никто ничего не замечает.</p>
<p>Удаление ноды происходит проще — просто убирается запись из DNS. Добавление и удаление вполне поддаются автоматизации (именно так мы поступили с частью, которая отвечала за веб-стриминг около 1000 мегабитных потоков на Amazom EC), но если вы вдруг решитесь повторять подобное — советую сначала посчитать, сколько занимает первичная синхронизация данных (у нас это 2 Гигабайта для «лёгкой версии портала» и примерно 1 Терабайт для видео, хранится только несколько последних месяцев).</p>
<p>Именно поэтому динамическое добавление/удаление нод из пула запасных мы убрали через некоторое время работы проекта — слишком много занимает контент и слишком уж параноидальным получился скрипт — убирал ноды при каждой проблеме связи с ними.</p>
<p>Отдельно стоит упомянуть про подсчёты отображений новости. У меня сложилось впечатление, что любимое занятие у журналистов (помимо написаний/съёмок репортажей) — это мерянье количеством посетителей той или иной новости. Примерно литр крови и километр нервов нам пришлось потратить, чтобы убедить журналистскую братию в том, что не требуется выводить изменения счётчиков в реальном времени.</p>
<p>Программисты прекрасно понимают, что узнать, сколько человек в настоящий момент читают статью просто невозможно, можно только посчитать количество запросов статьи с сервера, для журналистов же это одинаковые понятия. <img src='http://www.spicesoft.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Для подсчёта просмотров мы связались с Кирилом Коринским (также известным, как <a href="http://catap.habrahabr.ru/">catap</a>), который любезно согласился добавить фичу подсчёта просмотров URL в свою ветку Nginx-а. Ну а дальше уже всё просто — все узлы переодически опрашиваются и счётчики страниц учитываются в свойствах самой страницы. Так как счётчики (т.е. сами значения) хранятся в отдельных файлах (сейчас это по одному файлу на новость, в скором времени мы планируем сделать группу счётчиков в одном файле, чтобы уменьшить количество самих файлов) — то при синхронизации передаётся не страницы сайта целиком, а только файл-счётчик. При большом количестве файлов это создаёт дополнительную нагрузку на дисковую подсистему — поэтому, при использовании такого же подхода сразу продумывайте о том, как разбить счётчики по группам — мы остановились на разбиении счётчиков по типам новостей и дате — файлы относительно маленькие и со временем они перестают меняться, так как старые новости никого практически не интересуют.</p>
<p>Вот вкратце, плюсы использованного нами решения:</p>
<ol>
<li>Использование статических сайтов в качестве узлов веб-кластера позволяет свести администрирование всего кластера к нескольким рутинным задачам — обновлению операционной системы узлов и оплате траффика. Этот же пункт позволяет раскидать географически узлы кластера, что вкупе с GEO-DNS может рассматриваться вообще как некоторый аналог сети доставки контента (CDN) — по сути это оно и есть.</li>
<li>Использование транзакционного механизма БД и перенос логики в саму БД позволяет всегда иметь целостную и логически непротиворечивую версию сайта — впрочем, я бы очень удивился, если бы «срез» данных с сервера был бы логически нецелостным.</li>
<li>Если ожидается наплыв посетителей — то простым увеличением узлов кластера можно легко с ним справиться. В нашем случае, полный ввод нового узла в строй занимал чуть более часа для текстовой части портала и около суток (нельзя впихнуть невпихуемое) для видео. Если смириться с частичной синхронизацией сайтов и остальное «доливать» в фоне — то ввод нового узла для видео также можно сократить до часа.</li>
<li>Административный сервер можно сделать из любого из узлов (при необходимости) — достаточно просто развернуть бэкап базы (в сжатом виде около сотни мегабайт). Весь остальной контент уже есть.</li>
</ol>
<p>Ну и парочка минусов, чтобы не всё казалось таким безоблачным:</p>
<ol>
<li>Решение не подходит для случаев, когда есть части сайта, которые по-разному должны видеть разные пользователи, т.е. когда по условию задачи страницы генерируются персонально для каждого пользователя. В нашем случае этого оказалось и ненужно.</li>
<li>Счётчики посещений обновляются с отставанием примерно в полчаса-час. Терпимо, но вам придётся в этом долго убеждать клиента.</li>
<li>Больше всего проблем доставляет синхронизация с местным зеркалом — наши провайдеры ещё не продают траффик по цене в 7 евро за Терабайт и если и предоставляют 100 честных Мегабит в мир — то по очень неадекватным ценам.</li>
<li>Проектируйте менее параноидальную систему слежения за узлами кластера — наша оказалась слишком чувствительной, пришлось переводить добавление и удаление узлов в ручной режим.</li>
</ol>
<p>И буквально маленькая щепотка опыта, которая позволит разнообразить пресную кашу будней.</p>
<p>Для хранения оффлайн-копии сайта мы используем файловую систему JFS. Она себя очень хорошо зарекомендовала и при работе с множеством мелких файлов и при работе с большими файлами (по моему опыту ещё только XFS может практически моментально удалить файл размером в 200-300Гб).</p>
<p>Так вот — по умолчанию файловая система монтировалась с параметрами по умолчанию. Но так как у нас со временем стало очень много файлов, дисковые операции стали немного подтормаживать. Так как время последнего доступа к файлу нам не требуется, я добавил опцию «noatime» к параметрам монтирования ФС. Вот что получилось — момент добавления, думаю, вы определите сами:</p>
<p><img src="http://habrastorage.org/storage/14472ba5/b9991b4a/e025d4b8/792f1fcc.png" alt="" /></p>
<p>Кратко повторюсь — для стабильной работы в обычном режиме используется:</p>
<ul>
<li>3 сервера для раздачи контента</li>
<li>2 сервера для «админки»</li>
<li>2 сервера для DNS и системы слежения за остальными серверами.</li>
</ul>
<p>Узлы кластера разбросаны географически и находятся у разных провайдеров.<br />
В случае ожидаемых событий, привлекающих большое количество посетителей — подключаются дополнительные сервера для раздачи контента.</p>
<p>В месяц потребляется около 40Тб траффика, общий объём контента — чуть более 1 Терабайта, видеоконтент хранится около 3-х месяцев.</p>
<p>Я с удовольствием отвечу на вопросы хабрасообщества.<br />
Приветствую, уважаемые сообщники!</p>
<p>Эта статья — о том, как мы реализовали веб-кластер для новостного портала (с пиком посещений в 130 тысяч уникальных посетителей в день — это 7Тб траффика за 3 дня — выборы и 2 последующих. Сейчас в среднем кластер раздаёт 35-40 Тб траффика в месяц), о том, как по-разному понимают одинаковые задачи программисты и журналисты, о том, как можно достичь одной и той же цели, идя разными путями.</p>
<p>Она будет интересна тем, кто хочет построить легко масштабируемый географически распределённый веб-кластер, не вкладывая астрономических сумм в оборудование (а по меркам телевидения — будут вообще смешные суммы).</p>
<p>Я больше чем уверен, что маркетологи, толкающие убер-решения свежевыпущенных продуктов, имеющих в своём названии слова «масштабируемый веб-кластер» или «horizontal infinite scalable web cluster», меня возненавидят.</p>
<p>Я больше чем уверен, что конкуренты наших клиентов будут удивлены простотой решения, которое мы использовали.</p>
<p><a name="habracut"></a></p>
<p>Я не буду приводить банальных конфигов, которые можно найти в любом тоториале по настройке PHP, Nginx и Firebird (у последнего, строго говоря, и настраивать-то нечего — всё работает с пол-пинка «из коробки») и вообще буду рассказывать о сути решения, а не о том, какая из версий PHP лучше.</p>
<p>Опытным проектировщикам вряд ли будет интересно — они и так всё знают, а вот тем, кто только начинает путь на нелёгком поприще проектирования систем сложнее, чем «Hello, World!» наверняка будет что подчерпнуть — решение в боевом режиме уже скоро как 2 года, при этом никаких архитектурных проблем не возникало (хотя выход из строя сразу двух жёстких дисков на двух из трёх узлов был, но никто ничего не заметил — сайты чуть-чуть медленнее открывались, чем обычно).</p>
<p>Итак, пара слов, с чего всё начиналось. Жил-был сайтик группы независимых журналистов, которые очень мечтали стать настоящим телевидением (забегая вперёд, скажу, что у них это получилось — они создали своё, вполне успешное телевидение с «блэкджеком и шл&#8230;» — далее по тексту). Страна у нас маленькая, ничего страшного не происходит (и мы этому рады), но раз в 4 года у нас традиционно проходят выборы в Парламент. Который уже традиционно никак не избирает Президента. (Не бойтесь, политики тут не будет, это просто для общего понимания момента).</p>
<p>Разумеется, в период перед выборами и немного после все интернет СМИ очень сильно колбасит. Некоторые сайты не просто лежат, они валяются, некоторые переодически пытаются выдать хотя бы строчку текста, но проблема всеобщая и известная — сайты не справляются с наплывом посетителей. Я про обычные, текстовые сайты. А у наших клиентов сайт был необычный. Дело в том, что у них было и видео — новостные сюжеты, они производили 10 гигабайт в месяц — в то время, сейчас они создают такое количество видео в день. Ко всему прочему (это последнее упоминание политики, честное слово) эти журналисты не отличались особой лояльностью к власти. Говорили и писали что хотели. Совсем обнаглели, да? Мы всегда себя позиционируем как наёмников — клиент предлагает задачу, мы предлагаем её решение. Всё остальное нас не интересует, мы соблюдаем нейтралитет.</p>
<p>Перед нами была поставлена задача — предложить решение для новостных сайтов, которое позволит не просто выстоять при наплыве 50-100 тыс посетителей, но ещё было бы и географически разбросано по миру и управлялось из мобильного бункера любой точки Вселенной планеты. Разумеется, географический разброс узлов кластера оставался за нами. В результате мы предложили следующую схему (художник из меня никакой, вы уж меня извините):</p>
<p><img src="http://habrastorage.org/storage/c291b663/b2706a7b/8bf348f8/3ed9ac8c.gif" alt="" /></p>
<p>(Это упрощённая схема на ноябрь, в дальнейшем почти все сервера перенесли к Hetzner-у, так как у Netdirekt-a в то время постоянно колбасило канал. Сейчас у них с сетью ситуация обстоит намного лучше).<br />
Обычные посетители видят один из 3-х серверов, при этом, мы сделали так, что «лёгкий» контент в виде текста и картинок все посетители из Молдовы тянули с одного их 3-х, а «тяжёлый» контент (видео) — тянули с сервера, расположенного у местного провайдера. Внешние посетители просто не видели молдавское зеркало и весь контент тянули с одного из немецких серверов.</p>
<p>Вот, что у нас получилось с посетителями в результате (каждая часть портала имеет свой счётчик):</p>
<p><img src="http://habrastorage.org/storage/879a1d8a/a6b18a37/d3e2b7e5/52b3142d.png" alt="" /></p>
<p>Эта схема позволяет сменить управляющий сервер в любой момент, сама проверяет доступность узлов кластера, легко масштабируется — в качестве резервного рассматривался и Amazon EC – более того, Amazon EC даже использовался некоторое время для видеостриминга (около 4-х месяцев), но из-за дороговизны траффика решено было всё-таки стриминг-ноды перенести к немецкому Hetzner-у.<br />
Непосредственно за 2 недели до часа «Х» мы взяли резервные сервера и держали их наготове (но пользователи их не видели, так как держать активным сервер несколько дешевле, чем использовать его в боевом режиме — только из-за траффика).</p>
<p>Как это всё работает? Очень просто — молча и круглосуточно <img src='http://www.spicesoft.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>На управляющем сервере (как я уже упоминал, у портала 2 больших «раздела»: новости в виде текста с картинками и новости в виде текстового дайджеста и видео— де-факто используется 2 сервера, но для простоты я изобразил один) есть то, что обычно именуется системой управления контентом.</p>
<p>Основная задача этого сервера — позволять журналистам добавлять новости. Раз в определённое время (3-5 минут) стартует скрипт, который создаёт… offline-копию сайта. Разумеется, генерируются только страницы, которые были изменены или которые нуждаются в перестройке из-за кроссылок и зависимостей.</p>
<p>Это очень просто реализуется при помощи генераторов (sequense) и каскадных триггеров в Firebird — процедуре требуется внести изменения только в основную страницу сайта, а каскадные триггеры обновят все зависимости, пометив каждую страницу, которая нуждается в обновлении. Пометка выставляется не в виде флага 1/0, а в виде уникального номера, получаемого на основе генератора. Скрипт создания оффлайновой версии при старте узнаёт новое значение генератора, считывает значение этого генератора от своего предыдущего запуска и пересоздаёт все страницы в полученном диапазоне. При этом, так как мы используем транзакционный механизм Firebird – скрипту глубоко наплевать, какие изменения происходят во время его выполнения — т.е. у нас всегда создаётся целостная и непротиворечивая версия сайта, что бы при этом не делали репортёры.</p>
<p>Таким образом, у нас создаётся мастер-копия портала (ну или двух порталов, если угодно — текстового и видео). Скрипт (как и сама админка) написан на PHP и для работы с Firebird использует ADODB – так что его довольно-таки просто можно перестраивать по желанию заказчика*.</p>
<p>(* Но мы собираемся избавиться от ADODB в скором времени во всех наших будущих проектах — его универсальность только вредит, так как нормального механизма работы с БД, позволяющего использовать все особенности Firebird SQL сервера (впрочем, как и остальных) там не реализовано — к примеру, невозможно перехватывать исключения при выборке из селективных процедур, нет гибкого управления транзакциями и вообще, у этих классов слишком много ИИ — я предпочитаю самостоятельно решать, когда я хочу откатить тразакцию, а когда — подтвердить.)</p>
<p>Единственное, что пришлось менять в настройках Firebird – это значение размера кэша страниц БД — так как количество подключений к БД очень небольшое (редко когда более 50-60 одновременных подключений), то и количество страниц экспериментальным путём было увеличено до 2048 (мы используем Classic вариант, для архитектуры Super это значение спокойно можно увеличить в 10 раз, так как там общий кэш страниц. В грядущей версии Firebird 3.0 разработчики обещают одну SMP-friendly архитектуру с общим кэшем, так что для неё вполне можно будет использовать большие значения для настроек страничного кэша).</p>
<p>Затем, при помощи обычного rsync-а разница изменений раскидывается по зеркалам, которые из себя представляют обычные узлы для раздачи статики на основе Nginx. Я думаю, не требуется рассказывать, на что способен 4-хядерный сервер с 12 Гигабайтами оперативки при раздаче одной только статики? <img src='http://www.spicesoft.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>При этом, 10% канала каждой ноды (это как раз 10 или 100 мегабит, в зависимости от конкретного подключения) зарезервировано для синхронизации. Синхронизация происходит в 2 этапа — сначала синхронизируется «тяжёлый» контент — картинки и видео, потом — текст (html/xml/js).</p>
<p>Иногда (при загруженных каналах от управляющего сервера к зеркалам) посетитель может увидеть маленькие несоответствия в виде негрузящихся картинок и/или видеороликов — так как используется round-robin DNS, то текст страницы пользователь может получить с одного зеркала, а ссылку на видео — с другого. Это не мешает порталу работать — текст есть всегда, а картинка или видео рано или поздно объявятся.</p>
<p>Так как на сайтах есть динамические формочки — например, подписка на рассылку новостей — то эти формочки обрабатываются отдельно выделенным сервером (он не изображён на схеме, но сути это не меняет). Даже если предположить, что все посетители одновременно ломанутся подписываться на новости и этот сервер «ляжет» — ничего страшного не случится — формы подгружаются в iframe и на доступности новостей отсутствие этих формочек никак не отражается.</p>
<p>Добавление нового узла происходит просто — сначала синхронизируется новое зеркало с основной копией (это происходит параллельно с обычным режимом работы синхронизатора), затем запись добавляется в DNS и… никто ничего не замечает.</p>
<p>Удаление ноды происходит проще — просто убирается запись из DNS. Добавление и удаление вполне поддаются автоматизации (именно так мы поступили с частью, которая отвечала за веб-стриминг около 1000 мегабитных потоков на Amazom EC), но если вы вдруг решитесь повторять подобное — советую сначала посчитать, сколько занимает первичная синхронизация данных (у нас это 2 Гигабайта для «лёгкой версии портала» и примерно 1 Терабайт для видео, хранится только несколько последних месяцев).</p>
<p>Именно поэтому динамическое добавление/удаление нод из пула запасных мы убрали через некоторое время работы проекта — слишком много занимает контент и слишком уж параноидальным получился скрипт — убирал ноды при каждой проблеме связи с ними.</p>
<p>Отдельно стоит упомянуть про подсчёты отображений новости. У меня сложилось впечатление, что любимое занятие у журналистов (помимо написаний/съёмок репортажей) — это мерянье количеством посетителей той или иной новости. Примерно литр крови и километр нервов нам пришлось потратить, чтобы убедить журналистскую братию в том, что не требуется выводить изменения счётчиков в реальном времени.</p>
<p>Программисты прекрасно понимают, что узнать, сколько человек в настоящий момент читают статью просто невозможно, можно только посчитать количество запросов статьи с сервера, для журналистов же это одинаковые понятия. <img src='http://www.spicesoft.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Для подсчёта просмотров мы связались с Кирилом Коринским (также известным, как <a class="user_link" href="http://catap.habrahabr.ru/"><span style="color: #6da3bd;">catap</span></a>), который любезно согласился добавить фичу подсчёта просмотров URL в свою ветку Nginx-а. Ну а дальше уже всё просто — все узлы переодически опрашиваются и счётчики страниц учитываются в свойствах самой страницы. Так как счётчики (т.е. сами значения) хранятся в отдельных файлах (сейчас это по одному файлу на новость, в скором времени мы планируем сделать группу счётчиков в одном файле, чтобы уменьшить количество самих файлов) — то при синхронизации передаётся не страницы сайта целиком, а только файл-счётчик. При большом количестве файлов это создаёт дополнительную нагрузку на дисковую подсистему — поэтому, при использовании такого же подхода сразу продумывайте о том, как разбить счётчики по группам — мы остановились на разбиении счётчиков по типам новостей и дате — файлы относительно маленькие и со временем они перестают меняться, так как старые новости никого практически не интересуют.</p>
<p>Вот вкратце, плюсы использованного нами решения:</p>
<ol>
<li>Использование статических сайтов в качестве узлов веб-кластера позволяет свести администрирование всего кластера к нескольким рутинным задачам — обновлению операционной системы узлов и оплате траффика. Этот же пункт позволяет раскидать географически узлы кластера, что вкупе с GEO-DNS может рассматриваться вообще как некоторый аналог сети доставки контента (CDN) — по сути это оно и есть.</li>
<li>Использование транзакционного механизма БД и перенос логики в саму БД позволяет всегда иметь целостную и логически непротиворечивую версию сайта — впрочем, я бы очень удивился, если бы «срез» данных с сервера был бы логически нецелостным.</li>
<li>Если ожидается наплыв посетителей — то простым увеличением узлов кластера можно легко с ним справиться. В нашем случае, полный ввод нового узла в строй занимал чуть более часа для текстовой части портала и около суток (нельзя впихнуть невпихуемое) для видео. Если смириться с частичной синхронизацией сайтов и остальное «доливать» в фоне — то ввод нового узла для видео также можно сократить до часа.</li>
<li>Административный сервер можно сделать из любого из узлов (при необходимости) — достаточно просто развернуть бэкап базы (в сжатом виде около сотни мегабайт). Весь остальной контент уже есть.</li>
</ol>
<p>Ну и парочка минусов, чтобы не всё казалось таким безоблачным:</p>
<ol>
<li>Решение не подходит для случаев, когда есть части сайта, которые по-разному должны видеть разные пользователи, т.е. когда по условию задачи страницы генерируются персонально для каждого пользователя. В нашем случае этого оказалось и ненужно.</li>
<li>Счётчики посещений обновляются с отставанием примерно в полчаса-час. Терпимо, но вам придётся в этом долго убеждать клиента.</li>
<li>Больше всего проблем доставляет синхронизация с местным зеркалом — наши провайдеры ещё не продают траффик по цене в 7 евро за Терабайт и если и предоставляют 100 честных Мегабит в мир — то по очень неадекватным ценам.</li>
<li>Проектируйте менее параноидальную систему слежения за узлами кластера — наша оказалась слишком чувствительной, пришлось переводить добавление и удаление узлов в ручной режим.</li>
</ol>
<p>И буквально маленькая щепотка опыта, которая позволит разнообразить пресную кашу будней.</p>
<p>Для хранения оффлайн-копии сайта мы используем файловую систему JFS. Она себя очень хорошо зарекомендовала и при работе с множеством мелких файлов и при работе с большими файлами (по моему опыту ещё только XFS может практически моментально удалить файл размером в 200-300Гб).</p>
<p>Так вот — по умолчанию файловая система монтировалась с параметрами по умолчанию. Но так как у нас со временем стало очень много файлов, дисковые операции стали немного подтормаживать. Так как время последнего доступа к файлу нам не требуется, я добавил опцию «noatime» к параметрам монтирования ФС. Вот что получилось — момент добавления, думаю, вы определите сами:</p>
<p><img src="http://habrastorage.org/storage/14472ba5/b9991b4a/e025d4b8/792f1fcc.png" alt="" /></p>
<p>Кратко повторюсь — для стабильной работы в обычном режиме используется:</p>
<ul>
<li>3 сервера для раздачи контента</li>
<li>2 сервера для «админки»</li>
<li>2 сервера для DNS и системы слежения за остальными серверами.</li>
</ul>
<p>Узлы кластера разбросаны географически и находятся у разных провайдеров.<br />
В случае ожидаемых событий, привлекающих большое количество посетителей — подключаются дополнительные сервера для раздачи контента.</p>
<p>В месяц потребляется около 40Тб траффика, общий объём контента — чуть более 1 Терабайта, видеоконтент хранится около 3-х месяцев.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spicesoft.net/blog/2011/03/14/%d0%b2%d0%b5%d0%b1-%d0%ba%d0%bb%d0%b0%d1%81%d1%82%d0%b5%d1%80/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spicesoft</title>
		<link>http://www.spicesoft.net/blog/2011/03/12/7/</link>
		<comments>http://www.spicesoft.net/blog/2011/03/12/7/#comments</comments>
		<pubDate>Sat, 12 Mar 2011 21:15:58 +0000</pubDate>
		<dc:creator>Berd</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.spicesoft.net/blog/?p=7</guid>
		<description><![CDATA[Прогрессивные технологии, как способ выжать из сервера максимум Вступление Забавно, но когда программист разрабатывает какой-либо продукт, он редко задумывается над вопросом могут ли на одну кнопку в один момент времени нажать одновременно 2000 человек. А зря. Оказывается могут. Как ни &#8230; <a href="http://www.spicesoft.net/blog/2011/03/12/7/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Прогрессивные технологии, как способ выжать из сервера максимум</h2>
<div>
<h1>Вступление</h1>
<p><img src="http://s59.radikal.ru/i164/0902/fb/6cda499057fb.png" alt="Просто красивый rrdtool =)" /><br />
Забавно, но когда программист разрабатывает какой-либо продукт, он редко задумывается над вопросом могут ли на одну кнопку в один момент времени нажать одновременно 2000 человек. А зря. Оказывается могут. Как ни странно но большинство движков, написанных такими программистами, очень плохо ведут себя под большими нагрузками. Кто бы подумал, а всего один лишний INSERT, не проставленный index, или кривая рекурсивная функция могут поднять load averages чуть ли не на порядок.</p>
<p>В этой статье я опишу как мы, разработчики проекта, сумели выжать из одного сервера с Pentium 4 HT / 512Mb RAM, максимум, держа одновременно 700+ пользователей на форуме и 120,000 на трекере. Да, проект этот — торрент трекер. Предлагаю сразу оставить в стороне разговоры о копирайтах и правах, мне это не интересно, что действительно интересно — это HighLoad.<br />
<a name="habracut"></a><br />
Для начала опишу проект таким, каким он был:</p>
<p>Обычный торрент трекер на движке <a href="http://torrentpier.info/index.php">TorrentPier</a> (он же в девичестве phpbb 2.x)</p>
<ul>
<li>Сервер на FreeBSD 6.0</li>
<li>Pentium 4 HT / 512Mb RAM</li>
<li>Web-сервер Apache</li>
<li>База MySQL</li>
<li>Вся логика на PHP</li>
</ul>
<p>То есть практически <a href="http://en.wikipedia.org/wiki/LAMP_(software_bundle)">LAMP</a></p>
<p>Вкратце сразу распишу последовательно те шаги которые мы предприняли:</p>
<ul>
<li>Установка на сервер <a href="http://en.wikipedia.org/wiki/PHP_accelerator">opcode cache</a></li>
<li>Замена apache на nginx</li>
<li>Кэширование некоторых промежуточных выборок в <strong>НЕ</strong> RDBMS</li>
<li>Перевод ключевой части (читай трекера) на C++</li>
<li>Оптимизация сетевого стека FreeBSD, а также её обновление до последней -STABLE</li>
<li>Оптимизация MySQL</li>
<li>Кэширование BB-кодов</li>
<li>Переписка кода на использование SphinxSearch</li>
<li>Профайлинг кода и установка средств мониторинга</li>
<li>Разборка запросов из MySQL slow query log</li>
</ul>
<p>Теперь о каждом пункте поподробнее</p>
<h1>Установка на сервер opcode cache</h1>
<p>Он нужен всегда! Установка <a href="http://en.wikipedia.org/wiki/PHP_accelerator">php-cache</a> дало 300%+ производительности, потратив 15 минут времени.<br />
Кэши бывают разные: <a href="http://eaccelerator.net/">eAccelerator</a>, <a href="http://xcache.lighttpd.net/">xCache</a>, <a href="http://pecl.php.net/package/APC">APC</a> и т.д… Мы остановились на последнем, из-за хорошей скорости и возможности хранить в нём пользовательские данные</p>
<h1>Замена apache на nginx</h1>
<p>Apache — тяжёлый и медленный, сначала стоял как основной web-сервер, потом перед ним был поставлен <a href="http://sysoev.ru/nginx/">nginx</a>, отдающий статику и сжимающий ответы gzip&#8217;ом. Далее от apache отказались вообще в пользу связки nginx+<a href="http://php-fpm.anight.org/">php-fpm</a> (если быть точным на тот момент это был spawn_fcgi, но сейчас такой вариант лучше). Связка в те времена была не самая популярная для production, но у нас она работала замечательно!</p>
<h1>Кеширование некоторых промежуточных выборок в <strong>НЕ</strong> RDBMS</h1>
<p><a href="http://en.wikipedia.org/wiki/RDBMS">RDBMS</a> — это зло. Оно удобно, но за удобство надо платить. В данном случае скоростью. А нам именно она и нужна. Так, что часть результатов самых популярных и не критичных к актуальности запросов к мускулу мы закешировали в APC. Сразу предчувствуя множество вопросов почему не в <a href="http://www.danga.com/memcached/">memcached</a>… Как бы вам ответить… мне уже надоело даже это слово слышать memcached,memcached,memcached как будто это панацея от всего. Его не предлагают последнее время разве, что только от диареи. В нашем случае выбор пал на APC ибо он не использует TCP соединение и из-за этого работает в <strong>разы</strong> быстрее. Темболее пока у нас всё отлично крутится на одном сервере и нам распределённое хранилище не так уж и нужно.<br />
<a href="http://www.metabrew.com/article/anti-rdbms-a-list-of-distributed-key-value-stores/">Вы можете выбрать любое другое key/value хранилище, не обязательно хранящее данные в оперативной памяти</a>.<br />
Но весьма вероятно, что в вашем случае <a href="http://www.danga.com/memcached/">memcached</a>/<a href="http://memcachedb.org/">memcachedb</a>/<a href="http://memcachedb.org/memcacheq/">memcacheQ</a> будут лучшим вариантом.</p>
<h6>Вообще была идея сделать многоуровневую кэш-прослойку в которой php искал значение в глобальных переменных, потом в APC, далее в memcached, а лишь потом лезет в базу SELECT&#8217;ом. Но так как проектом занимаемся в свободное от учёбы/работы/семьи время, то до этого пока не дошло.</h6>
<h1>Перевод ключевой части (читай трекера) на C++</h1>
<p>120000 активных пиров создают не мало коннектов к nginx, что ещё хуже, так каждый из них дёргает php, который дёргает мускул. Вам не кажется что ето уж слишком? Нам тоже так показалось. Один из наших разработчиков собрался с силами и переписал код <a href="http://xbtt.sourceforge.net/tracker/">XBTT</a> под фронтенд TorrentPier&#8217;а. Оно того стоило, теперь клиент обращается к трекеру на 2710 порт, который держит в памяти табличку с пирами, там его быстро находит, делает что надо и отдаёт ответ пиру обратно. Раз в минуту скидывает результаты в базу. Всё прекрасно. +100000% производительности.<br />
Вот результаты теста, когда мы поставили время анонса — 1 минута<br />
<code>input (rl0) output<br />
packets errs bytes packets errs bytes colls drops<br />
20K 0 2.5M 16K 0 1.5M 0 0</code><br />
Цена вопроса 100 Метров памяти и 30% загрузка однго проца. Итого получается, что с такой же загрузкой можно держать примерно 8 Миллионов пиров на одной машине при получасовом времени анонса</p>
<p>PID USERNAME THR PRI NICE SIZE RES STATE C TIME WCPU COMMAND<br />
10 root 1 171 52 0K 8K RUN 1 538.6H 47.12% idle: cpu1<br />
6994 root 1 108 0 98140K 96292K CPU0 0 3:57 33.98% xbt_tracker<br />
11 root 1 171 52 0K 8K RUN 0 595.0H 31.20% idle: cpu0<br />
35 root 1 -68 -187 0K 8K WAIT 0 17.1H 21.14% irq21: rl0<br />
12 root 1 -44 -163 0K 8K WAIT 0 482:57 9.96% swi1: net</p>
<p>[root@****] /usr/ports/devel/google-perftools/&gt; netstat -an | wc -l<br />
24147</p>
<h1>Оптимизация сетевого стека FreeBSD, а также её обновление до последней -STABLE</h1>
<p>В последних версиях FreeBSD 6 очень хорошо переработан планировщик 4BSD, а в 7ке так вообще есть такая приятная вещь как <a href="http://people.freebsd.org/~kris/scaling/7.0%20Preview.pdf">ULE, с которой мускул работает в разы шустрее на SMP</a><br />
Также в любой высокопроизводительной инсталяции FreeBSD нужно крутить sysctl, я рекомендую это делать <a href="http://www.opennet.ru/base/net/tune_freebsd.txt.html">по Сысоеву</a></p>
<h1>Оптимизация MySQL</h1>
<p>База данных это то, во что рано или поздно упирается любой проект, мы не исключение.<br />
В то время myisam у нас использовался по двум причинам</p>
<ul>
<li>он используется по-умолчанию</li>
<li>в нём есть FULLTEXT индекс для поиска по форуму</li>
</ul>
<p>Так мы потратили немало времени крутя буферы. Особенно в этом помог <a href="http://www.day32.com/MySQL/">tuning-primer.sh</a><br />
В дальнейшем планируется перевод базы на <a href="http://www.mysqlperformanceblog.com/2008/12/16/announcing-percona-xtradb-storage-engine-a-drop-in-replacement-for-standard-innodb/">Xtradb</a>. В любом случае нам пока хорошо — база влезает в память =)</p>
<h1>Кэширование BB-кодов</h1>
<p>Оказывается phpbb «на лету» преобразовывает bbcod&#8217;ы в html. Не хорошо. Закешировали сгенерированный html код в отдельном поле базы данных для каждого поста/подписи. В итоге база потяжелела почти в 2 раза, зато сайт начал летать.</p>
<h1>Переписка кода на использование SphinxSearch</h1>
<p>Как-то читал презентацию фликера, по поводу того как они у себя делали поиск. Так как база у них на <a href="http://en.wikipedia.org/wiki/InnoDB">innodb</a> они сделали отдельную ферму Master-MultipleSlaves на myisam, чтобы обрабатывать на ней поиски. Что ж, мы не так богаты, сервер у нас только один. Ещё один наш разработчик, взяв волю в кулак, перевёл весь поиск по сайту на сверхбыстрый <a href="http://www.sphinxsearch.com/">SphinxSearch</a>. Результат превзошёл все ожидания. Сервер опять залетал.<br />
Как косвенный эффект это позволило нам ввести просто <strong>супер-мега-удобный rss со встроенным поиском</strong>, который почти не грузит сервер.</p>
<h1>Профайлинг кода и установка средств мониторинга</h1>
<p>Странно, но многие этим ещё не пользуются. А зря. Если не знаешь где находится bottleneck устранить его невозможно. Для этого мы напихали в php код hook&#8217;ов профайлера, а на сервер установили <a href="http://habrahabr.ru/blogs/linux/30494/">munin</a>.</p>
<h1>Разборка запросов из MySQL slow query log</h1>
<p>Тут классика! 20% запросов к базе занимают 80% времени. Приглядитесь может и у вас так. А после разбора логов, подписок FORCE INDEX к запросам и закоментирования нескольких строчек в php загрузка в час пик упала в два раза, а главная страница начала грузится в 10(!!) раз быстрее.<br />
В общем очень рекомендую проводить такую операцию раз-два в год или после введения множества мелких нововведений. Очень помог инструмент <a href="http://hackmysql.com/mysqlsla">mysqlsla</a>.</p>
<h1>Вместо послесловия</h1>
<p>Вот как несколькими шагами мы превратили обычный LAMP в комплексную систему. Сейчас мы живём на обычном Core2Duo 2Ггц с 3Гб оперативки, сейчас ноутбуки в магазинах продаются «покруче», но нам хватает, а загрузка в час пик не поднимается выше 1.5 при 200000 тысячах пиров и ~500 пользователях форума. Интересно каких объёмов потребовался бы парк если бы мы тупо росли горизонтально используя LAMP и репликацию?<br />
Посмотрим как всё изменится когда нам перестанет хватать одного сервера.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.spicesoft.net/blog/2011/03/12/7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

