<?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/online/feed/index.xml" rel="self"></atom:link><lastBuildDate>Mon, 18 Jan 2010 16:43:00 +0300</lastBuildDate><item><title>Архитектура Plenty of Fish</title><link>https://www.insight-it.ru//highload/2010/arkhitektura-plenty-of-fish/</link><description>&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/fa2360fd/" rel="nofollow" target="_blank" title="http://www.plentyoffish.com/"&gt;Plenty of Fish&lt;/a&gt; представляет собой очень
популярный сервис онлайн знакомств, насчитывающий более 45 миллионов
посетителей в месяц и 30+ миллионов просмотров страниц в сутки (что
составляет около 500-600 страниц в секунду). Но это не самая интересная
часть истории... Все это управляется единственным человеком при
использовании нескольких серверов, при этом он тратит на работу всего
пару часов в день и зарабатывает 6 миллионов долларов на рекламе от
Google. Завидуете? Я тоже :) Как же ему удалось соединить столько
влюбленных пар, используя так мало ресурсов?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="istochniki-informatsii"&gt;Источники информации&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Данный пост является переводом &lt;a href="https://www.insight-it.ru/goto/e06f86e0/" rel="nofollow" target="_blank" title="http://highscalability.com/plentyoffish-architecture"&gt;англоязычной
статьи&lt;/a&gt;, автор
оригинала: Todd Hoff.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/35763c73/" rel="nofollow" target="_blank" title="http://channel9.msdn.com/ShowPost.aspx?PostID=331501#331501"&gt;Channel9 интервью с Markus Frind&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/fa591b8c/" rel="nofollow" target="_blank" title="http://plentyoffish.wordpress.com/%20target="&gt;Блог Markus Frind&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/ed31cb93/" rel="nofollow" target="_blank" title="http://www.readwriteweb.com/archives/plentyoffish_one_billion.php"&gt;Plentyoffish: компания одного человека может стоить 1 миллиард
долларов&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="platforma"&gt;Платформа&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft Windows&lt;/li&gt;
&lt;li&gt;ASP.NET&lt;/li&gt;
&lt;li&gt;IIS&lt;/li&gt;
&lt;li&gt;Akamai CDN&lt;/li&gt;
&lt;li&gt;Foundry ServerIron Load Balancer&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="statistika"&gt;Статистика&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PlentyOfFish (POF) имеет 1.2 миллиарда просмотров страниц в месяц, в
среднем 500 тысяч уникальных авторизованных пользователей в день.
Пиковый сезон приходится на январь каждого года, когда эти цифры
возрастают на 30%.&lt;/li&gt;
&lt;li&gt;POF имеет единственного сотрудника: создатель и генеральный директор
Markus Frind.&lt;/li&gt;
&lt;li&gt;Зарабатывает до 10 миллионов долларов в год на рекламе от Google,
работает при этом только около двух часов в день.&lt;/li&gt;
&lt;li&gt;30+ миллионов просмотров страниц в день (500 - 600 страниц в секунду).&lt;/li&gt;
&lt;li&gt;1.2 миллиарда просмотров страниц и 45 миллионов посетителей в месяц.&lt;/li&gt;
&lt;li&gt;Имеет &lt;a href="https://www.insight-it.ru/goto/ca40875e/" rel="nofollow" target="_blank" title="http://ru.wikipedia.org/wiki/CTR_(%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%BD%D0%B5%D1%82)"&gt;CTR&lt;/a&gt; в 5-10 раз выше, чем Facebook.&lt;/li&gt;
&lt;li&gt;Находится в top 30 сайтов США по данным Competes Attention, top 10 в Канаде и top 30 в Великобритании.&lt;/li&gt;
&lt;li&gt;Нагрузка балансируется между двумя веб-серверами с 2 Quad Core Intel
Xeon X5355 @ 2.66Ghz, 8GB RAM (используется около 800 MB), 2 жесткими
дисками, работают под управлением Windows x64 Server 2003.&lt;/li&gt;
&lt;li&gt;3 сервера баз данных. Информация об их конфигурации не предоставляется.&lt;/li&gt;
&lt;li&gt;Приближается к 64000 одновременных соединений и 2 миллионам просмотрам
страниц в час.&lt;/li&gt;
&lt;li&gt;Интернет-канал в 1Gbps, из которых используется только 200Mbps.&lt;/li&gt;
&lt;li&gt;1 TB трафика от отдачи 171 миллионов изображений через Akamai.&lt;/li&gt;
&lt;li&gt;6TB система хранения данных для обработки миллионов полноразмерных
изображений, которые загружаются на сайт каждый месяц.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="chto-vnutri"&gt;Что внутри?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Модель монетизации заключалась в использовании рекламы от Google.
Match.com, для сравнения, получает 300 миллионов долларов в год, в
основном с платных подписок. Источник дохода POF должен измениться,
чтобы позволить ему получать больше выручки от имеющихся пользователей.
Планируется нанять больше сотрудников, в частности людей, которые будут
заниматься продажей рекламы напрямую вместо того, чтобы полностью
полагаться на AdSense.&lt;/li&gt;
&lt;li&gt;При 30 миллионах просмотрах страниц в день можно зарабатывать неплохие
деньги на рекламе, даже
если&amp;nbsp;&lt;a href="https://www.insight-it.ru/goto/b1c7d720/" rel="nofollow" target="_blank" title="http://en.wikipedia.org/wiki/Cost_per_mille"&gt;CPM&lt;/a&gt; будет всего 5-10
центов.&lt;/li&gt;
&lt;li&gt;Akamai используется для отдачи более 100 миллионов изображений в день.
Если на странице 8 изображений и каждое загружается за 100 миллисекунд -
их загрузка займет почти секунду, так что распределение изображений
целесообразно.&lt;/li&gt;
&lt;li&gt;Десятки миллионов изображений отдаются с серверов POF, но большинство из
них размером меньше 2KB и практически полностью закешированы в
оперативной памяти.&lt;/li&gt;
&lt;li&gt;Все динамично. Практически никакой статики.&lt;/li&gt;
&lt;li&gt;Все исходящие данные сжимаются с использованием Gzip, что обходится
всего 30% использованием процессорного времени. Используется много
вычислительных ресурсов, но зато существенно сокращается использование
пропускной способности интернет-канала.&lt;/li&gt;
&lt;li&gt;Кэширование ASP .NET не используется, так как данные теряют свою
актуальность практически сразу же.&lt;/li&gt;
&lt;li&gt;Встроенные компоненты ASP также не используется. Почти все написано с
чистого листа. Ничего не может быть более сложным, чем кучка простых
if-then-else и циклов. Все максимально элементарно.&lt;/li&gt;
&lt;li&gt;Балансировка нагрузки:&lt;/li&gt;
&lt;li&gt;IIS произвольно ограничивает общее количество соединений до 64000,
таким образом балансировщик нагрузки был добавлен для обработки большего
количества одновременных соединений. Вариант с добавлением второго IP
адреса и использованием round robin DNS также рассматривался, но вариант
с балансировщиком нагрузки выглядел более избыточным и позволял более
легко расширять количество серверов. Помимо этого ServerIron позволял
использовать более продвинутую функциональность, вроде блокировки ботов
и балансировку запросов по cookies, сессиям или IP-адресам
пользователей.&lt;/li&gt;
&lt;li&gt;Windows Network Load Balancing (NLB) функция не использовалась, так
как не поддерживает привязку сессий к серверам. Обходным путем было бы
хранение сессионных данных в базе данных или общей файловой системе.&lt;/li&gt;
&lt;li&gt;8-12 NLB серверов могут объединяться в кластер и может использоваться
неограниченное количество таких кластеров. Схема DNS round robin может
использоваться для распределения запросов между кластерами. Теоретически
такая архитектура могла бы позволить 70 веб-серверам обрабатывать более&amp;nbsp;300 тысяч одновременных соединений.&lt;/li&gt;
&lt;li&gt;NLB имеет опцию для отправки каждого пользователя на конкретный
сервер, таким образом не используется внешнее хранилище для сессионных
данных и если сервер выходит из строя - пользователи просто
разлогиниваются из системы. Если это состояние включает в себя например
корзину интернет-магазина или какую-то другую важную информацию, то
такой подход мог бы показаться&amp;nbsp;неприемлемым, но для сайта знакомств это
было бы не так критично.&lt;/li&gt;
&lt;li&gt;Было решено, что хранение и получение сессионных данных программными
средствами слишком дорого. Аппаратная балансировка нагрузка проще:
пользователи просто назначаются конкретным серверам и в случае сбоя
сервера назначенным ему пользователям предлагается пройти процесс
авторизации еще раз.&lt;/li&gt;
&lt;li&gt;Покупка ServerIron была дешевле и проще, чем использование NLB.
Многие крупные сайты используют их для создания пулов TCP соединений,
автоматическому определению ботов и так далее. ServerIron может делать
намного больше, чем просто балансировать нагрузку и такие функции
достаточно привлекательные за эту цену.&lt;/li&gt;
&lt;li&gt;Была большая проблема с выбором системы размещения рекламы. Многие из
них хотели несколько сотен тысяч в год и многолетний контракт.&lt;/li&gt;
&lt;li&gt;В процессе избавления от ASP.NET повторителей и использование взамен
конкатенации строк или response.write. Если у вас миллионы просмотров
страниц в день - просто напишите весь код для отображения на экране
пользователя.&lt;/li&gt;
&lt;li&gt;Большинство изначальных вложений ушло на построение SAN. Избыточность
любой ценой.&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;Производительность наблюдается через диспетчер задач. Когда
появляются пики - ситуация рассматривается более детально. Проблемы
обычно заключались в блокировках на уровне СУБД. Собственно говоря почти
всегда это были проблемы с базами данных, очень редко они возникают на
уровне .NET. Так как POF не использует библиотеки .NET, отследить
проблемы с производительностью оказывается достаточно просто. Если бы
использовалось много уровней framework'ов, поиск мест, где скрываются
проблемы, был бы трудным и утомляющим.&lt;/li&gt;
&lt;li&gt;Если Вы делаете запрос к базе данных 20 раз при отображении одной
страницы, &amp;nbsp;Вы проиграли в любом случае, вне зависимости от того, что Вы
будете делать.&lt;/li&gt;
&lt;li&gt;Разделяйте запросы чтения и записи к базе данных. Если у вас нет
избыточного количества оперативной памяти не следование этому правилу
может заставить систему зависнуть на несколько секунд.&lt;/li&gt;
&lt;li&gt;Постарайтесь делать базы данных только для чтения.&lt;/li&gt;
&lt;li&gt;Денормализуйте данные. Если Вам приходится доставать данные из 20
разных таблиц, попробуйте сделать просто одну таблицу, где будут лежать
все нужные для чтения данные.&lt;/li&gt;
&lt;li&gt;Один день может проработать почти что угодно, но когда Ваша база
данных удвоится - использованные подход может внезапно перестать
работать.&lt;/li&gt;
&lt;li&gt;Если система делает только что-то одно, она будет делать это реально
хорошо. Только записывайте данные и все будет нормально. Только читайте
данные и все будет нормально. Делайте и то и другое - и все испортится.
База данных погрязнет в проблемах с блокировками.&lt;/li&gt;
&lt;li&gt;Если Вы полностью используете вычислительные мощности, Вы либо
делаете что-то не так, либо Ваша система на самом деле очень
оптимизирована. Если вы можете разместить всю базу в оперативной
памяти - обязательно делайте это.&lt;/li&gt;
&lt;li&gt;Процесс разработки выглядит примерно следующим образом: появляется идея,
быстро реализуется и выдается пользователям в пределах 24 часов. Отклик
от пользователей получается по слежению за тем, что они делают на сайте:
выросло количество сообщений на пользователя? среднее время сессий
выросло? Если пользователям новая фишка не пришлась по вкусу - просто
уберите её.&lt;/li&gt;
&lt;li&gt;При небольшом количестве серверов системные сбои достаточно редки и
краткосрочны. Наибольшими сложностями были проблемы с DNS, когда
некоторые интернет-провайдеры говорили, что POF больше не существует. Но
так как сайт бесплатен, пользователи нормально относятся к небольшим
периодам его недоступности. Люди часто не замечают простой сайта, так
как думают, что это какая-то проблема у них, с интернет-соединением или
еще чем-то.&lt;/li&gt;
&lt;li&gt;Переход от миллиона пользователей к 12 миллионам пользователей был
большим прыжком. Система может обслуживать и 60 миллионов пользователей
с двумя веб-серверами.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Часто смотрите на конкурентов для идей новых функциональных
возможностей.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Рассмотрите использование чего-то вроде S3, когда система начнет
требовать географической балансировки.&lt;/p&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;li&gt;В начале старайтесь держать все максимально простым. Практически все
дают этот же самый совет, а Markus говорит, что все что он делает -
всего лишь очевидный здравый смысл. Но то что просто, не всегда означает
всего лишь осмысленную вещь. Создание простых вещей является результатом
многих лет практического опыта.&lt;/li&gt;
&lt;li&gt;Поддерживайте время доступа к базе данных быстрым и у Вас не будет
проблем.&lt;/li&gt;
&lt;li&gt;Одной из основных причин, по которой POF может работать с таким
небольшим количеством сотрудников и оборудования, является использование
CDN для отдачи активно используемого контента. Использование CDN может
оказаться секретным соусом для многих крупных сайтов. Markus считает,
что в top 100 не существует ни одного сайта, не использующего CDN. Без
CDN время загрузки страницы в Австралии возросло бы до 3-4 секунд только
за счет изображений.&lt;/li&gt;
&lt;li&gt;Реклама на Facebook принесла плохие результаты. Из 2000 кликов только 1
человек регистрировался. С CTR равным 0.04% Facebook выдавал 0.4 клика
на 1000 показов рекламы (CPM). При 5 центах CPM = 12.5 центов за клик,
50 центах CPM = 1.25\$ за клик. 1 доллар CPM = 2.50\$ за клик. 15\$ CPM
= 37.50\$ за клик.&lt;/li&gt;
&lt;li&gt;Это просто продавать несколько миллионов просмотров страниц с высоким
CPM, но НАМНОГО сложнее продавать миллиарды просмотров с высоким CPM,
как это делают Myspace и Facebook.&lt;/li&gt;
&lt;li&gt;Модель монетизации, основанная на рекламе, ограничивает Ваши доходы. Вам
придется переходить к платной модели чтобы повышать прибыль.
Генерировать 100 миллионов долларов в год за счет бесплатного сайта
практически невозможно - Вам потребуется слишком большой рынок.&lt;/li&gt;
&lt;li&gt;Повышение количества просмотров за счет Facebook не работает для сайтов
знакомств. Иметь посетителя на собственном сайте намного более
прибыльно. Большинство просмотров страниц на Facebook находятся за
пределами США и Вам придется делить 5 центов CPM с Facebook.&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>Mon, 18 Jan 2010 16:43:00 +0300</pubDate><guid>tag:www.insight-it.ru,2010-01-18:highload/2010/arkhitektura-plenty-of-fish/</guid><category>Akamai CDN</category><category>ASP</category><category>ASP .NET</category><category>dating</category><category>Foundry</category><category>IIS</category><category>Microsoft</category><category>online</category><category>Plenty of Fish</category><category>POF</category><category>ServerIron</category><category>Windows</category><category>Windows Server</category><category>архитектура</category><category>Архитектура Plenty of Fish</category><category>Масштабируемость</category><category>сайт знакомств</category></item><item><title>Aladdin от Baidu</title><link>https://www.insight-it.ru//highload/2010/aladdin-ot-baidu/</link><description>&lt;p&gt;Наверняка все прекрасно знают о лидерах интернет-поиска в российской
части интернета: про Google, Яндекс или Рамблер сказано уже не мало
слов, все много раз о них читали, пользовались, обсуждали - ведь уже
прошло больше 10 лет с момента создания каждой из этих поисковых систем
и, как следствие, их конкуренции на просторах рунета. Намного меньше же
внимания на российских информационных сайтах уделяется национальным
проектам других стран, а ведь среди них тоже есть заслуживающие внимания
экземпляры, об одном из них я бы и хотел сегодня поведать.
&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="istochniki-dannykh"&gt;Источники данных&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/7e247449/" rel="nofollow" target="_blank" title="http://tech.sina.com.cn/i/2009-12-16/14423683386.shtml"&gt;Baidu Aladdin Technology Guashudila&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/9d98f3c7/" rel="nofollow" target="_blank" title="http://tech.sina.com.cn/i/2009-08-18/16063362415.shtml"&gt;Rachel Liao, лекция директора по архитектуре Baidu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/d1f8deb1/" rel="nofollow" target="_blank" title="http://news.xinhuanet.com/it/2006-04/06/content_4390847.htm"&gt;Baidu Chief Architect: алгоритмы на службе разработчиков Baidu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/cc13f208/" rel="nofollow" target="_blank" title="http://baike.baidu.com/view/2086291.htm"&gt;Aladdin Plans&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Если кто-то достаточно любопытен, чтобы нажать на приведенные ссылки -
они все на китайском, так что статья написана на основе перевода Google
Translate со всеми вытекающими последствиями. Даже за название "Aladdin"
не ручаюсь, его тоже он придумал :)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="o-kompanii-baidu"&gt;О компании Baidu&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/50a1d1a7/" rel="nofollow" target="_blank" title="http://www.baidu.com"&gt;Baidu.com&lt;/a&gt; является лидером китайского рынка
интернет-поиска, объем которого достаточно значителен. На данный момент
Китай насчитывает около 340-360 миллионов интернет-пользователей, что
превышает общую численность населения США. Не трудно представить с каким
трафиком приходится сталкиваться крупнейшей китайской поисковой системе.&lt;/p&gt;
&lt;p&gt;Чтобы не быть голословным, еще немного цифр о Baidu:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;100 миллионов поисковых запросов в день&lt;/li&gt;
&lt;li&gt;Более миллиарда проиндексированных страниц&lt;/li&gt;
&lt;li&gt;300-400 миллионов проиндексированных сайтов&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Уже на сегодняшний день размеры китайской части интернета производят
впечатление и с каждым днем она расширяется все больше. Как следствие,
на рынке образуются все новые и новые возможности для создания сервисов,
удовлетворяющих потребности китайских пользователей Интернет.
Компания&amp;nbsp;&lt;strong&gt;Baidu Inc.&lt;/strong&gt; пристально наблюдает за развитием ситуации и
обнаружила огромную потребность среди сервис-провайдеров в удобной
платформе для создания и предоставления пользователям новых сервисов.
Baidu считает создание платформы для использования их технологии
сторонними разработчиками и сервис-провайдерами очень важным
направлением развития на пути к повышению качества пользовательского
опыта в целом. Эти наблюдения стали толчком к рождению в рамках Baidu
новой технологии под названием&amp;nbsp;&lt;a href="https://www.insight-it.ru/goto/e0a5512c/" rel="nofollow" target="_blank" title="http://open.baidu.com/"&gt;Aladdin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Как крупнейшей китайской поисковой системе, Baidu приходится быть чем-то
большим, чем просто инструментом для поиска, это позволяет удовлетворять
потребности потенциальных клиентов наиболее гармоничным и целесообразным
образом. Помимо неустанной погони за технологическими инновациями, Baidu
предпочитает придерживаться политики "потребности клиентов важнее
всего".&lt;/p&gt;
&lt;h2 id="aladdin"&gt;Aladdin&lt;/h2&gt;
&lt;p&gt;Согласно официальному сайту Baidu, эта технология представляет собой
открытую поисковую платформу, позволяющую сторонним разработчикам
использовать технологию Baidu в своих приложениях и сервисах. Владельцы
интернет-проектов и разработчики могут предоставить Baidu данные в уже
структурированном виде для того, чтобы создать еще более мощные и
функционально-насыщенные приложения, позволяя интернет-сайтам получать
еще более значимый трафик, а пользователям - еще больше облегчить
использование сайтов и поиск в сети Интернет.&lt;/p&gt;
&lt;p&gt;В декабре 2008 года Baidu объявили о высокоприоритетной программе под
кодовым названием&amp;nbsp;&lt;em&gt;"Aladdin"&lt;/em&gt;, основной идеей была попытка расширить
текущие рамки веб-поиска, по большей части за счет включения так
называемого "глубинного интернета" в поисковую базу, проведения более
глубокого анализа контента. Помимо этого упоминались возможность
интеграции и управляемой обработки информации, направленных на
минимизацию издержек поиска и времени обработки запроса при повышение
общего качества поисковых результатов. В том же заявлении Baidu также
описали их общую позицию по данному направлению: платформа Aladdin
является надстройкой над текущей поисковой системой Baidu, позволяющей
дополнение и расширение функциональных возможностей.&lt;/p&gt;
&lt;p&gt;Согласно исследованиям Baidu, только 75% пользователей поисковых систем
в конечном итоге удовлетворяют свои информационные потребности. В
процессе анализа причин данного факта было выявлено, что в большом
количестве случаев искомая информация находится на ресурсах по каким-то
причинам находящимся вне доступа поисковых систем (начиная от
технических ограничений, отсутствия внешних ссылок на ресурс и
заканчивая искусственными&amp;nbsp;барьерами вроде REP или принудительной
авторизации).&lt;/p&gt;
&lt;p&gt;Перед разработчиками Aladdin встают две основные проблемы с точки зрения
технической реализации: "как определить пользовательские потребности" и
"как сортировать". Конечно же они очень тесно связаны между собой, это
хорошо демонстрирует пример с поисковым запросом "полное солнечное
затмение": до затмения пользователи хотят когда оно будет и откуда лучше
смотреть, а во время и после него намного актуальнее будет увидеть
видео-запись или прямую трансляцию, а также прочитать и поделиться
комментариями. Самым простым методом решения данного класса задач
является статистический анализ - Aladdin выделяет два основных фактора,
используемых для сортировки результатом в соответствии с потребностями
пользователей: "удовлетворенность потребностей" и "уровень отклика на
спрос". Конечно же оценочные характеристики спроса и потребностей не
означают сам спрос, то есть возможны и более сложные ситуации, когда за
пользовательским запросом стоит целый комплекс более простых
потребностей.&lt;/p&gt;
&lt;p&gt;Алгоритмы, используемые в Aladdin для решения упомянутых проблем,
основаны на машинном обучении, анализе поведения пользователей, а также
обратной связи от использования технологии на практике. Конечная цель
данной платформы заключается в построении целой интеллектуальной
экосистемы, &amp;nbsp;которая станет новым шагом в развитии компании Baidu и
китайской части интернета в целом.&lt;/p&gt;
&lt;h3 id="vozmozhnosti-platformy"&gt;Возможности платформы&lt;/h3&gt;
&lt;p&gt;С технической точки зрения Aladdin от Baidu представляет собой открытый
API к поисковой технологии Baidu, позволяющий добавлять свои данные в
структурированном виде в поисковый индекс, отмечать релевантные ключевые
слова, методы отображения информации и пометки данных гео-метками.&lt;/p&gt;
&lt;p&gt;Одним из важнейших направлений развития поисковых систем является
повышение "интеллектуальности" поиска, Baidu уделяет внимание не только
обнаружению более ценной информации в глубинах Интернета, но и
предоставлению более удобных, точных и сообразительных поисковых
сервисов.&lt;/p&gt;
&lt;p&gt;На сегодняшний день, технология Aladdin была интегрирована в ряд
приложений, позволив тем самым реализовать на страницах с результатами
поиска&amp;nbsp;множество интересных возможностей: прямой звонок клиенту для
обсуждения каких-то товаров или услуг, интеграция с почтовым сервисом,
прослушивание музыки с использованием встроенного flash-плеера и многие
другие.&lt;/p&gt;
&lt;p&gt;После обязательной процедуры подачи и рассмотрения заявки пользователям
платформы Aladdin предоставляются следующие возможности:&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;На первый взгляд все эти рассуждения и заявления о функциональных
возможностях кажутся абсурдными, даже отчасти ироничными. Ну кому может
понадобиться вручную управлять результатами поиска, добавлять и
структурировать данные, возиться с сортировкой и внешним видом?&lt;/p&gt;
&lt;h3 id="vzgliad-s-drugoi-storony"&gt;Взгляд с другой стороны&lt;/h3&gt;
&lt;p&gt;Да, вся платформа Aladdin по своей задумке очень искуственна:
практически все делается вручную, но по сути это лишь процесс
интеграции, а не работа с самим контентом. Для большинства других
поисковых систем такой подход неприемлем: где найти столько людей, чтобы
управлять огромными массивами данных вручную? Наоборот все поисковые
системы стремятся по максимуму все автоматизировать и борятся с
искуственным вмешательством в поисковый индекс (т.н. SEO), но... если
вспомнить, что Baidu работает в Китае - вся затея начинает обретать
здравый смысл. Как сама компания Baidu, так и большинство их
потенциальных партнеров, клиентов и пользователей находится в примерно
одинаковой ситуации: большое количество дешевой рабочей силы,
относительно низкий уровень образования и профессиональной подготовки, а
также прочие национальные особенности. В их ситуации не выгодно идти по
пути Google и делать&amp;nbsp;&lt;em&gt;основной&lt;/em&gt; акцент на построении полностью
автоматизированных систем анализа контента, добавления дополнительного
материала к поисковым результатам и самим делать различные
дополнительные приложения и сервисы. Намного выгоднее пойти по
собственному пути, более адаптированному к ситуации в Китае, большое
количество трудолюбивых людей позволяет строить сервисы коллективно, с
привлечением партнеров, клиентов и заинтересованных лиц. Да, во многом
вручную, за счет интеграции совершенно различных систем и сервисов, но
зато более качественно и продуманно. В этом-то и заключается вся магия
Китая.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 14 Jan 2010 00:01:00 +0300</pubDate><guid>tag:www.insight-it.ru,2010-01-14:highload/2010/aladdin-ot-baidu/</guid><category>Aladdin</category><category>Baidu.com</category><category>online</category><category>Масштабируемость</category><category>поиск</category><category>поисковые системы</category></item><item><title>Нам два годика</title><link>https://www.insight-it.ru//misc/2010/nam-dva-godika/</link><description>&lt;p&gt;В общем судя по всему я решил считать 3 января 2008 года Днем
Рождения&amp;nbsp;&lt;strong class="trebuchet"&gt;Insight IT&lt;/strong&gt;, так что как раз самое время написать очередной
бестолковый "праздничный" пост, по совместительству выполняющий роль
"новогоднего" (надо же поздравить всех читателей с Наступившим, хоть и
несколько поздновато; отметил я просто замечательно и три дня провел без
интернета). В повестке дня у нас сегодня обзор основных событий
прошедшего года и планы на наступивший, кому интересно - читаем дальше
;)&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Как не сложно увидеть по датам постов - первые 10 месяцев года прошли очень
пассивно для данного блога. Я был весь в работе и учебе, постов писал
мало, на комментарии отвечал редко - в общем халтурил по полной
программе. Впрочем время для меня зря не прошло - успел получить степень
бакалавра Бизнес-Информатики и поступить в магистратуру на программу
"Электронный бизнес". В дополнение к общему затишью ложку дегтя добавлял
теперь уже бывший хостинг провайдер (по прежнему не хочу устраивать
анти-рекламу, российская компания с доменом из двух букв, кому было
интересно уже наверное давно успели посмотреть) - возможно кто-то из
читателей помнит эти регулярные проблемы с доступностью сайта, некоторые
из которых даже доходили до простоев более двух недель подряд.&lt;/p&gt;
&lt;p&gt;На этом в общем-то негативные стороны заканчиваются, так что перейдем к
положительным моментам. Во-первых, блог переехал-таки на новый хостинг в
США: там существенно более ответственно относятся к клиентам, отличная
техподдержка, пока никаких сбоев, современное оборудование, никаких
фиксированных ограничений по трафику/дисковому
пространству/процессорному времени/чему-то еще в этом духе - в целом
пока вижу в данном решении почти только плюсы, из минусов разве что чуть
больший пинг и цена на 500р./год выше. Во-вторых, в октябре я остался
без работы - про это я уже рассказывал достаточно подробно, повторяться
не буду. В общем у меня стало появляться существенно больше свободного
времени, которое я мог позволить себе тратить на блог. Не трудно
заметить возросшую активность как в постах, так и в комментариях,
циферки в статистике &lt;em&gt;Google Analytics&lt;/em&gt;, &lt;em&gt;Feedburner&lt;/em&gt; и &lt;em&gt;Wordpress.com
Stats&lt;/em&gt; достаточно резво растут вверх и я надеюсь, что эта тенденция
продолжится и на протяжении всего наступившего года. Уже накопилась
масса идей для новых постов - осталось только найти в себе силы
материализовать их.&lt;/p&gt;
&lt;p&gt;Вообще я уже почти три месяца сижу без работы и почему-то чем дальше -
тем менее активно ищу новую. Некоторое время назад, примерно
одновременно с принятием решения о смене хостинга, мне пришла в голову
идея попробовать зарабатывать на&amp;nbsp;&lt;strong class="trebuchet"&gt;Insight IT&lt;/strong&gt;, чтобы позволить себе оттягивать&amp;nbsp;&lt;a href="https://www.insight-it.ru/resume/"&gt;процесс поиска работы&lt;/a&gt; как можно дальше. Сначала попробовал наиболее "гуманный" по отношению к читателям метод, который более-менее сносно работал в 2008 году - поставил побольше блоков &lt;em&gt;Google AdSense&lt;/em&gt;. Оказалось больше не работает, цены за клик упали в 3-5 раз, да и CTR ниже плинтуса. Этот факт подтолкнул меня создать появившуюся в меню навигации несколько дней назад страничку&amp;nbsp;&lt;a href="https://www.insight-it.ru/contact/"&gt;&lt;em&gt;"Реклама"&lt;/em&gt;&lt;/a&gt; (возможно кто-то уже успел ознакомиться), основная идея - я готов размещать ту или иную форму рекламы напрямую, без посредников в виде бирж или каких-то других автоматизированных систем. Очень надеюсь, что кто-то заинтересуется и откликнется, иначе у меня останется только очень не нравящийся мне самому вариант со всяким бредом из области SEO: вроде продажи ссылок на биржах, размещении чужих статей и тому подобного... Либо вообще отказываться от затеи с монетизацией блога и возвращаться к поиском "офисной" работы, но вообще мне очень не хотелось бы снова
забрасывать&amp;nbsp;&lt;strong class="trebuchet"&gt;Insight IT&lt;/strong&gt;, одно из самых любимых хобби как-никак.&lt;/p&gt;
&lt;p&gt;Основные темы блога мне по-прежнему очень интересны: как информационные
технологии в целом, так и&amp;nbsp;&lt;a href="https://www.insight-it.ru/highload/"&gt;архитектуры высоконагруженных систем&lt;/a&gt; в частности. Мне наверное еще предстоит&amp;nbsp;поэкспериментировать&amp;nbsp;с различными форматами изложения информации, более узкими темами и вопросами, чтобы подстроиться под наверняка изменившиеся за прошедший год интересы аудитории блога, я по прежнему рад комментариям, &lt;a href="https://www.insight-it.ru/contact/"&gt;письмам&lt;/a&gt; и другим видам обратной связи. По старинке хочется порекомендовать всем, кто этого еще не сделал,&amp;nbsp;&lt;a href="/feed/"&gt;&lt;em&gt;подписаться на RSS&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;До новых встреч!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sun, 03 Jan 2010 23:59:00 +0300</pubDate><guid>tag:www.insight-it.ru,2010-01-03:misc/2010/nam-dva-godika/</guid><category>online</category><category>WordPress</category><category>День Рождения</category><category>ДР</category><category>интернет</category><category>итоги года</category></item><item><title>Новый Google: интернет-гигант проливает свет на темы поиска в реальном времени, локального поиска, облачных вычислений и освобождения данных</title><link>https://www.insight-it.ru//theory/2009/novyjj-google-internet-gigant-prolivaet-svet-na-temy-poiska-v-realnom-vremeni-lokalnogo-poiska-oblachnykh-vychislenijj-i-osvobozhdeniya-dannykh/</link><description>&lt;p&gt;Когда речь заходит о продуктовых и бизнес стратегиях, &lt;a href="/tag/google/"&gt;Google&lt;/a&gt; обычно становится одной из самых скрытных и секретных компаний. Но не смотря на это, интернет-гигант некоторое время назад согласился дать серию интервью, в основном с участием высшего продуктового менеджмента, работающего в штабквартире в Mountain View, CA.&lt;/p&gt;
&lt;p&gt;В четырех отдельных интервью, сотрудники Google окунулись в самые
насущные темы, наиболее актуальные для компании в целом. Среди них
оказались различные вопросы, начиная с поиска в реальном времени,
локального поиска, и заканчивая облачными вычислениями, а также так
называемой возможностью освобождения данных. Под освобождением данных
имеется ввиду комплекс мер, направленных на предоставлении пользователям
возможности экспортировать их файлы и другую цифровую информацию из
продуктов Google (если они сами этого захотят, конечно же).&lt;/p&gt;
&lt;p&gt;Достаточно любопытный факт: менеджеры Google реально очень скучные. И им
правда нравится выглядеть именно так (по крайней мере пока их PR-коллеги
находятся рядом). Они не разговаривают о конкурентах. Они не делают
прогнозов о развитии индустрии. И они не говорят конкретно кто над чем
работает внутри Google. Просто-напросто они фокусируются на
совершенствовании своих продуктов, особенно в направлении удобства
использования пользователями, разве этого не достаточно?&lt;/p&gt;
&lt;p&gt;Возможно Jack Menzel, старший продукт-менеджер, лучше всего это выразил,
когда пошутил о "неблагодарности" работы над веб-поиском в Google: "Вы
демонстрируете [новую функцию поиска] людям, а они говорят: 'Да, вроде
она работает, ну и что?'" (Как быстро все мы забываем, каково это было
искать информацию в Интернете всего несколько лет назад.) Что ж, без
дальнейших предисловий, перейдем к основным моментам, связанным с
различными аспектами работы Google.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;&lt;em&gt;По мотивам &lt;a href="https://www.insight-it.ru/goto/c19fec69/" rel="nofollow" target="_blank" title="http://www.xconomy.com/national/2009/12/21/the-new-google-internet-giant-opens-up-about-real-time-and-local-search-cloud-computing-and-data-liberation/?single_page=true"&gt;статьи на xconomy.com&lt;/a&gt;,
автор&amp;nbsp;&lt;a href="https://www.insight-it.ru/goto/1e1524b7/" rel="nofollow" target="_blank" title="Posts by Gregory T. Huang"&gt;Gregory T. Huang&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="poisk-v-realnom-vremeni"&gt;Поиск в реальном времени&lt;/h2&gt;
&lt;p&gt;Google активно работает над максимально оперативным обновлением
результатов поиска по сети Интернет, в том числе и по социальным медиа
вроде &lt;a href="/tag/twitter/"&gt;Twitter&lt;/a&gt; или &lt;a href="/tag/facebook/"&gt;Facebook&lt;/a&gt;, практически так же быстро, как такая информация и публикуется.&lt;/p&gt;
&lt;p&gt;Menzel, бывший сотрудник Microsoft, который изучал компьютерное ремесло
в University of Washington, возглавляет продуктовую группу на данном
фронте. Он говорит, что компания Google работала над ускорением процесса
индексации и ранжирования на протяжении уже многих лет: когда-то данные
обновлялись раз в месяц, потом обновление стало ежедневным, чтобы
поспевать за блогами и новостными сайтами. В течении прошлого года
&lt;a href="/tag/twitter/"&gt;Twitter&lt;/a&gt; стал популярен и, как следствие, появилась
достаточно критичная потребность в обновлении информации за считанные
секунды или в крайнем случае минуты. "Мы двигались по направлению к
тому, чтобы становиться все быстрее и быстрее, на протяжении уже
достаточно длительного периода времени", говорит Menzel. "Данная
траектория развития была выбрана уже давно. Каждый шаг в данном
направлении приводит к все новым и новым проблемам и трудностям. Мы
верим, что именно получение доступа к свежей информации является одним
из ключевых факторов, являющихся залогом успеха Google." (В число
остальных факторов, относящихся к самому поиску, входят такие показатели
как релевантность, быстрота получения результата и полнота контента.)&lt;/p&gt;
&lt;p&gt;Menzel считает, что самой сложной задачей является не просто
быстродействие, а релевантность результатов потребностям пользователей
(возможно, кто-то привык называть этот показатель словом
&lt;em&gt;"пертинентность"&lt;/em&gt;). "Это очень, очень непросто собирать свежий
короткоживущий контент и ранжировать его рядом с, скажем, статьями из
New York Times или просто постами из блогов." Стоит заметить, что когда
контент появился буквально только что, обычно на него еще практически
никто не успел сослаться, а значит Google не может полноценно
использовать PageRank, их классическую технологию.&lt;/p&gt;
&lt;p&gt;Вместо этого, они "тяжело опираются на все то, что они выявили в течении
последних 10 лет", говорит Menzel. Это включает в себя, например,
способы отбрасывания контента, который скорее всего является
иррелевантным или спамом, в более общем случае. Помимо этого он
упоминал "совершенно новые сигналы", скажем "новые языковые модели",
которые позволяют понять какие обновления являются релевантными, а
какие - просто горстка никому не нужных данных от какого-нибудь
ученого-океанографа, или методы определения насколько тот или иной
создатель контента авторитетен в своей области.&lt;/p&gt;
&lt;p&gt;Говоря о будущем, Menzel повторил то, что казалось бы на сегодняшний
день говорят все о поиске: еще рано. "На самом деле мы лишь начали
работать над данной задачей и у нас все еще очень долгий путь впереди".
Он надеется, что в течении 5 лет Google сделает поиск намного более
персонализированным, чем он есть сегодня. Например, Google будет знать
что ты увлекаешься футболом, но привык называть его не "soccer", а
"football", то есть помимо прочего поисковая система должна понимать кем
является каждый ее конкретный пользователь, как и с кем он связан, кем
он является в реальной жизни, где находится, и, тем самым, помогать ему
организовывать всю информацию вокруг него.&lt;/p&gt;
&lt;p&gt;"Поиск - все еще очень далекая от решения проблема," - говорит Menzel.
"Существует еще масса вещей, которые очень не просто найти в
Интернете."&lt;/p&gt;
&lt;h2 id="lokalnyi-poisk"&gt;Локальный поиск&lt;/h2&gt;
&lt;p&gt;В эту категорию попадают все виды поисковых запросов, так или иначе
связанных с географической информацией, скажем "отели в Гонг-Конге" или
"рестораны в Сиэттле", а также запросы с мобильных устройств на поиск
близлежащих мест, заведений, достопримечательностей и прочих объектов.&lt;/p&gt;
&lt;p&gt;Carter Maslan, директор продуктового менеджмента в области локального
поиска в Google, называет эту область "организацией мировой информации
географически" , или созданием быстрого и простого гида по
"гео-Интернету". Самым сложным моментом в данном вопросе по его мнению
является&amp;nbsp;отображение&amp;nbsp;всех этих различных способов выражения
пользовательского запроса на очень большой массив локализированных
данных, а также возвращение правильного ответа на полученный запрос в
минимальные сроки.&lt;/p&gt;
&lt;p&gt;Maslan, еще один экс-сотрудник Microsoft, говорит, что Google
обрабатывает большое количество поисковых запросов для анализа того, как
люди предпочитают искать локальную информацию, и как с географической
точки зрения создаются ссылки на различные вещи. По его мнению конечная
цель заключается в том, чтобы сделать поиск и обнаружение мест рядом с
собой практически не требующим от пользователя каких-либо усилий.
Наиболее знакомые сценарии, это помощь в ориентировании в новом
окружении, скажем после приземления в аэропорту, или поиск баров во
время ночной прогулки по пригородам Нью-Йорка.&lt;/p&gt;
&lt;p&gt;Складывается впечатление, что все это должно плотно вписываться в более
широкую&amp;nbsp;стратегию&amp;nbsp;Google, связанную с мобильными технологиями. "Ваш
телефон знает многое" - говорит Maslan. "Он знает где Вы сейчас
находитесь, он может определить в каком направлении Вы направляетесь.
Все не ограничивается только текстом в окошке для поискового запроса. Мы
хотим вывести мобильную информацию на передний план." Существующим на
данный момент примером является &lt;a href="https://www.insight-it.ru/goto/62aa81c9/" rel="nofollow" target="_blank" title="http://www.google.com/mobile/goggles/"&gt;Google Goggles&lt;/a&gt;, приложение, которое
позволяет сфотографировать логотип, достопримечательность или какое-то
место и мгновенно получить информацию о нем.&lt;/p&gt;
&lt;p&gt;Maslan считает, что основной отличительной чертой Google в области
локального поиска является "открытость для всех источников", что
достаточно сложно с технической точки зрения. Это включает в себя
пребывание в состоянии "активной глобальности", а не просто в
индексировании информации о ключевых станциях метро. "Масштаб, с которым
Google работает с картографическими и гео-кодированными данными, в
совокупности с пониманием принципов работы Интернета является ключем для
успешной работы в данной области".&lt;/p&gt;
&lt;p&gt;Возможно в скором будущем мы увидим вещи вроде карт и списков компаний
или мест от Google в еще большем количестве мест и языков по всему миру,
с еще более точной информацией, чутко реагирующей на локальные события
вроде открытия, закрытия или перемещения предприятий и организаций. "Мы
четко понимаем, какие именно вещи у нас получаются лучше всего" -
говорит Maslan. "У нас есть небольшие команды из людей, фанатично
настроенных на реализацию их наиболее правильным образом".&lt;/p&gt;
&lt;h2 id="oblachnye-vychisleniia"&gt;Облачные вычисления&lt;/h2&gt;
&lt;p&gt;Наверняка все наслышаны о знаменитых вычислениях "в облаках", то есть с
использованием программного обеспечения, работающем на удаленных
серверах, часто нескольких одновременно и в виртуализированном&amp;nbsp;окружении, а не прямо на персональном компьютере. В
этом ключе Google наиболее интересует выполнение повседневных задач,
таких как работа с электронной почтой, составление расписаний и
управление документами. На самом деле это всего лишь часть более широкой
стратегии Google по облачным вычисления - именно она создает видимость
того, что потребители, предприятия и организации арендуют вычислительный
мощности и хранилища данных через Интернет, так как это дешевле и более
эффективно для многих приложений.&lt;/p&gt;
&lt;p&gt;Ken Norton, старший продукт-менеджер Google (а также выпускник Boston
University и бывший предприниматель), поведал о Google Apps и стратегии
компании в области облачных вычислений. Команда Norton'а работает
конкретно над Google Calendar, но Google Apps также включают в себя и
другие продукты, такие как Gmail, Google Talk, Google Docs и Google
Sites. &amp;ldquo;Сеть выигрывает на том, как приложения будут потребляться&amp;rdquo; - он
сказал.&lt;/p&gt;
&lt;p&gt;Ключевым преимуществом Google на данном фронте является масштаб и
инфраструктура. "У нас есть настолько много серверов и датацентров по
всему миру, что мы можем содержать их достаточно дешево и эффективно" -
говорит Norton. Это преимущество оказывает влияние и на индивидуальные
устройства, так как оно "открывает новые возможности" для потребителей,
возможность использовать веб-приложения с любого типа устройств, будь то
смартфон, нетбук или обычный полноразмерный ноутбук.&lt;/p&gt;
&lt;p&gt;Работа Google в области облачных вычислений сфокусирована на двух
уровнях: на первом располагаются готовые программные продукты вроде
Google Apps, направленные на прямое потребление конечными пользователями
(как индивидуальными, так и корпоративными); второй же уровень занимает
App Engine, "облачная" платформа, предназначенная для использования
разработчиками программного обеспечения для эффективного построения их
собственных веб-продуктов.&lt;/p&gt;
&lt;p&gt;Относительно прогнозов на следующий год на фронте облачных вычислений,
Norton сказал, что "мы постоянно совершенствуемся". В 2009 году было
запущенно более 100 основных новых функциональных возможностей в Google
Apps - таких вещей, как видео чат в GTalk или Gmail offline. Он считает,
что Google "продолжит делать акцент на коммуникационных предложениях".
Помимо развития Gmail и Calendar, это включает в себя доведение до ума
Google Docs и придание более завершенного вида набору их возможностей.
Norton говорит, что Google также ищет возможности по расширению своих
предложений в области коллаборации, в том числе в виде продуктов для
крупного бизнеса, совместимыми с различными системами обеспечения
безопасности для аутентификации.&lt;/p&gt;
&lt;p&gt;Подведем черту: все выглядит как-будто Google совершает переход от
фокусирования на бесплатных потребительских продуктах, работающих в
"облаках", к более активной работе над платными облачными сервисами для
бизнес-пользователей.&lt;/p&gt;
&lt;h2 id="osvobozhdenie-dannykh"&gt;Освобождение данных&lt;/h2&gt;
&lt;p&gt;Последнее время в компании все больше внимания уделяется предоставлению
пользователям легко экспортировать их данные из продуктов Google, таких
как&amp;nbsp;Blogger, Google Maps, Google Docs, Chrome и App Engine
(пользовательские данные разработчиков). На первый взгляд это может
показаться очередным капризом PR-менеджеров, но на самом деле за этим
фактом стоит более глубокая и интересная инновационная стратегия.&lt;/p&gt;
&lt;p&gt;Brian Fitzpatrick, ветеран opensource разработок, возглавляет двухлетний
проект от офисов Google в Чикаго. Основная идея заключается в оказании
помощи пользователям, если они хотят получить свои файлы и другие данные
из облака Google, чтобы у них была возможность перейти на какую-то
другую систему, если они захотят. "Большинство людей не думает о
возможности экспорта данных до тех пор пока не станет слишком поздно" -
говорит Fitzpatrick. "Мы надеемся, что если вы прекратите использование
одного нашего продукта сегодня, то у вас будет возможность попробовать
другой продукт завтра."&lt;/p&gt;
&lt;p&gt;Помимо "создания правильных возможностей для пользователей" существует и
другая мотивация. "Мы, как компания, старательно работаем над такими
вещами, как поиск. Если пользователи становятся привязанным к вашим
продуктам, то вы становитесь более самодовольными, расслабленными. Если
же уйти достаточно просто, то вы будете серьезно мотивированны делать
свои продукты как можно лучше, чтобы избежать ухода пользователей любой
ценой."&lt;/p&gt;
&lt;p&gt;Что ж, теперь у нас есть эта возможность. Google считает, что эта
открытость с точки зрения пользовательских данных, заставит компанию
работать более старательно для удержания пользовательской
базы.&amp;nbsp;Fitzpatrick не знает других компаний, которые бы открыто заявляли
об инициативе создания подобных возможностей для своих пользователей.&lt;/p&gt;
&lt;p&gt;По его мнению наибольшая трудность лежит не собственно в разработке
такого функционала, а в повышение&amp;nbsp;осведомленности&amp;nbsp;пользователей о
наличии возможности экспортировать свои данные из облака. "Достаточно
сложно заставить пользователей думать, что это на самом деле важно". Но
в целом этот подход достаточно достаточно хорошо вписывается в понятие о
том, как потребители и корпоративные пользователи заботятся о всех своих
данных, когда все большая и большая их част мигрирует "в облака" и как
Google хочет быть ответственным за организацию мировых данным, шаг за
шагом, на протяжении всего пути.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Tue, 29 Dec 2009 18:17:00 +0300</pubDate><guid>tag:www.insight-it.ru,2009-12-29:theory/2009/novyjj-google-internet-gigant-prolivaet-svet-na-temy-poiska-v-realnom-vremeni-lokalnogo-poiska-oblachnykh-vychislenijj-i-osvobozhdeniya-dannykh/</guid><category>cloud computing</category><category>data liberation</category><category>Google</category><category>local search</category><category>online</category><category>realtime search</category><category>интервью</category><category>интернет</category><category>облачные вычисления</category><category>освобождение данных</category><category>поиск</category><category>Сеть</category></item><item><title>Дизайн, верстка и RSS</title><link>https://www.insight-it.ru//misc/2009/dizajjn-verstka-i-rss/</link><description>&lt;p&gt;Я лично считаю, что очень важно после каких-либо кардинальных изменений
сайта получить feedback от пользователей. Данный пост служит именно для
этих целей.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Для затравки пара опросов:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Опрос 2009" class="responsive-img" src="https://www.insight-it.ru/images/design-poll-2009.jpeg"/&gt;&lt;/p&gt;
&lt;p&gt;В добавок хочется услышать отзывы об этих и других нововведениях (вроде
нового хостинга) в комментариях.&lt;/p&gt;
&lt;p&gt;Еще буду рад, если кто-то предложит какие-нибудь интересные и
востребованные темы для новых постов и обсуждений, у меня есть и свои
соображения, но мнение читателей для меня тоже очень важно.&lt;/p&gt;
&lt;p&gt;Всем, проявившим инициативу, заранее спасибо за помощь в улучшении блога
&lt;strong&gt;Insight IT&lt;/strong&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Mon, 28 Dec 2009 20:44:00 +0300</pubDate><guid>tag:www.insight-it.ru,2009-12-28:misc/2009/dizajjn-verstka-i-rss/</guid><category>feedback</category><category>online</category><category>RSS</category><category>WordPress</category><category>верстка</category><category>внешний вид</category><category>дизайн</category><category>опрос</category></item><item><title>Архитектура MySpace</title><link>https://www.insight-it.ru//highload/2009/arkhitektura-myspace/</link><description>&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/f989d588/" rel="nofollow" target="_blank" title="http://www.myspace.com"&gt;MySpace.com&lt;/a&gt; является одним из наиболее быстро
набирающих популярность сайтов в Интернете с 65 миллионами пользователей
и 260000 регистрациями в день. Этот сайт часто подвергается критике
из-за не достаточной производительности, хотя на самом деле MySpace
удалось избежать ряда проблем с масштабируемостью, с которыми
большинство других сайтов неизбежно сталкивались. Как же им это
удалось?
&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="istochniki-informatsii"&gt;Источники информации&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Данная статья является переводом статьи &lt;a href="https://www.insight-it.ru/goto/e9f0b809/" rel="nofollow" target="_blank" title="http://highscalability.com/blog/2009/2/12/myspace-architecture.html"&gt;MySpace
Architecture&lt;/a&gt;,
автором которой является Todd Hoff. Когда-то давно один из читателей
этого блога просил меня осветить и эту тему, тогда я так и не решился
из-за отсутствия моего личного интереса, но сейчас снова случайно
наткнулся на эту статью и подумал: а почему бы и нет?&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/45549701/" rel="nofollow" target="_blank" title="http://www.infoq.com/news/2009/02/MySpace-Dan-Farino"&gt;Презентация: за сценой MySpace.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/8d5c1d4d/" rel="nofollow" target="_blank" title="http://www.baselinemag.com/c/a/Projects-Networks-and-Storage/Inside-MySpacecom/"&gt;Внутри MySpace.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="platforma"&gt;Платформа&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ASP .NET 2.0&lt;/li&gt;
&lt;li&gt;Windows&lt;/li&gt;
&lt;li&gt;IIS&lt;/li&gt;
&lt;li&gt;MSSQL Server&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="chto-vnutri"&gt;Что внутри?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;300 миллионов пользователей.&lt;/li&gt;
&lt;li&gt;Отдает 100Gbps в Интернет. 10Gbps из них является HTML контентом.&lt;/li&gt;
&lt;li&gt;4,500+ веб серверов со связкой: Windows 2003 / IIS 6.0 / ASP .NET.&lt;/li&gt;
&lt;li&gt;1,200+ кэширующих серверов, работающих на 64-bit Windows 2003. На
    каждом 16GB объектов находятся в кэше в оперативной памяти.&lt;/li&gt;
&lt;li&gt;500+ серверов баз данных, работающих на 64-bit Windows и SQL Server
    2005.&lt;/li&gt;
&lt;li&gt;MySpace обрабатывает 1.5 миллиарда просмотров страниц в день, а
    также 2.3 миллионов одновременно работающих пользователей в течении
    дня.&lt;/li&gt;
&lt;li&gt;Вехи по количеству пользователей:&lt;ul&gt;
&lt;li&gt;500 тысяч пользователей: простая архитектура перестает
справляться&lt;/li&gt;
&lt;li&gt;1 миллион пользователей: вертикальное партиционирование временно
спасает от основных болезненных вопросов с масштабированием&lt;/li&gt;
&lt;li&gt;3 миллиона пользователей: горизонтальное масштабирование
побеждает над вертикальным&lt;/li&gt;
&lt;li&gt;9 миллионов пользователей: сайт мигрирует на ASP.NET, создается
виртуализированная система хранения данных (SAN)&lt;/li&gt;
&lt;li&gt;26 миллионов пользователей: MySpace переходит на 64-битную
технологию.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;500 тысяч учетных записей было многовато для двух веб-серверов и
    одного сервера баз данных.&lt;/li&gt;
&lt;li&gt;На 1-2 миллионах учетных записей:&lt;ul&gt;
&lt;li&gt;Они использовали архитектуру базы данных, построенную на
концепции вертикального партиционирования, с отдельными базами
данных для разных частей сайта, которые использовались для
выполнения различных функций, таких как экран авторизации, профили
пользователей и блоги.&lt;/li&gt;
&lt;li&gt;Схема с вертикальным партиционированием помогала разделить
нагрузку как для операций чтения, так и для операций записи, а если
пользователям в друг оказывалась нужна новая функциональная
возможность - достаточно было просто добавить еще один сервер баз
данных для её обслуживания.&lt;/li&gt;
&lt;li&gt;MySpace переходит от использования систем хранения, подключенных
к серверам баз данных напрямую, к сетям хранения данных (SAN), при
таком подходе целый массив систем хранения объединяется вместе
специализированной сетью с высокой пропускной способностью, и
сервера баз данных также получают доступ к хранилищам через эту
сеть. Переход к SAN оказал положительное влияние как на
производительность, так и на доступность и надежность системы.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;На 3 миллионах учетных записей:&lt;ul&gt;
&lt;li&gt;Решение с вертикальным партиционированием не протянуло долго, так
как им приходилось реплицировать какую-то часть информации (например
информацию об учетных записях) по всем вертикальным частям базы
данных. С таким большим количеством операций репликации данных один
узел даже при незначительном сбое мог существенно замедлить
обновление информации во всей системе.&lt;/li&gt;
&lt;li&gt;Индивидуальные приложения вроде блогов на под-секциях сайта
достаточно быстро стали слишком большими для нормальной работы с
единственным сервером базы данных&lt;/li&gt;
&lt;li&gt;Произведена реорганизация всех ключевых данных для более логичной
организации в единственную базу данных&lt;/li&gt;
&lt;li&gt;Пользователи были разбиты на группы по миллиону в каждой и каждая
такая группа была перемещена на отдельный SQL Server&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;9&amp;ndash;17 миллионов учетных записей:&lt;ul&gt;
&lt;li&gt;Переход на ASP .NET, который требовал меньше ресурсов по
сравнению с их предыдущим вариантом архитектуры. 150 серверов,
использовавших новый код могли обработать нагрузку, для которой
раньше требовалось 246 серверов.&lt;/li&gt;
&lt;li&gt;Снова пришлось столкнуться с узким местом в системе хранения
данных. Реализация SAN решило какую-то часть старых проблем с
производительностью, но на тот момент потребности сайта начали
периодически превосходить возможности SAN по пропускной способности
операций ввода-вывода - той скорости, с которой она может читать и
писать данные на дисковые массивы.&lt;/li&gt;
&lt;li&gt;Столкнулись с лимитом производительности при размещении миллиона
учетных записей на одном сервере, ресурсы некоторых серверов начали
исчерпываться.&lt;/li&gt;
&lt;li&gt;Переход к виртуальному хранилищу, где весь SAN рассматривается
как одно большое общее место для хранения данных, без необходимости
назначать конкретные диски для хранения данных определенной части
приложения. MySpace на данный момент работает со стандартизированным
оборудованием от достаточно нового вендора SAN - 3PARdata&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Был добавлен кэширующий уровень &amp;mdash; прослойка из специализированных
    серверов, расположенных между веб-серверами и серверами данных, чья
    единственная задача была захватывать копии часто запрашиваемых
    объектов с данными в памяти и отдавать их веб-серверам для
    минимизации количества поиска данных в СУБД.&lt;/li&gt;
&lt;li&gt;26 миллионов учетных записей:&lt;ul&gt;
&lt;li&gt;Переход на 64-битные сервера с SQL Server на правах решения
проблемы с недостатком оперативной памяти. С тех пор их стандартный
сервер баз данных оснащен 64 GB RAM.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Горизонтальная федерация баз данных&lt;/strong&gt;. Базы данных
    партиционируются в зависимости от своего назначения. У них есть базы
    данных с профилями, электронными сообщениями и так далее. Каждая
    партиция основана на диапазоне пользователей. По миллиону в каждой
    базе данных. Таким образом, у них есть Profile1, Profile2 и все
    остальные базы данных вплоть до Profile300, если считать, что у них
    на данный момент зарегистрировано 300 миллионов учетных записей.&lt;/li&gt;
&lt;li&gt;Кэш ASP не используется, так как он не обеспечивает достаточного
    процента попаданий на веб серверах. Кэш, организованный как
    промежуточный слой, имеет существенно более высокое значение данного
    показателя.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Изоляция сбоев&lt;/strong&gt;. Внутри веб-сервера запросы сегментируются по
    базам данным. Разрешено использование только 7 потоков для работы с
    каждой базой данных. Таким образом, если база данных по каким-то
    причинам начинает работать медленно, только эти потоки замедлятся, в
    то время как остальные потоки будут успешно продолжать обрабатывать
    поток трафика.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="rabota-saita"&gt;Работа сайта&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Коллектор данных о производительности&lt;/strong&gt;. Централизованная система
    сбора информации о производительности через UDP. Такой подход более
    надежен, чем стандартный механизм Windows, а также позволяет любому
    клиенту подключиться и увидеть статистику.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Веб-система по просмотру дампов стеков процессов&lt;/strong&gt;. Можно просто
    сделать клик правой кнопкой мыши на проблемном сервере и увидеть
    дамп стека процессов, управляемых .NET. И это после привычки каждой
    раз удаленно подключаться к серверу, включать дебаггер и через
    полчаса получать свой ответ о том что же все таки происходит.
    Медленно, немасштабируемо и утомительно. Эта же система позволяет
    увидеть не просто стек процесса, но и предоставляет большое
    количество информации о контексте, в котором он работает.
    Обнаружение проблем намного проще при таком подходе, например можно
    легко увидеть, что база не отвечает, так как 90 ее потоков
    заблокировано.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Веб-система создания дампа heap-памяти&lt;/strong&gt;. Создает дамп всей
    выделенной памяти. Очень удобно и полезно для разработчиков.
    Сэкономьте часы на выполнение этой работы вручную.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Профайлер&lt;/strong&gt;. Прослеживает запрос от начала до конца и выводит
    подробный отчет. В нем можно увидеть URL, методы, статус, а также
    все, что поможет идентифицировать медленный запрос и его причины.
    Обнаруживает проблемы с блокировкой потоков, непредвиденными
    исключениями, другими словами все, что может оказаться интересным. В
    то же время остается очень легковесным решением. Работает на одной
    машине из каждой VIP (группа из 100 серверов) в production-среде.
    Опрашивает 1 поток каждые 10 секунд. Постоянно следит за системой в
    фоновом режиме.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Powershell&lt;/strong&gt;. Новая программная оболочка от Microsoft, которая
    работает в процессе и передаем объекты между командами вместо работы
    с текстовыми данными. MySpace разрабатывает множество так называемых
    commandlets'ов для поддержки различных операций.&lt;/li&gt;
&lt;li&gt;Разработана собственная технология асинхронной коммуникации для
    того, чтобы обойти проблемы с сетевыми проблемами Windows и работать
    с серверами как с группой. Например, она позволяет доставить файл
    .cs, скомпилировать его, запустить, и доставить результат обратно.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Развертывание&lt;/strong&gt;. Обновление кодовой базы происходит с помощью
    упомянутой выше собственной технологии. Ранее происходило до 5 таких
    обновлений в день, сейчас же они происходят лишь раз в неделю.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="podvodim-itogi"&gt;Подводим итоги&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;С помощью стека Microsoft тоже можно делать большие веб-сайты.&lt;/li&gt;
&lt;li&gt;Стоит использовать кэширование с самого начала.&lt;/li&gt;
&lt;li&gt;Кэш является более подходящим местом для хранения временных данных,
    не требующих персистентности, например информации о пользовательских
    сессиях.&lt;/li&gt;
&lt;li&gt;Встроенные в операционные систему возможности, например по
    обнаружению DDoS-атака, могут приводить к необъяснимым сбоям.&lt;/li&gt;
&lt;li&gt;Храните свои данные в географически удаленных датацентрах для
    минимизации проблем, связанных со сбоями в электросети.&lt;/li&gt;
&lt;li&gt;Рассматривайте возможности использования виртуализированных систем
    хранения данных или кластерных файловых систем с самого начала. Это
    позволит существенно параллелизировать операции ввода-вывода, а
    также увеличивать дисковое пространство без необходимости какой-либо
    реорганизации.&lt;/li&gt;
&lt;li&gt;Разрабатывайте утилиты для работы с production окружением.
    Невозможно смоделировать все ситуации в тестовой среде.
    Масштабируемость и все различные варианты использования API не могут
    быть симулированы в процессе тестирования качества программного
    обеспечения. Обычные пользователи и хакеры обязательно найдут такие
    способы использования вашего продукта, о которых вы даже никогда и
    не подумаете в процессе тестирования, хотя конечно большая часть все
    же обнаружима в процессе QA тестирования.&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>Mon, 21 Dec 2009 16:15:00 +0300</pubDate><guid>tag:www.insight-it.ru,2009-12-21:highload/2009/arkhitektura-myspace/</guid><category>ASP</category><category>ASP .NET</category><category>highload</category><category>IIS</category><category>Microsoft</category><category>MSSQL</category><category>MySpace</category><category>myspace.com</category><category>online</category><category>Windows</category><category>Windows Server</category><category>архитектура</category><category>архитектура MySpace</category><category>Масштабируемость</category></item><item><title>Google Chrome</title><link>https://www.insight-it.ru//linux/2008/google-chrome/</link><description>&lt;p&gt;&lt;img alt="Google Chrome" class="right" src="https://www.insight-it.ru/images/google-chrome.png" title="Google Chrome"/&gt;
Наверное многие из вас уже успели за последние пару дней стать
свидетелями всей этой шумихи на просторах Сети, связанной с выходом
Google на рынок браузеров. Сопутствующие релизу
&lt;a href="https://www.insight-it.ru/goto/c770d69f/" rel="nofollow" target="_blank" title="http://www.google.com/googlebooks/chrome/#"&gt;комиксы&lt;/a&gt; произвели на меня
вполне положительное впечатление, благодаря достаточно большой
актуальности поднятых в них проблем и интересным вариантам их решений.
Так что я определенно решил, что поглядеть что за зверь такой - &lt;strong&gt;Google
Chrome&lt;/strong&gt;, определенно стоит, а что из этого вышло я и хотел бы тут
рассказать, так что очередную рекламу нового продукта или какие-либо
практически полезные советы у Вас врядли получится здесь обнаружить.
&lt;!--more--&gt;
Первым делом я посетил &lt;a href="https://www.insight-it.ru/goto/34cc95f4/" rel="nofollow" target="_blank" title="http://www.google.com/chrome"&gt;официальную страничку
браузера&lt;/a&gt; и практически сразу немного
разочаровался, увидев в заголовке надпись &lt;strong&gt;Google Chrome (BETA) for
W****ws&lt;/strong&gt;. Сразу напросился вопрос: а где версия для &lt;strong&gt;Linux&lt;/strong&gt;?
Покопавшись в соседних страничках ничего подобного обнаружить не
удалось - пришлось пожать плечами с мыслью "наверное еще не сделали".&lt;/p&gt;
&lt;p&gt;Зато через какое-то время наткнувшись на очередную заметку про все ту же
довольно избитую тему, я заметил ма-а-аленькую неприметную
&lt;a href="https://www.insight-it.ru/goto/2e08eade/" rel="nofollow" target="_blank" title="http://dev.chromium.org/developers/how-tos/build-instructions-linux"&gt;ссылку&lt;/a&gt;
на "инструкцию по компиляции Google Chrome из исходников в Linux". В
очередной раз пожав плечами с мыслью "а нам не привыкать, все равно
Gentoo пользуюсь" отправился вводить заветное заклинание в
свежесозданную консольку.&lt;/p&gt;
&lt;p&gt;Заклинание это выглядит примерно следующим образом:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;CHROME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/src
mkdir &lt;span class="nv"&gt;$CHROME&lt;/span&gt;/chrome
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$CHROME&lt;/span&gt;/chrome
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LANG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;C
&lt;span class="nv"&gt;$CHROME&lt;/span&gt;/depot_tools/gclient config http://src.chromium.org/svn/trunk/src
&lt;span class="nv"&gt;$CHROME&lt;/span&gt;/depot_tools/gclient sync
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$CHROME&lt;/span&gt;/src/chrome
../third_party/scons/scons.py Hammer
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Для успешного каста требуются следующие ингридиенты:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;subversion &amp;gt;= 1.4&lt;/li&gt;
&lt;li&gt;pkg-config &amp;gt;= 0.20&lt;/li&gt;
&lt;li&gt;python &amp;gt;= 2.4&lt;/li&gt;
&lt;li&gt;perl &amp;gt;= 5.x&lt;/li&gt;
&lt;li&gt;gcc/g++ &amp;gt;= 4.2&lt;/li&gt;
&lt;li&gt;bison &amp;gt;= 2.3&lt;/li&gt;
&lt;li&gt;flex &amp;gt;= 2.5.34&lt;/li&gt;
&lt;li&gt;gperf &amp;gt;= 3.0.3&lt;/li&gt;
&lt;li&gt;libnss3-dev &amp;gt;= 3.12&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Начался процесс вполне оптимистично - строчки, генерируемые &lt;strong&gt;svn co&lt;/strong&gt;
побежали по экрану вполне весело, но когда этот процесс затянулся на
более чем час &amp;ndash; стало очевидно, что даже &lt;em&gt;Google&lt;/em&gt; оказалось не по зубам
выдержать такой наплыв желающх "заценить" новую игрушку и обеспечить
достаточную пропускную способность на сервере с SVN. Правда и масштабы
проекта мягко говоря впечатляют - директория с исходным кодом перед
инициализацией компиляции оказалось очень даже весомой: &lt;strong&gt;2.6 GB&lt;/strong&gt;. В
общем в итоге я не придумал ничего лучше, чем по старой традиции
оставить браузер компилироваться на ночь и с чистой совестью уползти
спать.&lt;/p&gt;
&lt;p&gt;В итоге оказалось, что в результате получается не вовсе браузер, а лишь
некоторые непонятно зачем нужные бинарники: надо было внимательно читать
инструкцию, особенно обведенный в красную рамку блок - студенческая
привычка при чтении чего-либо подсознательно отфильтровывать всю на
первый взгляд второстепенную информацию, попадающую в категорию "слишком
много букв", дала о себе знать :( В общем там об этом все заранее
предупреждали - я просто не заметил, ну да ладно: в wine-то оно точно
заведется, все тот же Google с легкостью помог обнаружить
соответствующий мануал, для моего Gentoo он свелся к следующему:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
emerge --sync&lt;span class="p"&gt;;&lt;/span&gt; emerge -av wine cabextract
&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/bin
sudo wget www.kegel.com/wine/winetricks
sudo chmod +x winetricks
winetricks riched20 riched30 flash allfonts
&lt;span class="nb"&gt;cd&lt;/span&gt; ~
wget gpdl.google.com/chrome/install/149.27/chrome_installer.exe
wine chrome_installer.exe
rm chrome_installer.exe
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Запуск с ходу из инсталлятора ничем хорошим не закончилcя, но вот такая
команда вполне нормально запустила-таки браузер&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;wine ~/.wine/drive_c/windows/profiles/blinkov/Local Settings/Application Data/Google/Chrome/Application/chrome.exe--new-http --in-process-plugins
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;(если кто соберется копипастить - не забываем подменять &lt;code&gt;blinkov&lt;/code&gt; на свое имя
пользователя)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Первое впечатление - ужасный V**ta-like дизайн, вернее не то чтобы он
совсем ужасный - минималистичность очень даже полезное свойство для
дизайна браузера, но в мое KDE 3.5.9 темно-фиолетовой раскраски он не
вписывается ну совсем никак. Ну да ладно - пока он стоит "просто
побаловаться", то можно и потерпеть. Далее я решил пройтись по основным
"фишечкам", заинтересовавшим меня в комиксах - все реализовано вполне
"как обещали", очень много концептуально правильных решений, которых в
старом-добром FF определенно не хватает (перечислять наверное смысла
нет - все и так уже, наверное, в курсе что там есть "вкусненького"). Но
и многих абсолютно жизненно-важных вещей я там не обнаружил - начиная с
блокировки рекламы и заканчивая все тем же стандартно-фиксированным
дизайном и отсутствием центрального репозитория плагинов. Кое-какие
неприятности можно свалить на все еще не окончательную доведенность до
ума wine (проблемы с SSL/TSL, скажем), но на них я смело закрывал
глаза - пока не будет полноценной Linux-версии о регулярном
использовании данного продукта речи быть просто не может. Скорость
работы новинки также произвела впечатление - на его фоне даже FF чисто
субъективно показался медлительным (не смотря на все огрехи wine, как
оно будет выглядить в native-версии - предсказать сложно).&lt;/p&gt;
&lt;p&gt;Меню настроек оказалось вполне стандартным - ничего лишнего, лишь самые
необходимые вещи, даже ребенок разберется. Хотя сложно на самом деле
сказать плюс это или минус: если вдруг взбредет в голову потюнить
что-либо более специфическое, могут возникнуть проблемы, хотя впринципе
возможно там всетаки предусмотренно какое-то более расширенное меню
настроек, по аналогии с about:config в FF, а я его просто не нашел.&lt;/p&gt;
&lt;p&gt;Вдоволь наигравшись, я смело закрыл окошко браузера, с твердой
уверенностью, что когда-нибудь потом обязательно заморочусь и с
установкой и (возможно) эксплуатацией полноценной native Linux версии,
когда граждане из Google соизволят-таки довести ее до работоспособного
состояния - к тому времени глядишь и ситуацию с плагинами и темами
исправят. Вот такая вот бестолковая история, спасибо, что дочитали до
конца :)&lt;/p&gt;
&lt;p&gt;P.S.: А вот &lt;a href="/feed/"&gt;тут есть RSS&lt;/a&gt;, если вдруг кто еще не в курсе.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sat, 06 Sep 2008 00:36:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-09-06:linux/2008/google-chrome/</guid><category>Chrome</category><category>Google</category><category>Google Chrome</category><category>online</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><item><title>it's a pic</title><link>https://www.insight-it.ru//misc/2008/its-a-pic/</link><description>&lt;p&gt;&lt;img alt="it's a pic logo" class="left" src="https://www.insight-it.ru/images/itsapic-logo.png" title="логотип"/&gt;
Не удивлюсь, если заголовок этого поста вам не сказал ровным счетом
ничего - это вполне логично. Именно эту ситуацию я и хотел бы сегодня
исправить: &lt;strong&gt;it's a pic&lt;/strong&gt; представляет собой...
&lt;!--more--&gt;
...очередной интернет-проект. Хотели увидеть что-то более
грандиозное? - читайте дальше!&lt;/p&gt;
&lt;p&gt;Начать наверное стоит с обозначения основной сути: поисковая система
изображений, ориентированная на глобальный рынок. Да-да, мы уже видели
поиск картинок в исполнении Google/Yahoo!/MSN/Яндекс/Рамблер (нужное
подчеркнуть) - скажете вы, так в чем же разница?&lt;/p&gt;
&lt;p&gt;Сейчас объясню. Никогда не возникало мысли, что частенько поиск картинок
в обычных поисковых системах по большей части выдает всякий бред, очень
слабо коррелирующий с тем, что Вы на самом деле искали? Основная их
проблема заключается в том, что способов провести ассоциацию между
текстом и изображением не так-то много. Чаще всего в их распоряжении
лишь HTML-документы, ссылающиеся на изображение. То есть на основании
атрибута &lt;code&gt;alt&lt;/code&gt; у тэга &lt;code&gt;&amp;lt;img /&amp;gt;&lt;/code&gt; и изредка anchor-текста обычных
ссылок, поисковая система должна составить представление о том, что же
на самом деле изображено в графическом файле. Варианты ручного
построения таких соответствий тоже существуют, но либо нужно платить
огромнейшему количеству человек за рутинную работу (что-то на грани
фантастики - количество изображений в Сети измеряется числом с слишком
большим количеством нулей) или подталкивать людей заниматься этим
бесплатно, оформив это, например, в виде online-игры. Обычно в таких
играх двум участникам одновременно предоставляется один и тот же набор
изображений, а их задачей является последовательно вводить свои
ассоциации связанные с текущим изображением. Если они оба ввели одно и
то же слово - оно ассоциируется с изображением, а пользователям
начисляются виртуальные очки. В общем поиск изображений по ключевым
словам - задача, связанная с массой проблем и неточностей.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It's a pic&lt;/strong&gt; является как раз поисковой системой, призванной избавить
людей, ищущих изображения от всех этих проблем с неточностью и
некорректностью результатов. Чтобы не придумывать каких-то временных
решений проблемы было решено искоренить основательно: основная идея
заключается в использовании в качестве критерия поиска не набор ключевых
слов, а просто изображение. Сказать, что два изображения похожи,
компьютеру намного проще, чем сказать что на картинке нарисован,
например, жираф - именно на это и делает ставку этот проект.&lt;/p&gt;
&lt;p&gt;Выглядит это примерно следующим образом: допустим Вы хотите найти
побольше изображений заката и выбрать наиболее приглянувшееся, для этого
достаточно загрузить в систему с локального компьютера изображение
заката (хотя если оно уже присутствует в Сети - можно и просто указать
URL) и собственно говоря нажать кнопку "Найти" - вот и все! Вот ваши
результаты:&lt;/p&gt;
&lt;p&gt;&lt;img alt="пример работы it's a pic" class="responsive-img" src="https://www.insight-it.ru/images/itsapic-scr.jpg" title="пример работы"/&gt;&lt;/p&gt;
&lt;p&gt;Наверное Вы уже заметили, что написав приличную часть поста я так до сих
пор и не дал ссылки на саму поисковую систему. У этого есть достаточно
простая причина - проект находится в стадии закрытого
&amp;beta;-тестирования (что вы собственно говоря могли
прочитать и на скриншоте чуть выше). Так что недостаточная точность
поиска вполне объясняется скромной базой данных изображений - можно
заметить на все том же скриншоте семизначную цифру количества
изображений в его базе. Но даже из такого небольшого количества
изображений системе удается достаточно точно выбрать похожие на образец
экземпляры и отсортировать их в соответствии с их релевантностью
оригиналу.&lt;/p&gt;
&lt;p&gt;Наверняка у Вас снова напрашивается вопрос: а как же я собственно попал
в закрытую бету проекта и узнал так много о нем еще до его запуска? Нет,
мне никто так до сих пор и не дает эксклюзивной информации о проектах,
но эта информация была получена и не из Сети. Не буду тянуть и раскрою
все карты: я просто-напросто с недавних пор участвую в этом проекте.
Собственно говоря одной из основных моих задач является вывод этой
системы из закрытой бета-версии в открытую, то есть обеспечить
работоспособность алгоритмов при несколько больших нагрузках, чем
один-два разработчика одновременно, ищущих что-то просто для проверки и
тестирования.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Tue, 27 May 2008 19:35:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-05-27:misc/2008/its-a-pic/</guid><category>it's a pic</category><category>online</category><category>архитектура</category><category>изображение</category><category>информационные технологии</category><category>поиск</category><category>поисковые системы</category></item><item><title>Архитектура Google Talk</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-googletalk/</link><description>&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/8bce017/" rel="nofollow" target="_blank" title="http://www.google.com/talk"&gt;Google Talk&lt;/a&gt; представляет собой сервис
мгновенного обмена сообщениями от Google. В основе этого сервиса лежит
&lt;abbr title="eXtensible Messaging and Presence Protocol"&gt;XMPP&lt;/abbr&gt; протокол, более известный как &lt;em&gt;Jabber&lt;/em&gt;. В России среди &lt;abbr title="Instant Messaging"&gt;IM&lt;/abbr&gt;-сервисов
несомненно наиболее широко распространен &lt;em&gt;ICQ&lt;/em&gt;, но количество русских
пользователей &lt;em&gt;Jabber&lt;/em&gt; тоже неуклонно растет.&lt;/p&gt;
&lt;p&gt;Вам когда-нибудь доводилось задумываться какое количество сообщений
приходится обрабатывать такого рода сервисам? Допустим есть абстрактный
&lt;abbr title="Instant Messaging"&gt;IM&lt;/abbr&gt;-сервис, которым пользуется миллион пользователей, в среднем каждый из
них отправляет сто текстовых сообщений. Сколько всего сообщений
обработал и доставил сервис? Сто миллионов? Наивно!
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="vvedenie"&gt;Введение&lt;/h3&gt;
&lt;p&gt;Сервисы мгновенного обмена на самом деле подвергаются существенно
большей нагрузке, чем это может показаться на первый взгляд. Давайте
взглянем на расшифровку аббревиатуры &lt;abbr title="eXtensible Messaging and Presence Protocol"&gt;XMPP&lt;/abbr&gt;: eXtensible Messaging and
Presence Protocol. Обмен сообщениями - лишь одна из его функций,
наиболее важная же его часть остается "за сценой" - отображение
присутствия пользователей &lt;em&gt;online&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Давайте посмотрим на наш абстрактный пример с точки зрения присутствия:
пускай им пользуется все тот же миллион пользователей, когда один из них
включил компьютер и появился online - он должен уведомить весь свой
список контактов об этом событии, а также узнать кто из них находится
online. Если этот список велик, то такое элементарное событие может
обернуться для сервиса далеко не одной сотней обработанных и
доставленных сообщений. Помимо простого изменения статуса online/offline
подобную цепочку сообщений может генерировать и любое другое изменение
статуса: связанное с отсутствием пользователя около компьютера или с
изменением небольшого текстового сообщения, которое обычно отображается
в контакт листе рядом с ником пользователя и призвано отображать текущее
его состояние, занятие или чего там только не пишут (эта функция не
всегда предоставляется &lt;abbr title="Instant Messaging"&gt;IM&lt;/abbr&gt;-сервисами, но наверняка многим знакома по
&lt;em&gt;ICQ&lt;/em&gt;, если не по &lt;em&gt;Jabber&lt;/em&gt;). Все эти сообщения как раз и стоят за
"presence" в аббревиатуре &lt;abbr title="eXtensible Messaging and Presence Protocol"&gt;XMPP&lt;/abbr&gt;, суммарный траффик, ими генерируемый,
может в несколько раз превышать траффик от собственно самих текстовых
сообщений.&lt;/p&gt;
&lt;p&gt;Если учесть факты, описанные в предыдущем абзаце, не трудно догадаться,
что зависимость суммарного количества presence-сообщений от количества
пользователей &lt;abbr title="Instant Messaging"&gt;IM&lt;/abbr&gt;-сервиса далеко не линейна. Их количество за какой-то
период времени можно очень приблизительно посчитать как произведение
трех параметров: количества пользователей online, средней длины списка
контактов среди них и количества изменений статуса каждым пользователем.
А каждый дополнительный пользователь в системе так или иначе увеличивает
как минимум два из этих трех параметров.&lt;/p&gt;
&lt;p&gt;Введение несколько затянулась, а проблема масштабируемости &lt;abbr title="eXtensible Messaging and Presence Protocol"&gt;XMPP&lt;/abbr&gt;-сервисов
я думаю теперь стала очевидна, так что сейчас очень подходящий момент,
чтобы вернуться к основной теме разговора - сервису Google Talk и том,
как команда его разработчиков решает эту проблему.&lt;/p&gt;
&lt;h3 id="istochniki-informatsii"&gt;Источники информации&lt;/h3&gt;
&lt;p&gt;Наверное уже стало заметно, что это не очередной перевод, а лично мной
написанный текстик. Так что сразу выдам
&lt;a href="https://www.insight-it.ru/goto/bd0c001f/" rel="nofollow" target="_blank" title="http://video.google.com/videoplay?docid=6202268628085731280"&gt;видео&lt;/a&gt;,
являющееся основным источником информации, и продолжу.&lt;/p&gt;
&lt;h3 id="arkhitektura"&gt;Архитектура&lt;/h3&gt;
&lt;p&gt;Со стороны Google (о котором я, кстати говоря, &lt;a href="https://www.insight-it.ru/highload/2008/arkhitektura-google/"&gt;уже писал&lt;/a&gt;) было бы глупо строить
сервис мгновенного обмена сообщениями в стороне от остальных
коммуникационных сервисов, предоставляемых этой компанией. Еще до своего
публичного старта Google Talk был интегрирован в почтовый сервис
&lt;a href="https://www.insight-it.ru/goto/af1829ed/" rel="nofollow" target="_blank" title="http://www.gmail.com"&gt;GMail&lt;/a&gt; и социальную сеть
&lt;a href="https://www.insight-it.ru/goto/31afe99f/" rel="nofollow" target="_blank" title="http://www.orkut.com"&gt;Orkut&lt;/a&gt;: эти сервисы просто запрашивали у Google
Talk присутствие online пользователей из своего списка контактов при
возникновении соответствующих событий, но при этом не отображали
результаты в своих страницах. Таким образом разработчики получили
возможность оценить предстоящие нагрузки и готовность сервиса к
публичному запуску намного более точно, чем они могли бы это сделать
средствами синтетических тестов.&lt;/p&gt;
&lt;p&gt;В отношении распределения нагрузок, сразу же был выбран и реализован
подход, связанный с разбиением пользователей на группы и распределением
работы с каждой отдельной группой по разным серверам. Это позволило
избежать всей той эволюции серверной части приложения от одного сервера
до большого кластера, что впрочем вполне оправданно, так как сразу же
после запуска сервису предстояло столкнуться с огромным количеством
пользователей и не ничуть не меньшей нагрузкой. Разработчики не забыли и
сразу же предусмотреть безболезненный перенос пользователей с одного
сервера на другой без видимых для него изменений, это позволило очень
гибко изменять количество серверов в системе.&lt;/p&gt;
&lt;p&gt;С точки зрения интеграции сервиса с другими проектами
&lt;a href="/tag/google/"&gt;Google&lt;/a&gt;, очень важно было предоставить определенный
уровень абстракции для взаимодействия в виде API и набора адресов, по
которым необходимо обращаться к сервису. Придерживаясь одного API можно
производить практически любые архитектурные или программные изменения в
рамках проекта таким образом, что все его пользователи и проекты, в
которые он интегрирован, просто не заметят что что-то изменилось.
Адреса, к которым происходит обращение при обмене данных, так же
являются своеобразной абстракцией - можно переместить сервис в новый
датацентр и благодаря DNS трафик будет направляться в нужное место.&lt;/p&gt;
&lt;p&gt;С другой стороны необходимо учитывать и программное обеспечение
работающие ниже уровнем, чем собственно код приложения: особенно ядро
операционной системы и используемые библиотеки. В данном случае большую
роль играет количество открытых TCP соединений, так как &lt;abbr title="Instant Messaging"&gt;IM&lt;/abbr&gt; требует
большое их количество, но активность в них не велика.&lt;/p&gt;
&lt;p&gt;Разработчики Google Talk постарались как можно больше внимания уделить
возможным сбоям и связанным с ними ситуациям. Любое даже запланированное
временное прекращение функционирования какой-то части системы может
резко увеличить нагрузку на остальную часть, даже если это просто
перезагрузка части системы - из-за очистившегося кэша серверы снова
начнут полноценно функционировать далеко не сразу, не говоря уже о
непредвиденных сбоях, когда последствия намного более глобальны. Для
своевременного устранения потенциальных проблем как с общем
функционированием системы, так и с недостаточной производительностью,
ведутся логи для всех этапов обработки запросов, а также предусмотрена
возможность профайлинга прямо на работающих в системе серверах.&lt;/p&gt;
&lt;p&gt;Но не стоит забывать и о клиентской части программного обеспечения:
какая-нибудь глупая ошибка в коде клиента сервиса запросто может
устроить DDoS атаку на сервис, что и случилось с одной из ранних версий
клиента Google Talk. Помимо этого необходимо поддерживать совместимость
разных версий клиентских приложений.&lt;/p&gt;
&lt;h3 id="zakliuchenie"&gt;Заключение&lt;/h3&gt;
&lt;p&gt;Благодаря описанным выше принципам Google Talk удается обрабатывать
каждое из миллиардов сообщений в день менее чем за 100 миллисекунд.
Тесная интеграция с другими сервисами &lt;a href="/tag/google/"&gt;Google&lt;/a&gt; позволила
проекту сразу же получить невероятную популярность, а продуманный подход
к разработке сервиса позволил справиться с огромной нагрузкой.&lt;/p&gt;
&lt;p&gt;На этот раз статья получилась скорее о специфике сервиса, чем о его
реализации. Технической информации найти практически не удалось, так что
очень кратко все, но надеюсь и в таком варианте было достаточно
интересно почитать. Напоследок хочу порекомендовать &lt;a href="/feed/"&gt;подписаться на RSS&lt;/a&gt;, если не хотите пропустить публикацию новых постов.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 22 May 2008 16:39:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-05-22:highload/2008/arkhitektura-googletalk/</guid><category>Google</category><category>Google Talk</category><category>IM</category><category>Jabber</category><category>Java</category><category>Linux</category><category>online</category><category>sharding</category><category>XMPP</category><category>архитектура</category><category>архитектура Google Talk</category><category>присутствие</category></item><item><title>DMOZ.org</title><link>https://www.insight-it.ru//misc/2008/dmozorg/</link><description>&lt;p&gt;Возможно Вы уже обратили внимание, что в начале мая данный блог был
добавлен в один из крупнейших (если не самый крупнейший) каталог
интернет-ресурсов - &lt;a href="https://www.insight-it.ru/goto/67c25a97/" rel="nofollow" target="_blank" title="http://dmoz.org"&gt;&lt;strong&gt;DMOZ.org&lt;/strong&gt;&lt;/a&gt;, также известный как
&lt;em&gt;Open Directory Project&lt;/em&gt;. Само по себе это событие достаточно значимо
для любого сайта, но я почему-то не счел нужным писать по этому поводу
отдельный пост, видимо просто так как других слов кроме как "Ура! Мой
блог попал в DMOZ!!!" у меня тогда не нашлось.&lt;/p&gt;
&lt;p&gt;Сегодня же произошло другое событие, связанное с этим крупным каталогом:
я стал редактором очень
небольшого его раздела - &lt;strong&gt;World/Russian/Компьютеры/Программирование/Блоги&lt;/strong&gt;. Раздел и правда оказался очень маленький - сегодняшним же утром за часок-другой разгреб все заявки, которые там лежали нерасмотренными. В целом впечатления от данного процесса очень положительные - нашел несколько интересных сайтов в заявках, которые потом еще достаточно долго читал просто так, уже после принятия решения о добавлении в каталог. Хотелось бы конечно раздел побольше, но я думаю всему свое время. Если у кого-нибудь из Вас есть блоги, подходящие под тематику выделенного мне раздела - &lt;a href="https://www.insight-it.ru/goto/6c8c179f/" rel="nofollow" target="_blank" title="http://www.dmoz.org/cgi-bin/add.cgi?where=World/Russian/%d0%9a%d0%be%d0%bc%d0%bf%d1%8c%d1%8e%d1%82%d0%b5%d1%80%d1%8b/%d0%9f%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5/%d0%91%d0%bb%d0%be%d0%b3%d0%b8"&gt;добавляйте их&lt;/a&gt;,
с удовольствием рассмотрю.
&lt;img alt="DMOZ Logo" class="right" src="https://www.insight-it.ru/images/dmoz-logo.png" title="DMOZ"/&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Mon, 19 May 2008 17:14:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-05-19:misc/2008/dmozorg/</guid><category>DMOZ.org</category><category>ODP</category><category>online</category><category>Open Directory Project</category><category>интернет</category><category>каталог</category><category>редактор</category></item><item><title>Масштабируемые веб-архитектуры</title><link>https://www.insight-it.ru//theory/2008/masshtabiruemye-veb-arkhitektury/</link><description>&lt;p&gt;&lt;img alt="Масштабируемость" class="right" src="https://www.insight-it.ru/images/display.png"/&gt;
Уже немало слов было сказано по этой теме как в моем блоге, так и за
его пределами. Мне кажется настал подходящий момент для того, чтобы
перейти от частного к общему и попытаться взглянуть на данную тему
отдельно от какой-либо успешной ее реализации.&lt;/p&gt;
&lt;p&gt;Приступим?
&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Для начала имеет смысл определиться с тем, о чем мы вообще будем
говорить. В данном контексте перед веб-приложением ставятся три основные
цели:&lt;/p&gt;
&lt;ul&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;/ul&gt;
&lt;p&gt;Основной темой разговора будет, как не трудно догадаться,
масштабируемость, но и остальные цели не думаю, что останутся в стороне.
Сразу хочется сказать пару слов про доступность, чтобы не возвращаться к
этому позднее, подразумевая как "само собой разумеется": любой сайт так
или иначе стремится к тому, чтобы функционировать максимально стабильно,
то есть быть доступным абсолютно всем своим потенциальным посетителям в
абсолютно каждый момент времени, но порой случаются всякие
непредвиденные ситуации, которые могут стать причиной временной
недоступности. Для минимизации потенциального ущерба доступности
приложения необходимо избегать наличия компонентов в системе,
потенциальный сбой в которых привел бы к недоступности какой-либо
функциональности или данных (или хотябы сайта в целом). Таким образом
каждый сервер или любой другой компонент системы должен иметь хотябы
одного дублера (не важно в каком режиме они будут работать: параллельно
или один "подстраховывает" другой, находясь при этом в пассивном
режиме), а данные должны быть реплицированы как минимум в двух
экземплярах (причем желательно не на уровне RAID, а на разных физических
машинах). Хранение нескольких резервных копий данных где-то отдельно от
основной системы (например на специальных сервисах или на отдельном
кластере) также поможет избежать многих проблем, если что-то пойдет не
так. Не стоит забывать и о финансовой стороне вопроса: подстраховка на
случай сбоев требует дополнительных существенных вложений в
оборудование, которые имеет смысл стараться минимизировать.&lt;/p&gt;
&lt;p&gt;Масштабируемость принято разделять на два направления:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;Вертикальная масштабируемость&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Увеличение производительности каждого компонента системы c целью
повышения общей производительности.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;Горизонтальная масштабируемость&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Разбиение системы на более мелкие структурные компоненты и
разнесение их по отдельным физическим машинам (или их группам) и/или
увеличение количества серверов параллельно выполняющих одну и ту же
функцию.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Так или иначе, при разработке стратегии роста системы приходится искать
компромис между ценой, временем разработки, итоговой производительность,
стабильностью и еще массой других критериев. С финансовой точки зрения
вертикальная масштабируемость является далеко не самым привлекательным
решением, ведь цены на сервера с большим количеством процессоров всегда
растут практически экспоненциально относительно количества процессоров.
Именно по-этому наиболее интересен горизонтальный подход, так как именно
он используется в большинстве случаев. Но и вертикальная
масштабируемость порой имеет право на существование, особенно в
ситуациях, когда основную роль играет время и скорость решения задачи, а
не финансовый вопрос: ведь купить БОЛЬШОЙ сервер существенно быстрее,
чем практически заново разрабатывать приложения, адаптируя его к работе
на большом количестве параллельно работающих серверов.&lt;/p&gt;
&lt;p&gt;Закончив с общими словами давайте перейдем к обзору потенциальных
проблем и вариантов их решений при горизонтальном масштабировании.
Просьба особо не критиковать - на абсолютную правильность и
достоверность не претендую, просто "мысли вслух", да и даже упомянуть
все моменты данной темы у меня определенно не получится.&lt;/p&gt;
&lt;h3 id="servery-prilozhenii"&gt;Серверы приложений&lt;/h3&gt;
&lt;p&gt;В процессе масштабирования самих приложений редко возникают проблемы,
если при разработке всегда иметь ввиду, что каждый экземпляр приложения
должен быть непосредственно никак не связан со своими "коллегами" и
должен иметь возможность обработать абсолютно любой запрос пользователя
вне зависимости от того где обрабатывались предыдущие запросы данного
пользователя и что конкретно он хочет от приложения в целом в текущий
момень.&lt;/p&gt;
&lt;p&gt;Далее, обеспечив независимость каждого отдельного запущенного
приложения, можно обрабатывать все большее и большее количество запросов
в единицу времени просто увеличивая количество параллельно
функционирующих серверов приложений, участвующих в системе. Все
достаточно просто (относительно).&lt;/p&gt;
&lt;h3 id="balansirovka-nagruzki"&gt;Балансировка нагрузки&lt;/h3&gt;
&lt;p&gt;Следущая задача - равномерно распределить запросы между доступными
серверами приложений. Существует масса подходов к решению этой задачи и
еще больше продуктов, предлагающих их конкретную реализацию.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;Оборудование&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Сетевое оборудование, позволяющее распределять нагрузку между
несколькими серверами, обычно стоит достаточно внушительные суммы,
но среди прочих вариантов обычно именно этот подход предлагает
наивысшую производительность и стабильность (в основном благодаря
качеству, плюс такое оборудование иногда поставляется парами,
работающими по принципу
&lt;a href="https://www.insight-it.ru/goto/a40f2b94/" rel="nofollow" target="_blank" title="http://en.wikipedia.org/wiki/Heartbeat_%28program%29"&gt;HeartBeat&lt;/a&gt;).
В этой индустрии достаточно много серьезных брендов, предлагающих
свои решения - есть из чего выбрать: &lt;em&gt;Cisco&lt;/em&gt;, &lt;em&gt;Foundry&lt;/em&gt;, &lt;em&gt;NetScalar&lt;/em&gt;
и многие другие.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;Программное обеспечение&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;В этой области еще большее разнообразие возможных вариантов.
Получить программно производительность сопоставимую с аппаратными
решениями не так-то просто, да и HeartBeat придется обеспечивать
программно, но зато оборудование для функционирования такого решения
представляет собой обычный сервер (возможно не один). Таких
программных продуктов достаточно много, обычно они представляют
собой просто HTTP-серверы, перенаправляющие запросы своим коллегам
на других серверах вместо отправки напрямую на обработку
интерпретатору языка программирования. Для примера можно упомянуть,
скажем, &lt;a href="/tag/nginx/"&gt;nginx&lt;/a&gt; с &lt;code&gt;mod_proxy&lt;/code&gt;. Помимо этого имеют
место более экзотические варианты, основанные на DNS, то есть в
процессе определения клиентом IP-адреса сервера с необходимым ему
интернет-ресурсов адрес выдается с учетом нагрузки на доступные
сервера, а также некоторых географических соображений.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Каждый вариант имеет свой ассортимент положительных и отрицательных
сторон, именно по-этому однозначного решения этой задачи не существует -
каждый вариант хорош в своей конкретной ситуации. Не стоит забывать, что
никто не ограничивает Вас в использовании лишь одного из них, при
необходимости может запросто быть реализована и практически произвольная
комбинация из них.&lt;/p&gt;
&lt;h3 id="resursoemkie-vychisleniia"&gt;Ресурсоемкие вычисления&lt;/h3&gt;
&lt;p&gt;Во многих приложениях используются какие-либо сложные механизмы, это
может быть конвертирование видео, изображений, звука, или просто
выполнение каких-либо ресурсоемких вычислений. Такие задачи требует
отдельного внимания если мы говорим о Сети, так как пользователь
интернет-ресурса врядли будет счастлив наблюдать за загружающейся
несколько минут страницей в ожидании лишь для того, чтобы увидеть
сообщение вроде: "Операция завершена успешно!".&lt;/p&gt;
&lt;p&gt;Для избежания подобных ситуаций стоит постараться минимизировать
выполнение ресурсоемких операций синхронно с генерацией интернет
страниц. Если какая-то конкретная операция не влияет на новую страницу,
отправляемую пользователю, то можно просто организовать &lt;em&gt;очередь&lt;/em&gt;
заданий, которые необходимо выполнить. В таком случае в момент когда
пользователь совершил все действия, необходимые для начала операции,
сервер приложений просто добавляет новое задание в очередь и сразу
начинает генерировать следущую страницу, не дожидаясь результатов. Если
задача на самом деле очень трудоемкая, то такая очередь и обработчики
заданий могут располагаться на отдельном сервере или кластере.&lt;/p&gt;
&lt;p&gt;Если результат выполнения операции задействован в следующей странице,
отправляемой пользователю, то при асинхронном ее выполнении придется
несколько схитрить и как-либо отвлечь пользователя на время ее
выполнения. Например, если речь идет о конвертировании видео в &lt;strong&gt;flv&lt;/strong&gt;,
то например можно быстро сгенерировать скриншот с первым кадром в
процессе составления страницы и подставить его на место видео, а
возможность просмотра динамически добавить на страницу уже после, когда
конвертирование будет завершено.&lt;/p&gt;
&lt;p&gt;Еще один неплохой метод обработки таких ситуаций заключается просто в
том, чтобы попросить пользователя "зайти попозже". Например, если сервис
генерирует скриншоты веб-сайтов из различных браузеров с целью
продемонстрировать правильность их отображения владельцам или просто
интересующимся, то генерация страницы с ними может занимать даже не
секунды, а минуты. Наиболее удобным для пользователя в такой ситуации
будет предложение посетить страницу по указанному адресу через
столько-то минут, а не ждать у моря погоды неопределенный срок.&lt;/p&gt;
&lt;h3 id="sessii"&gt;Сессии&lt;/h3&gt;
&lt;p&gt;Практически все веб-приложения каким-либо образом взаимодействуют со
своими посетителями и в подавляющем большинстве случаев в них
присутствует необходимость отслеживать перемещения пользователей по
страницам сайта. Для решения этой задачи обычно используется механизм
&lt;em&gt;сессий&lt;/em&gt;, который заключается в присвоении каждому посетителю
уникального идентификационного номера, который ему передается для
хранения в cookies или, в случае их отсутствия, для постоянного
"таскания" за собой через GET. Получив от пользователя некий ID вместе с
очередным HTTP-запросом сервер может посмотреть в список уже выданных
номеров и однозначно определить кто его отправил. С каждым ID может
ассоциироваться некий набор данных, который веб-приложение может
использовать по своему усмотрению, эти данные обычно по-умолчанию
хранятся в файле во временной директории на сервере.&lt;/p&gt;
&lt;p&gt;Казалось бы все просто, но... но запросы посетителей одного и того же
сайта могут обрабатывать сразу несколько серверов, как же тогда
определить не был ли выдан полученный ID на другом сервере и где вообще
хранятся его данные?&lt;/p&gt;
&lt;p&gt;Наиболее распространенными решениями является централизация или
децентрализация сессионных данных. Несколько абсурдная фраза, но,
надеюсь, пара примеров сможет прояснить ситуацию:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;Централизованное хранение сессий&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Идея проста: создать для всех серверов общую "копилку", куда они
смогут складывать выданные ими сессии и узнавать о сессиях
посетителей других серверов. В роли такой "копилки" теоретически
может выступать и просто примонтированная по сети файловая система,
но по некоторым причинам более перспективным выглядит использование
какой-либо СУБД, так как это избавляет от массы проблем, связанных с
хранением сессионных данных в файлах. Но в варианте с общей базой
данных не стоит забывать, что нагрузка на него будет неуклонно расти
с ростом количества посетителей, а также стоит заранее предусмотреть
варианты выхода из проблематичных ситуаций, связанных с
потенциальными сбоями в работе сервера с этой СУБД.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;Децентрализованное хранение сессий&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Наглядный пример - хранение сессий в &lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt;,
изначально расчитанная на распределенное хранение данных в
оперативной памяти система позволит получать всем серверам быстрый
доступ к любым сессионным данным, но при этом (в отличии от
предыдущего способа) какой-либо единый центр их хранения будет
отсутствовать. Это позволит избежать узких мест с точек зрения
производительности и стабильности в периоды повышенных нагрузок.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;В качестве альтернативы сессиям иногда используют похожие по
предназначению механизмы, построенные на cookies, то есть все
необходимые приложению данные о пользователе хранятся на клиентской
стороне (вероятно в зашифрованном виде) и запрашиваются по мере
необходимости. Но помимо очевидных преимуществ, связанных с отсутствием
необходимости хранить лишние данные на сервере, возникает ряд проблем с
безопасностью. Данные, хранимые на стороне клиента даже в зашифрованном
виде, представляют собой потенциальную угрозу для функционирования
многих приложений, так как любой желающий может попытаться
модифицировать их в своих интересах или с целью навредить приложению.
Такой подход хорош только если есть уверенность, что абсолютно любые
манипуляции с хранимые у пользователей данными безопасны. Но можно ли
быть уверенными на 100%?&lt;/p&gt;
&lt;h3 id="staticheskii-kontent"&gt;Статический контент&lt;/h3&gt;
&lt;p&gt;Пока объемы статических данных невелики - никто не мешает хранить их в
локальной файловой системе и предоставлять доступ к ним просто через
отдельный легковесный веб-сервер вроде &lt;a href="/tag/lighttpd/"&gt;lighttpd&lt;/a&gt; (я
подразумеваю в основном разные формы медиа-данных), но рано или поздно
лимит сервера по дисковому пространству или файловой системы по
количеству файлов в одной директории будет достигнут, и придется думать
о перераспределении контента. Временным решением может стать
распределение данных по их типу на разные сервера, или, возможно,
использование иерархической структуры каталогов.&lt;/p&gt;
&lt;p&gt;Если статический контент играет одну из основных ролей в работе
приложения, то стоит задуматься о применении распределенной файловой
системы для его хранения. Это, пожалуй, один из немногих способов
горизонтально масштабировать объем дискового пространства путем
добавления дополнительных серверов без каких-либо кардинальных изменений
в работе самого приложения. На какой именно кластерной файловой системе
остановить свой выбор ничего сейчас советовать не хочу, я уже
опубликовал далеко не один обзор конкретных реализаций - попробуйте
прочитать их все и сравнить, если этого мало - вся остальная Сеть в
Вашем распоряжении.&lt;/p&gt;
&lt;p&gt;Возможно такой вариант по каким-либо причинам будет нереализуем, тогда
придется "изобретать велосипед" для реализации на уровне приложения
принципов схожих с сегментированием данных в отношении СУБД, о которых я
еще упомяну далее. Этот вариант также вполне эффективен, но требует
модификации логики приложения, а значит и выполнение дополнительной
работы разработчиками.&lt;/p&gt;
&lt;p&gt;Альтернативой этим подходам выступает использование так называемых
&lt;strong&gt;Content Delievery Network&lt;/strong&gt; - внешних сервисов, обеспечивающих
доступность Вашего контента пользователям за определенное материальное
вознаграждение сервису. Преимущество очевидно - нет необходимости
организовывать собственную инфраструктуру для решения этой задачи, но
зато появляется другая дополнительная статья расходов. Список таких
сервисов приводить не буду, если кому-нибудь понадобится - найти будет
не трудно.&lt;/p&gt;
&lt;h3 id="keshirovanie"&gt;Кэширование&lt;/h3&gt;
&lt;p&gt;Кэширование имеет смысл проводить на всех этапах обработки данных, но в
разных типах приложений наиболее эффективными являются лишь некоторые
методы кэширования.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;СУБД&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Практически все современные СУБД предоставляют встроенные механизмы
для кэширования результатов определенных запросов. Этот метод
достаточно эффективен, если Ваша система регулярно делает одни и те
же выборки данных, но также имеет ряд недостатков, основными из
которых является инвалидация кэша всей таблицы при малейшем ее
изменении, а также локальное расположение кэша, что неэффективно при
наличии нескольких серверов в системе хранения данных.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;Приложение&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;На уровне приложений обычно производится кэширование объектов любого
языка программирования. Этот метод позволяет вовсе избежать
существенной части запросов к СУБД, сильно снижая нагрузку на нее.
Как и сами приложения такой кэш должен быть независим от конкретного
запроса и сервера, на котором он выполняется, то есть быть доступным
всем серверам приложений одновременно, а еще лучше - быть
распределенным по нескольким машинам для более эффективной
утилизации оперативной памяти. Лидером в этом аспекте кэширования по
праву можно назвать &lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt;, о котором я в свое
время уже успел &lt;a href="https://www.insight-it.ru/storage/2008/obzor-memcached/"&gt;подробно рассказать&lt;/a&gt;.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;HTTP-сервер&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Многие веб-серверы имеют модули для кэширования как статического
контента, так и результатов работы скриптов. Если страница редко
обновляется, то использование этого метода позволяет без каких-либо
видимых для пользователя изменений избегать генерации страницы в
ответ на достаточно большую часть запросов.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;Reverse proxy&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Поставив между пользователем и веб-сервером прозрачный
прокси-сервер, можно выдавать пользователю данные из кэша прокси
(который может быть как в оперативной памяти, так и дисковым), не
доводя запросы даже до HTTP-серверов. В большинстве случаев этот
подход актуален только для статического контента, в основном разных
форм медиа-данных: изображений, видео и тому подобного. Это
позволяет веб-серверам сосредоточиться только на работе с самими
страницами.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Кэширование по своей сути практически не требует дополнительных затрат
на оборудование, особенно если внимательно наблюдать за использованием
оперативной памяти остальными компонентами серверами и утилизировать все
доступные "излишки" под наиболее подходящие конкретному приложению формы
кэша.&lt;/p&gt;
&lt;p&gt;Инвалидация кэша в некоторых случаях может стать нетривиальной задачей,
но так или иначе универсального решения всех возможных проблем с ней
связанных написать не представляется возможным (по крайней мере лично
мне), так что оставим этот вопрос до лучших времен. В общем случае
решение этой задачи ложится на само веб-приложение, которое обычно
реализует некий механизм инвалидации средствами удаления объекта кэша
через определенный &lt;em&gt;период времени&lt;/em&gt; после его создания или последнего
использования, либо "вручную" при возникновении определенных &lt;em&gt;событий&lt;/em&gt;
со стороны пользователя или других компонентов системы.&lt;/p&gt;
&lt;h3 id="bazy-dannykh"&gt;Базы данных&lt;/h3&gt;
&lt;p&gt;На закуску я оставил самое интересное, ведь этот неотъемлемый компонент
любого веб-приложения вызывает больше проблем при росте нагрузок, чем
все остальные вместе взятые. Порой даже может показаться, что стоит
вообще отказаться от горизонтального масштабирования системы хранения
данных в пользу вертикального - просто купить тот самый БОЛЬШОЙ сервер
за шести- или семизначную сумму не-рублей и не забивать себе голову
лишними проблемами.&lt;/p&gt;
&lt;p&gt;Но для многих проектов такое кардинальное решение (и то, по большому
счету, временное) не подходит, а значит перед ними осталась лишь одна
дорога - горизонтальное масштабирование. О ней и поговорим.&lt;/p&gt;
&lt;p&gt;Путь практически любого веб проекта с точки зрения баз данных начинался
с одного простого сервера, на котором работал весь проект целиком. Затем
в один прекрасный момент наступает необходимость вынести СУБД на
отдельный сервер, но и он со временем начинает не справляться с
нагрузкой. Подробно останавливаться на этих двух этапах смысла особого
нет - все относительно тривиально.&lt;/p&gt;
&lt;p&gt;Следующим шагом обычно бывает &lt;strong&gt;master-slave&lt;/strong&gt; с асинхронной репликацией
данных, как работает эта схема уже неоднократно упоминалось в блоге, но,
пожалуй, повторюсь: при таком подходе все операции записи выполняются
лишь на одном сервере (master), а остальные сервера (slave) получают
данные напрямую от "мастера", обрабатывая при этом лишь запросы на
чтение данных. Как известно, операции чтения и записи любого веб-проекта
всегда растут пропорционально росту нагрузки, при этом сохраняется почти
фиксированным соотношение между обоими типами запросов: на каждый запрос
на обновление данных обычно приходится в среднем около десятка запросов
на чтение. Со временем нагрузка растет, а значит растет и количество
операций записи в единицу времени, а сервер-то обрабатывает их всего
один, а затем он же еще и обеспечивает создание некоторого количества
копий на других серверах. Рано или поздно издержки операций репликации
данных станут быть настолько высоки, что этот процесс станет занимать
очень большую часть процессорного времени каждого сервера, а каждый
slave сможет обрабатывать лишь сравнительно небольшое количество
операций чтения, и, как следствие, каждый дополнительный slave-сервер
начнет увеличивать суммарную производительность лишь незначительно, тоже
занимаясь по большей части лишь поддержанием своих данных в соответствии
с "мастером".&lt;/p&gt;
&lt;p&gt;Временным решением этой проблемы, возможно, может стать замена
master-сервера на более производительный, но так или иначе не выйдет
бесконечно откладывать переход на следующий "уровень" развития системы
хранения данных: &lt;strong&gt;"sharding"&lt;/strong&gt;, которому я совсем недавно посвятил
&lt;a href="https://www.insight-it.ru/theory/2008/segmentirovanie-bazy-dannykh/"&gt;отдельный пост "Сегментирование баз данных"&lt;/a&gt;.
Так что позволю себе остановиться на нем лишь вкратце: идея заключается
в том, чтобы разделить все данные на части по какому-либо признаку и
хранить каждую часть на отдельном сервере или кластере, такую часть
данных в совокупности с системой хранения данных, в которой она
находится, и называют сегментом или &lt;em&gt;shard&lt;/em&gt;&amp;rsquo;ом. Такой подход позволяет
избежать издержек, связанных с реплицированием данных (или сократить их
во много раз), а значит и &lt;em&gt;существенно&lt;/em&gt; увеличить общую
производительность системы хранения данных. Но, к сожалению, переход к
этой схеме организации данных требует массу издержек другого рода. Так
как готового решения для ее реализации не существует, приходится
модифицировать логику приложения или добавлять дополнительную
"прослойку" между приложением и СУБД, причем все это чаще всего
реализуется силами разработчиков проекта. Готовые продукты способны лишь
облегчить их работу, предоставив некий каркас для построения основной
архитектуры системы хранения данных и ее взаимодействия с остальными
компонентами приложения.&lt;/p&gt;
&lt;p&gt;На этом этапе цепочка обычно заканчивается, так как сегментированные
базы данных могут горизонтально масштабироваться для того, чтобы в
полной мере удовлетворить потребности даже самых высоконагруженных
интернет-ресурсов. К месту было бы сказать пару слов и о собственно
самой структуре данных в рамках баз данных и организации доступа к ним,
но какие-либо решения сильно зависят от конкретного приложения и
реализации, так что позволю себе лишь дать пару общих рекомендаций:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;Денормализация&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Запросы, комбинирующие данные из нескольких таблиц, обычно при
прочих равных требуют большего процессорного времени для выполнения,
чем запрос, затрагивающий лишь одну таблицу. А производительность,
как уже упоминалось в начале повествования, чрезвычайно важна на
просторах Сети.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;Логическое разбиение данных&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Если какая-то часть данных всегда используется отдельно от основной
массы, то иногда имеет смысл выделить ее в отдельную независимую
систему хранения данных.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;Низкоуровневая оптимизация запросов&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Ведя и анализируя логи запросов, можно определить наиболее медленные
из них. Замена найденных запросов на более эффективные с той же
функциональностью может помочь более рационально использовать
вычислительные мощности.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;В этом разделе стоит упомянуть еще один, более специфический, тип
интернет-проектов. Такие проекты оперируют данными, не имеющими четко
формализованную структуру, в таких ситуациях использование реляционных
СУБД в качестве хранилища данных, мягко говоря, нецелесообразно. В этих
случаях обычно используют менее строгие базы данных, с более примитивной
функциональностью в плане обработки данных, но зато они способны
обрабатывать огромные объемы информации не придираясь к его качеству и
соответствию формату. В качестве основы для такого хранилища данных
может служить кластерная файловая система, а для анализа же данных в
таком случае используется механизм под названием
&lt;a href="/tag/mapreduce/"&gt;MapReduce&lt;/a&gt;, принцип его работы я расскажу лишь вкратце,
так как в полном своем масштабе он несколько выходит за рамки данного
повествования.&lt;/p&gt;
&lt;p&gt;Итак, мы имеем на входе некие произвольные данные в не факт что
правильно соблюденном формате. В результате нужно получить некое
итоговое значение или информацию. Согласно данному механизму практически
любой анализ данных можно провести в следующие два этапа:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;Map&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Основной целью данного этапа является представление произвольных
входных данных в виде промежуточных пар ключ-значение, имеющих
определенный смысл и формально оформленных. Результаты подвергаются
сортировке и группированию по ключу, а после чего передаются на
следующий этап.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;Reduce&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Полученные после &lt;strong&gt;map&lt;/strong&gt; значения используются для финального
вычисления требуемых итоговых данных.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Каждый этап каждого конкретного вычисления реализуется в виде
независимого мини-приложения. Такой подход позволяет практически
неограниченно распараллеливать вычисления на огромном количестве машин,
что позволяет в мгновения обрабатывать объемы практически произвольных
данных. Для этого достаточно лишь запустить эти приложения на каждом
доступном сервере одновременно, а затем собрать воедино все результаты.&lt;/p&gt;
&lt;p&gt;Примером готового каркаса для реализации работы с данными по такому
принципу служит opensource проект Apache Foundation под названием
&lt;a href="https://www.insight-it.ru/storage/2008/hadoop/"&gt;&lt;em&gt;Hadoop&lt;/em&gt;&lt;/a&gt;, о котором я уже неоднократно
рассказывал ранее, да и &lt;a href="https://www.insight-it.ru/goto/1a5b89d0/" rel="nofollow" target="_blank" title="http://ru.wikipedia.org/wiki/Hadoop"&gt;статейку в Википедию&lt;/a&gt; написал в свое время.&lt;/p&gt;
&lt;h3 id="vmesto-zakliucheniia"&gt;Вместо заключения&lt;/h3&gt;
&lt;p&gt;Если честно, мне с трудом верится, что я смог написать настолько
всеобъемлющий пост и сил на подведение итогов уже практически не
осталось. Хочется лишь сказать, что в разработке крупных проектов важна
каждая деталь, а неучтенная мелочь может стать причиной провала. Именно
по-этому в этом деле учиться стоит не на своих ошибках, а на чужих.&lt;/p&gt;
&lt;p&gt;Хоть может быть этот текст и выглядит как некое обобщение всех постов из
серии &lt;a href="https://www.insight-it.ru/highload/"&gt;"Архитектуры высоконагруженных систем"&lt;/a&gt;, но врядли он
станет финальной точкой, надеюсь мне &lt;a href="/feed/"&gt;найдется что сказать&lt;/a&gt; по
этой теме и в будущем, может быть однажды это будет основано и на личном
опыте, а не просто будет результатом переработки массы полученной мной
информации. Кто знает?...&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Mon, 12 May 2008 09:00:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-05-12:theory/2008/masshtabiruemye-veb-arkhitektury/</guid><category>online</category><category>архитектура</category><category>веб-приложение</category><category>веб-проект</category><category>веб-сервер</category><category>геораспределение</category><category>информационные технологии</category><category>кэширование</category><category>Масштабируемость</category><category>распределенные вычисления</category><category>сегментирование баз данных</category></item><item><title>hCard</title><link>https://www.insight-it.ru//theory/2008/hcard/</link><description>&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/7ed2e6a8/" rel="nofollow" target="_blank" title="http://microformats.org/wiki/hcard"&gt;hCard&lt;/a&gt; представляет собой
реализацию спецификации &lt;a href="https://www.insight-it.ru/goto/9d8165cb/" rel="nofollow" target="_blank" title="http://www.ietf.org/rfc/rfc2426.txt"&gt;RFC 2426&lt;/a&gt;
(более известной как vCard) в виде микроформата. Основной его целью
является предоставление стандарта оформления персональных данных на
просторах Сети, но помимо этого имеется возможность указания информации
об компаниях, организациях или местах.
&lt;!--more--&gt;
Как и любой другой микроформат, hCard реализуется без нарушения
стандартов XHTML с помощью атрибутов тэга &lt;code&gt;class&lt;/code&gt;, причем какие именно
тэги используются - не важно. Для оформления данных используя этот
микроформат достаточно лишь объявить какой-либо тэг hCard объектом с
помощью &lt;code&gt;class="vcard"&lt;/code&gt; и разместить внутри него все тэги,
обозначающие какое-либо свойство объекта. Большая часть информации,
предоставляемой в соответствии с этим микроформатом является
опциональной, единственным обязательным свойством является имя объекта -
&lt;code&gt;class="fn"&lt;/code&gt;. Помимо этого в атрибуте &lt;strong&gt;profile&lt;/strong&gt; тэга &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;
принято указывать адрес &lt;code&gt;http://www.w3.org/2006/03/hcard&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;В целом все свойства объектов hCard можно поделить на семь групп:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;идентификационные&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; различные варианты имен объекта.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;адресные&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; указания различных адресов, каким-либо образом ассоциирующихся с
объектом: место жительство, работы и тому подобные.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;телекоммуникационные&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; любые формы контактной информации: номера телефонов, факс, адреса
электронной почты и так далее.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;географические&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; месторасположение объекта.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;организационные&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; информация о должности и компании или организации, в которой
работает объект.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;уточняющие&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; любая дополнительная информация об объекте.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;безопасность&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; ограничение доступа к информации в hCard.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Значением каждого свойства является видимый пользователю текст,
получающийся в результате обработки документа браузером (или другим
парсером данных). Но стоит несколько остановиться на свойстве photo, так
как для него действуют несколько другие правила размещения значения:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;при использовании свойства photo в тэге &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;, значением
    является адрес из атрибута &lt;code&gt;href&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;в тэге &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, значением является само изображение, то есть
    значение атрибута &lt;code&gt;src&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;в &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt;, значением является атрибут &lt;code&gt;`data&lt;/code&gt;, то есть его
    источник данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Раз уж зашла речь об размещении значений свойств, то сразу хочется
сказать об небольшом исключении в виде тэга &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt;, где оно
задается в атрибуте &lt;code&gt;title&lt;/code&gt;, а внутри самого тэга - некое более
удобное для чтения людьми его представление.&lt;/p&gt;
&lt;p&gt;Если тэг, обозначенный любым свойством, содержит какую-либо информацию
помимо самого значения свойства, то для отделения релевантного контента
от лишней информации можно разместить внутри тэга свойства дочерние
объекты, обозначив их атрибутом &lt;code&gt;class="value"&lt;/code&gt;. Это даст понять
парсеру микроформата, что собрав воедино (методом конкатенации) все
значения помеченных таким образом объектов он сможет получить значение
исходного свойства. Описание получилось несколько запутанным, так что
лучше продемонстрировать этот принцип на примере, в котором значению
свойства &lt;strong&gt;fn&lt;/strong&gt; будет присвоено значение "Иван Блинков":&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"vcard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Иван &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;подпрыгнул три раза на месте,
    обернулся и увидел написанную на стене
    свою фамилию: &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Блинков&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;.
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Как не трудно заметить, значение свойства разбавлено массой ненужной
информации, но с помощью тэгов с атрибутом &lt;code&gt;class="value"&lt;/code&gt; мне удалось
выделить лишь важную информацию, не поменяв при этом внешний вид
документа. Парсер микроформатов, читая этот документ, соединит обе части
и получит в итоге как раз "Иван Блинков", что и будет соответствовать
желаемому имени объекта.&lt;/p&gt;
&lt;p&gt;Вы заметили в предыдущем примере пробел после моего имени? Он был
поставлен для того, чтобы при конкатенации составные части значения не
слились в одно слово "ИванБлинков", не самый удобный подход к решению
проблемы, но у него есть альтернатива в виде тэга &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt; (не
забываем про упомянутое чуть выше исключение):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"vcard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;abbr&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fn"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Иван Блинков"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Иван
  &lt;span class="nt"&gt;&amp;lt;/abbr&amp;gt;&lt;/span&gt;
  подпрыгнул три раза на месте,
  обернулся и увидел написанную на стене
  свою фамилию: Блинков.
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Общей информации на сегодня хватит, так что перейду к деталям
реализации.&lt;/p&gt;
&lt;h4&gt;Идентификационные свойства&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Свойство&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Описание&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;fn&lt;/td&gt;
&lt;td&gt;полное имя объекта &lt;em&gt;(formatted name)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;имя, используется для идентификации составных частей fn &lt;em&gt;(name)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nickname&lt;/td&gt;
&lt;td&gt;прозвище&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bday&lt;/td&gt;
&lt;td&gt;день рождения в формате &lt;strong&gt;YYYY-MM-DD&lt;/strong&gt; &lt;em&gt;(birthday)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;photo&lt;/td&gt;
&lt;td&gt;фотография&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Свойство &lt;strong&gt;fn&lt;/strong&gt; уже успели слегка обсудить, так что перейдем сразу к
&lt;strong&gt;n&lt;/strong&gt;. Как уже было сказано, используется он для детализации составных
частей полного имени объекта, для чего оно имеет ряд подсвойств,
используемых в дочерних элементах:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;given-name&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; имя.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;additional-name&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; отчество.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;family-name&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; фамилия.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;honorific-preffix&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; какой-либо префикс к имени, отображающий социальный статус
человек.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;honorific-suffix&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&amp;ndash; суффикс с тем же смыслом.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Выглядит это все примерно так, ничего сложного:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"vcard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"n"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"given-name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Иван&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"additional-name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Иванович&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"family-name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Блинков&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Адресные свойства&lt;/h4&gt;
&lt;p&gt;Адрес может быть указан в двух формах:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;adr&lt;/strong&gt; - структурированной (с указанием составных частей);&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;label&lt;/strong&gt; - не структурированной.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для структурированного адреса используются подсвойства по аналогии с
&lt;strong&gt;n&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Свойство&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Описание&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;post-office-box&lt;/td&gt;
&lt;td&gt;почтовый адрес&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;extended-address&lt;/td&gt;
&lt;td&gt;полный адрес (с номером подъезда, квартиры и т.д.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;street-address&lt;/td&gt;
&lt;td&gt;улица&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;locality&lt;/td&gt;
&lt;td&gt;город&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;region&lt;/td&gt;
&lt;td&gt;регион, штат или провинция&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;postal-code&lt;/td&gt;
&lt;td&gt;индекс&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;type&lt;/td&gt;
&lt;td&gt;тип адреса, то есть то, как он связан с исходным идивидом, должен принимать одно из значений: dom, parcel, home, work, pref&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;label&lt;/strong&gt; же используется просто для написания адреса по тому же
принципу, как если бы Вы писали его, например, на конверте традиционного
письма. Возможно использование подсвойства &lt;strong&gt;type&lt;/strong&gt; как и в &lt;strong&gt;adr&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;С телекоммуникационными свойствами все проще:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;телефон - &lt;strong&gt;tel&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;адрес электронной почты - &lt;strong&gt;email&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;почтовый клиент - &lt;strong&gt;mailer&lt;/strong&gt; (не понятно - и зачем он тут сдался?).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Телефонный номер может иметь тип (&lt;strong&gt;type&lt;/strong&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;home&lt;/strong&gt; - домашний&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;msg&lt;/strong&gt; - имеется автоответчик&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;work&lt;/strong&gt; - рабочий&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pref&lt;/strong&gt; - предпочтительный&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;voice&lt;/strong&gt; - голосовой&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fax&lt;/strong&gt; - факс&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cell&lt;/strong&gt; - мобильный aka сотовый&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;video&lt;/strong&gt; - для видеоконференций&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pager&lt;/strong&gt; - пэйджер&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;bbs&lt;/strong&gt; - bulletin board system&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;modem&lt;/strong&gt; - возможно использование модема&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;isdn&lt;/strong&gt; - integrated services digital network&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pcs&lt;/strong&gt; - personal communication service&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Географические свойства также не отличаются особой сложностью:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;tz&lt;/strong&gt; - временная зона&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;long&lt;/strong&gt; - широта&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;lat&lt;/strong&gt; - долгота&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;С ручным заполнением этих свойств могут возникнуть некоторые проблемы,
но при интеграции веб-приложения с сервисом вроде Google Earth - должно
быть вполне удобно.&lt;/p&gt;
&lt;p&gt;Свойства, описывающие индивида с точки зрения работы, немногочисленны:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;title&lt;/strong&gt; - должность&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;role&lt;/strong&gt; - роль&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;logo&lt;/strong&gt; - ссылка на логотип компании&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;agent&lt;/strong&gt; - указание представителя индивида, например секретаря,
    например в виде ссылки на его hCard&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;org&lt;/strong&gt; - название компании&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Дополнительные свойства:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;category&lt;/strong&gt; - категория, то есть чем по сути является данный hCard,
    например - визитка&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;note&lt;/strong&gt; - какие-либо замечания к остальным свойствам&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rev&lt;/strong&gt; - время последнего редактирования hCard, то есть время на
    которое данная информация является актуальной&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sort-string&lt;/strong&gt; - отмечает какая часть hCard (обычно часть имени),
    которая будет использована при сортировке списка из нескольких hCard&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sound&lt;/strong&gt; - адрес, указывающий на звуковой файл с правильным
    произношением имени индивида&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;url&lt;/strong&gt; - адрес персонального или корпоративного сайта&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;uid&lt;/strong&gt; - уникальный идентификационный номер в каком-либо
    специфицированном IANA формате (подсвойство &lt;strong&gt;type&lt;/strong&gt; указывает в
    каком именно)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для обеспечения ограничения доступа к данным из &lt;a href="/tag/hcard/"&gt;hCard&lt;/a&gt;
используется два свойства - &lt;strong&gt;class&lt;/strong&gt; и &lt;strong&gt;key&lt;/strong&gt;. &lt;strong&gt;class&lt;/strong&gt; определяет
уровень доступа по примерно тому же принципу, что и в &lt;a href="/tag/oop/"&gt;ООП&lt;/a&gt;:
&lt;em&gt;public&lt;/em&gt; или &lt;em&gt;confidentional&lt;/em&gt;. А свойство &lt;strong&gt;key&lt;/strong&gt; предоставляет
публичный ключ, для расшифровки данных с закрытым доступом.&lt;/p&gt;
&lt;p&gt;Хочется добавить, что благодаря своей структурированной архитектуре
данный микроформат может использоваться в более широком спектре случаев,
чем просто предоставление персональных данных, например, можно описывать
и просто организацию или какое-либо место. Те же самые принципы могут
быть использованы и при оформление персональных данных в формате
&lt;a href="/tag/xml/"&gt;XML&lt;/a&gt; - достаточно лишь использовать те же самые атрибуты
hCard для произвольных тэгов &lt;a href="/tag/xml/"&gt;XML&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;В заключение хочу сказать, что в качестве источников информации для
данной статьи были использованы &lt;a href="https://www.insight-it.ru/goto/7ed2e6a8/" rel="nofollow" target="_blank" title="http://microformats.org/wiki/hcard"&gt;официальная вики&lt;/a&gt; и &lt;a href="https://www.insight-it.ru/goto/1161c09e/" rel="nofollow" target="_blank" title="http://www.xfront.com/microformats/hCard.html"&gt;презентация от Robert Costello&lt;/a&gt;, а подписаться на &lt;a href="/feed/"&gt;&lt;strong&gt;RSS&lt;/strong&gt;&lt;/a&gt; можно вот &lt;a href="/feed/"&gt;&lt;strong&gt;ТУТ&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sun, 13 Apr 2008 22:51:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-04-13:theory/2008/hcard/</guid><category>hcard</category><category>online</category><category>XHTML</category><category>интернет</category><category>Микроформаты</category><category>персональная информация</category></item><item><title>Архитектура Digg</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-digg/</link><description>&lt;p&gt;Трафик, генерируемый более чем 1.2 миллионами пользователей
&lt;a href="https://www.insight-it.ru/goto/e072c5ff/" rel="nofollow" target="_blank" title="http://www.digg.com"&gt;Digg&lt;/a&gt;, знаменитых своей жаждой информации,
способен загнать любой невинный сайт за рамки его вычислительных
ресурсов и пропускной способности канала. Как же сам Digg справляется с
такой нагрузкой?
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="istochniki-informatsii"&gt;Источники информации&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Этот текст - перевод
&lt;a href="https://www.insight-it.ru/goto/83eb8e27/" rel="nofollow" target="_blank" title="http://highscalability.com/digg-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
Hoff&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/3c9da0db/" rel="nofollow" target="_blank" title="http://www.computerworld.com/action/article.do?command=viewArticleBasic&amp;amp;articleId=9017778"&gt;Как Digg.com использует LAMP для масштабирования&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/fa3d3949/" rel="nofollow" target="_blank" title="http://www.oreillynet.com/onlamp/blog/2006/04/digg_phps_scalability_and_perf.html"&gt;Масштабируемость и производительность PHP в Digg&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/mysql/"&gt;MySQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/linux/"&gt;Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/php/"&gt;PHP&lt;/a&gt;&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/apc/"&gt;APC PHP Accelerator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/memcached/"&gt;Memcached&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="statistika"&gt;Статистика&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Проект стартовал в конце 2004 года на одном сервере под управлением
    &lt;a href="/tag/linux/"&gt;Linux&lt;/a&gt; с использованием &lt;a href="/tag/apache/"&gt;Apache 1.3&lt;/a&gt;, &lt;a href="/tag/php/"&gt;PHP
    4&lt;/a&gt; и &lt;a href="/tag/mysql/"&gt;MySQL 4.0&lt;/a&gt; (со стандартной системой
    хранения данных - MyISAM).&lt;/li&gt;
&lt;li&gt;Более 1.2 миллиона пользователей.&lt;/li&gt;
&lt;li&gt;Более 200 миллионов просмотров страниц в месяц.&lt;/li&gt;
&lt;li&gt;100 серверов расположены в нескольких датацентрах, из них:
    &amp;ndash; 20 серверов баз данных;
    &amp;ndash; 30 веб-серверов;
    &amp;ndash; несколько поисковых серверов, использующих Lucene;
    &amp;ndash; остальные используются для обеспечения избыточности.&lt;/li&gt;
&lt;li&gt;30 GB данных.&lt;/li&gt;
&lt;li&gt;Ни одна из проблем, с которыми пришлось столкнуться проекту не была
    связана с &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt;, в основном они касались базы данных.&lt;/li&gt;
&lt;li&gt;Легковесная природа &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt; позволила переместить
    вычислительные работы из базы данных в приложение для улучшения
    производительности.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="chto-vnutri"&gt;Что внутри?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Балансировщик нагрузки равномерно распределяет запросы между
    &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt; серверами.&lt;/li&gt;
&lt;li&gt;MySQL используется по принципу master-slave:
    -&amp;nbsp; Сервера, обрабатывающие большое количество транзакций, используют
    движок InnoDB.
    -&amp;nbsp; Сервера, выполняющие аналитическую обработку данных в реальном
    времени, используют MyISAM.
    -&amp;nbsp; Снижения производительности при переходе с &lt;a href="/tag/mysql/"&gt;MySQL&lt;/a&gt; 4.1
    на версию 5 замечено не было.&lt;/li&gt;
&lt;li&gt;Для кэширования используется &lt;a href="/tag/memcached/"&gt;Memcached&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Используется сегментирование баз данных.&lt;/li&gt;
&lt;li&gt;Особенности использования Digg существенно облегчают процесс
    масштабирования. Большинство посетителей просто просматривают
    главную страницу и уходят. Это приводит к тому, что 98% запросов к
    базе данных являются операциями чтения. Такое соотношение операций
    чтения и записи позволяет не беспокоиться о комплексной работе по
    проектированию операций записи, что позволяет намного проще
    масштабировать проект.&lt;/li&gt;
&lt;li&gt;Возникали проблемы, связанные с системой хранения данных, которые
    сообщали, что данные уже записаны на диск, когда на самом деле это
    было не так. Контроллеры делали это для создания впечатления более
    высокой производительности. Но на практике это приводило лишь к
    проблемам с целостностью данных. Это достаточно распространенная
    проблема, которую порой не так уж просто решить, правда все зависит
    от используемого оборудования.&lt;/li&gt;
&lt;li&gt;Для облегчения нагрузки на базы данных используется кэширование и
    &lt;a href="/tag/apc/"&gt;APC PHP Accelerator&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;С использованием рабочих потоков &lt;a href="/tag/apache/"&gt;Apache2&lt;/a&gt;, FastCGI и
    &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt; акселератора возможно избежать необходимости каждый
    раз заново интерпретировать и компилировать PHP скрипты: скрипт
    компилируется только при первом обращении, что существенно ускоряет
    скорость его выполнения при последующих обращениях.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="podvodim-itogi"&gt;Подводим итоги&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Используйте возможность выбора движка для &lt;a href="/tag/mysql/"&gt;MySQL&lt;/a&gt;. Если
    Вам нужны транзакции - используйте InnoDB, если нет - MyISAM.
    Например, если на master сервере расположены транзакционные таблицы,
    то для slave серверов можно использовать и MyISAM.&lt;/li&gt;
&lt;li&gt;В определенный момент рост стал невозможен путем добавления
    дополнительной оперативной памяти, пришлось продолжать рост путем
    изменения архитектуры.&lt;/li&gt;
&lt;li&gt;Люди часто жалуются, что Digg медлителен. Скорее это вызвано их
    огромными &lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt; библиотеками, чем работой их
    серверной системы.&lt;/li&gt;
&lt;li&gt;Стоит тщательно выбирать какие именно приложения развертывать. Они
    приложили все усилия, чтобы не использовать приложения, требующие
    больших вычислительных мощностей. Очевидно, что Digg работает на
    совершенно стандартной &lt;a href="/tag/lamp/"&gt;LAMP&lt;/a&gt; архитектуре, но тем не
    менее реализована она достаточно интересно. У инженеров часто
    возникает желание реализовать какой-либо дополнительный функционал,
    но всегда стоит иметь ввиду, что они могут разрушить инфраструктуру,
    если она не сможет расти теми же темпами. Так что с этим стоит
    повременить до тех пор пока система сможет выдерживать все
    необходимые нагрузки. Это приводит к планированию ресурсов, особенно
    большое внимание этому аспекту уделяет &lt;a href="/tag/flickr/"&gt;Flickr&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Вам остается лишь догадываться, сможет ли &lt;a href="/tag/digg/"&gt;Digg&lt;/a&gt; удержать
    свои позиции, если и дальше будет ограничивать добавление новых
    возможностей, или уступит более активно развивающимся сервисам
    социальных закладок? Возможно если бы была возможность увеличивать
    масштабы более простыми методами, более быстрое добавление новых
    функций и возможностей позволило бы более эффективно конкурировать
    на этом рынке? С другой стороны, просто добавление новых
    возможностей может и не поменять ситуацию кардинальным образом.&lt;/li&gt;
&lt;li&gt;Основные проблемы с масштабируемостью и производительностью связаны
    с обработкой данных и в большинстве случаев они не зависят от
    используемого языка программирования. Вы столкнетесь с ними при
    работе с &lt;a href="/tag/java/"&gt;Java&lt;/a&gt;, &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt;, &lt;a href="/tag/ruby/"&gt;Ruby&lt;/a&gt;, или
    подставьте сюда Ваш любимый язык программирования.&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Tue, 01 Apr 2008 20:49:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-04-01:highload/2008/arkhitektura-digg/</guid><category>APC</category><category>Digg</category><category>LAMP</category><category>Linux</category><category>Lucene</category><category>Memcached</category><category>MySQL</category><category>online</category><category>PHP</category><category>архитектура</category><category>архитектура Digg</category><category>интернет</category></item><item><title>Архитектура Friends for Sale</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-friends-for-sale/</link><description>&lt;p&gt;&lt;img alt="Friends for Sale Logo" class="right" src="https://www.insight-it.ru/images/friends-for-sale.png" title="Friends for Sale"/&gt;
За три коротких месяца &lt;em&gt;&lt;a href="https://www.insight-it.ru/goto/616a7ee4/" rel="nofollow" target="_blank" title="http://www.facebook.com/apps/application.php?id=7019261521"&gt;Friend for Sale&lt;/a&gt;&lt;/em&gt;
(рейтинговая система в условиях рыночной экономики) попала в десятку
лучших приложений &lt;em&gt;Facebook&lt;/em&gt;, непринужденно обрабатывая 200 запросов в
секунду и демонстрируя шокирующее количество просмотров страниц, за
месяц достигающее 300 миллионов просмотров. Все это дело рук двух
разработчиков, работающих не полный рабочий день, которые смогли создать
успешное веб-приложение, имея в своем распоряжении лишь кластер из
дюжины серверов и &lt;a href="/tag/ruby-on-rails/"&gt;Ruby on Rails&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Как Friends for Sale масштабируется для того, чтобы обеспечить торговлю
всеми этими красивыми людьми? Как Вы думаете, сколько стоят Ваши друзья
на открытом рынке?
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="istochniki-informatsii"&gt;Источники информации&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Традиционная пара фраз, чтобы отдать должное
&lt;a href="https://www.insight-it.ru/goto/2ee4cfe9/" rel="nofollow" target="_blank" title="http://highscalability.com/friends-sale-architecture-300-million-page-view-month-facebook-ror-app"&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;автору&lt;/a&gt;. Продолжаем:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ответы на стандартный набор вопросов от Siqi Chen и Alexander Le,
    создателей Friends for Sale;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/2266d3f8/" rel="nofollow" target="_blank" title="http://highscalability.com/docs/EmergingTechSIGPresentation.pdf"&gt;Virality on Facebook&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/ruby-on-rails/"&gt;Ruby on Rails&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/centos/"&gt;CentOS&lt;/a&gt; (64 bit)&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/capistrano/"&gt;Capistrano&lt;/a&gt; - для обновлений и перезапусков
    серверов&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/memcached/"&gt;Memcached&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/mysql/"&gt;MySQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/nginx/"&gt;nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/starling/"&gt;Starling&lt;/a&gt; - распределенный сервер очередей&lt;/li&gt;
&lt;li&gt;Softlayer - хостинг&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/pingdom/"&gt;Pingdom&lt;/a&gt; - мониторинг&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/lvm/"&gt;LVM&lt;/a&gt; -   &lt;a href="https://www.insight-it.ru/goto/157d64d2/" rel="nofollow" target="_blank" title="http://magicmodels.rubyforge.org/magic_multi_connections/"&gt;Magic Multi-Connections Gem&lt;/a&gt; -
    разделение операций чтения и записи между серверами&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="statistika"&gt;Статистика&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Это Facebook приложение находится в десятке наиболее популярных;&lt;/li&gt;
&lt;li&gt;Около 600 тысяч активных пользователей;&lt;/li&gt;
&lt;li&gt;Полмиллиона уникальных посетителей ежедневно, и эта цифра неуклонно
    растет;&lt;/li&gt;
&lt;li&gt;Темпы роста проекта достигают 300% в месяц;&lt;/li&gt;
&lt;li&gt;200 запросов в секунду;&lt;/li&gt;
&lt;li&gt;5 TB трафика в месяц;&lt;/li&gt;
&lt;li&gt;Над проектом работают 2 разработчика и 1 админимтратор баз данных.&lt;/li&gt;
&lt;li&gt;4 сервера баз данных, 6 серверов приложений, 1 тестовый сервер и 1
    сервер для балансировки нагрузки:&lt;ul&gt;
&lt;li&gt;Каждый из серверов приложений содержит 4 ядра и 8 GB оперативной
памяти.&lt;/li&gt;
&lt;li&gt;На каждом из них работает 16 сервисов &lt;a href="/tag/mongrel/"&gt;mongrel&lt;/a&gt; (в
сумме - 96).&lt;/li&gt;
&lt;li&gt;4 GB оперативной памяти на каждом из них отведено под
&lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Сервера баз данных имеют более серьезное оборудование: при тех же
4-х ядрах, они имеют 32 GB оперативной памяти и RAID 10 массив из
четырех 15000rpm SCSI дисков, работающих в режиме "master/slave".&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="davaite-znakomitsia"&gt;Давайте знакомиться&lt;/h3&gt;
&lt;h4&gt;Для чего нужна ваша система?&lt;/h4&gt;
&lt;p&gt;Наша система разработана в качестве платформы для нашего Facebook
приложения, Friends for Sale.
В целом оно представляет собой аналог рейтинговой системы
&lt;a href="https://www.insight-it.ru/goto/d7a8b770/" rel="nofollow" target="_blank" title="http://www.hotornot.com/"&gt;Hot-or-Not&lt;/a&gt; с некоторым добавлением рыночной
экономики. В момент проведения интервью это приложение было на 10-м
месте по популярности среди приложений Facebook.&lt;/p&gt;
&lt;p&gt;Описание этого приложения на самом Facebook гласит:&lt;/p&gt;
&lt;div class="card blue lighten-1"&gt;
&lt;div class="card-content white-text"&gt;
Покупайте и продавайте своих друзей как питомцев! Вы можете научить их
толкаться, отправлять подарки или просто представлять Вас в выгодном
свете.

Зарабатывайте как практичный инвестор в питомцев или как популярный
товар!
&lt;/div&gt;
&lt;/div&gt;
&lt;h4&gt;Почему вы решили построить эту систему?&lt;/h4&gt;
&lt;p&gt;Мы разработали ее скорее как эксперимент для того, чтобы проверить
удалось ли нам понять концепции и измерения вирусного эффекта в рамках
Facebook. Мне кажется нам это удалось. :)&lt;/p&gt;
&lt;h4&gt;С какими конкретными сложными задачами, связанными с дизайном, архитектурой или реализацией системы, вам пришлось столкнуться при построении системы?&lt;/h4&gt;
&lt;p&gt;Как и в любом Facebook приложении, каждый запрос является динамическим,
так что кэширование страниц невозможно. Так как приложение является
интерактивным, со множеством операций записи, определенные трудности
вызвало масштабирование базы данных.&lt;/p&gt;
&lt;h4&gt;Каковы были ваши&lt;/h4&gt;
&lt;p&gt;действия, направленные для решения этих задач?&lt;/p&gt;
&lt;p&gt;С самого начала мы активно использовали &lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt; -
для перезагрузки страницы совсем не требуется выполнение SQL запросов. В
основном мы использовали кэширование фрагментов Rails с индивидуальной
логикой актуальности.&lt;/p&gt;
&lt;h4&gt;Как вы оцениваете размеры вашей системы?&lt;/h4&gt;
&lt;p&gt;Вчера статистика показала более полумиллиона уникальных посетителей, и
эта цифра неуклонно растет.
За этот месяц было зарегистрировано более 300 миллионов просмотров
страниц.&lt;/p&gt;
&lt;h4&gt;Каковы показатели использования пропускной способности интернет-канала?&lt;/h4&gt;
&lt;p&gt;В прошлом месяце было потрачено 3 терабайта трафика, но в этом месяце
ожидается цифра не меньше 5 терабайт. Эти цифры состоят по большей части
из XHTML / CSS и нескольких небольших иконок.&lt;/p&gt;
&lt;h4&gt;Как много документов используется в системе? Сколько изображений? Какой объем данных?&lt;/h4&gt;
&lt;p&gt;По большому счету у нас нет уникальных документов... но зато у нас есть
около 10 миллионов профилей пользователей.
Единственными используемыми изображениями являются несколько
статических иконок.&lt;/p&gt;
&lt;h4&gt;Как вы оцениваете темпы роста вашей системы?&lt;/h4&gt;
&lt;p&gt;Месяц назад за сутки просматривалось около трех миллионов страниц, на
данный момент эта цифра достигла 10 миллионов в сутки. Из чего можно
сделать вывод, что ориентировочные темпы роста проекта составляют 300% в
месяц. Если говорить о ежесекундной нагрузке, то на данный момент она
составляет около 200 запросов в секунду.&lt;/p&gt;
&lt;h4&gt;Какая часть посетителей платит вам за участие в вашем проекте?&lt;/h4&gt;
&lt;p&gt;Он абсолютно бесплатен для пользователей.&lt;/p&gt;
&lt;h4&gt;Каковы показатели "текучести" пользователей?&lt;/h4&gt;
&lt;p&gt;В среднем около 1% в сутки, с ежедневным ростом в 3% от этой цифры, если
говорить в терминах новых установок .&lt;/p&gt;
&lt;h4&gt;Как много учетных записей активно принимали участие в проекте за последний месяц?&lt;/h4&gt;
&lt;p&gt;По данным &lt;a href="/tag/google/"&gt;Google&lt;/a&gt; за последний месяц проект посетил 2.1
миллион уникальных пользоывтелей.&lt;/p&gt;
&lt;h4&gt;Какова архитектура вашей системы?&lt;/h4&gt;
&lt;p&gt;Она представляет собой относительно стандартный Rails кластер. В
качестве интерфейса между запросами пользователей и серверами приложений
используется proxy балансировщик нагрузки, который перенаправляет
запросы напрямую шести четырехядерным серверам приложений. На каждом
сервере приложений запущено 16 &lt;a href="/tag/mongrel/"&gt;mongrel&lt;/a&gt;'ов, что в сумме
дает 96. Балансировщик нагрузки перенаправляет запросы напрямую на порты
серверов &lt;a href="/tag/mongrel/"&gt;mongrel&lt;/a&gt;. В дополнение к этому на каждом сервере
приложений выделено 4 GB оперативной памяти под
&lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt;, а также работает локальный сервер
распределенного менеджера очередей &lt;a href="/tag/starling/"&gt;Starling&lt;/a&gt; и несколько
менее важных фоновых процессов.&lt;/p&gt;
&lt;p&gt;&lt;a href="/tag/subd/"&gt;СУБД&lt;/a&gt; работает на двух серверах (четыре ядра, 32 GB
оперативной памяти, четыре 15000rpm SCSI диска в RAID 10) в режиме
"master/slave". Для организации распределения операций чтения и записи
между серверами используется &lt;a href="https://www.insight-it.ru/goto/157d64d2/" rel="nofollow" target="_blank" title="http://magicmodels.rubyforge.org/magic_multi_connections/"&gt;Magic Multi-Connections Gem&lt;/a&gt; от Dr
Nic.&lt;/p&gt;
&lt;p&gt;На данный момент ведется работа над добавлением дополнительных серверов,
работающих в роли "slave", для обеспечения более эффективного
распределения нагрузки, избыточности и политик хранения запасных копий
данных. Помимо этого нам помогают Percona (ребята из
mysqlperformanceblog) с удаленной работой над архитектурой базы данных.&lt;/p&gt;
&lt;p&gt;Нашим хостинг-провайдером является Softlayer - он просто фантастический.
Основной проблемой был тот факт, что их балансировщик нагрузки не
справлялся со своей задачей ... поначалу у нас возникала масса проблем,
связанных с задержками и повисшими соединениями. Переход на отдельный
сервер с запущенным только nginx в режиме proxy балансировщика нагрузки
позволила решить все проблемы.&lt;/p&gt;
&lt;h4&gt;Каким образом планируется масштабировать архитектуру вашего проекта?&lt;/h4&gt;
&lt;p&gt;Каких-то конкретных планов нет. На уровне приложения система не
использует какие-либо общие ресурсы, так что все достаточно тривиально.
На уровне баз данных на данный момент все еще используется один сервер в
роли "master", но мы стараемся отложить неизбежный переход к
сегментированной базе данных на как можно более длительный срок. На
данный момент базы данных масштабируются вертикально, но со временем,
надеюсь, мы сможем от этого избавиться.&lt;/p&gt;
&lt;h4&gt;Назовите самые интересные уникальные факты о вашем проекте?&lt;/h4&gt;
&lt;p&gt;Я могу назвать:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ни один из двух разработчиков ранее не имел опыта в крупномасштабных
    разработках на основе &lt;a href="/tag/rails/"&gt;Rails&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Наша траектория роста проекта достаточно редка в истории разработок
    с использованием &lt;a href="/tag/rails/"&gt;Rails&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;У нас практически не было возможностей для кэширования статических
    страниц - каждый запрос страницы приходилось обрабатывать
    &lt;a href="/tag/rails/"&gt;Rails&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Чему вам удалось научиться? Каков залог вашего успеха? Чего бы вам хотелось сделать по-другому в прошлом, если бы была такая возможность? Что бы вы оставили как есть?&lt;/h4&gt;
&lt;p&gt;Отличные хостинг, оборудование и архитектура БД являются очень важными
факторами. Мы привыкли пользоваться услугами хостинга Railsmachine,
который честно говоря является отличным провайдером shared хостинга, но
со временем они потеряли возможность выдерживать необходимую нагрузку. В
итоге почти месяц мы были едва способны отвечать на запросы браузеров
из-за проблем с оборудованием, хотя последующий переход на Softlayer
занял всего два часа. Стоит заранее выбирать качественный хостинг, если
планируется масштабирование проекта, смена хостинг-провайдера - не очень
веселое занятие.&lt;/p&gt;
&lt;p&gt;Основным выводом, который нам удалось сделать, является тот факт, что
причиной проблемы с масштабированием практически всегда является база
данных. Все без исключений проблемы с производительностью в итоге
сводились к серверу баз данных, конфигурации СУБД, эффективности
запросов или решению вопроса насчет необходимости использования
индексов.&lt;/p&gt;
&lt;p&gt;Определенно нам нужен был более качественный хостинг намного раньше.&lt;/p&gt;
&lt;p&gt;Мы определенно не сменим наш framework - &lt;a href="/tag/rails/"&gt;Rails&lt;/a&gt; был
незаменим при быстрой разработке приложения, нам удалось доказать, что
для масштабирования проекта на &lt;a href="/tag/ror/"&gt;RoR&lt;/a&gt; достаточно двух парней,
абсолютно не имеющих опыта в этом.&lt;/p&gt;
&lt;h4&gt;Кто входит в состав вашей команды?&lt;/h4&gt;
&lt;p&gt;У нас есть два разработчика, включая меня. Помимо этого недавно мы
начали пользоваться услугами помощи с DBA, о которой уже упоминалось.&lt;/p&gt;
&lt;h4&gt;Сколько всего людей участвует в проекте?&lt;/h4&gt;
&lt;p&gt;В технической части - два разработчика и один администратор баз данных,
работающий на контрактной основе.&lt;/p&gt;
&lt;h4&gt;Где они расположены с географической точки зрения?&lt;/h4&gt;
&lt;p&gt;Все участники проекта живут в районе SOMA, San Francisco.&lt;/p&gt;
&lt;h4&gt;Каковы обязанности каждого из участников проекта?&lt;/h4&gt;
&lt;p&gt;Оба разработчика проекта по совместительству являются и его создателями.
Поначалу я (Siqi) был ответственным за дизайн и разработку
пользовательского интерфейса, но так как у меня был некоторый опыт с
развертыванием систем я взял на себя и разработку управления сетевыми
операциями и развертывания. Мой коллега Alex был ответственным за
большую часть &lt;a href="/tag/rails/"&gt;Rails&lt;/a&gt; кода, вся логика приложения - его рук
дело.&lt;/p&gt;
&lt;p&gt;На данный момент я по большей части занимаюсь более техническими
моментами, такими как оптимизация сетевых операций и работы и репликации
&lt;a href="/tag/mysql/"&gt;MySQL&lt;/a&gt;. С трудом получается вернуться к работе над
пользовательским интерфейсом - к тому, что мне по-настоящему нравится.
Но это был опыт, который явно стоило получить, так что я стараюсь
извлекать максимум выгоды из этого занятия.&lt;/p&gt;
&lt;h4&gt;У вас есть какая-то определенная философия менеджмента?&lt;/h4&gt;
&lt;p&gt;Да - найти самых умелых и сообразительных людей, сделать им наилучшее
возможное предложение и убраться с их пути. Самые лучшие менеджеры
должны уметь НЕ МЕШАТЬ работникам, так что я стараюсь максимально этому
следовать при работе с другими участниками проекта. Но, к сожалению, мне
удается это далеко не всегда.&lt;/p&gt;
&lt;h4&gt;Если ваша команда работает раздельно, как вам удается координировать свою работу?&lt;/h4&gt;
&lt;p&gt;Нам стоило бы задуматься об использования каких-либо эффективных средств
общения. Мне кажется, что использование удаленной работа / outsourcing'а
является по-настоящему сложной задачей - я предпочитаю обходиться без
этого в разработке основы системы. Для системного администрирования или
разработки архитектуры БД это было бы более оправданно.&lt;/p&gt;
&lt;h3 id="chto-vy-ispolzuete-dlia-razrabotki"&gt;Что вы используете для разработки?&lt;/h3&gt;
&lt;p&gt;Мы используем &lt;a href="/tag/rails/"&gt;Rails&lt;/a&gt; с несколькими plug-in'ами, самыми
важными являются cache-fu от Cris Wanstrath и magic multi connections от
Dr Nic. В качестве текстового редактора я предпочитаю vim с плагином
rails.vim.&lt;/p&gt;
&lt;h4&gt;Какие языки программирования используются?&lt;/h4&gt;
&lt;p&gt;&lt;a href="/tag/ruby-on-rails/"&gt;Ruby on Rails&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Сколько используется серверов?&lt;/h4&gt;
&lt;p&gt;На данный момент используется кластер из 12 серверов.&lt;/p&gt;
&lt;h4&gt;Как они используются?&lt;/h4&gt;
&lt;p&gt;4 сервера баз данных, 6 серверов приложений, 1 тестовый сервер и 1
сервер для балансировки нагрузки.&lt;/p&gt;
&lt;h4&gt;Кто их предоставляет?&lt;/h4&gt;
&lt;p&gt;Мы заказываем их у Softlayer - до подключения их к системе проходит
порой менее четырех часов, что очень неплохо.&lt;/p&gt;
&lt;h4&gt;Какая операционная система используется?&lt;/h4&gt;
&lt;p&gt;CentOS 5 (64 бит)&lt;/p&gt;
&lt;h4&gt;Какой http сервер используется?&lt;/h4&gt;
&lt;p&gt;nginx&lt;/p&gt;
&lt;h4&gt;Какая СУБД используется?&lt;/h4&gt;
&lt;p&gt;MySQL 5.1&lt;/p&gt;
&lt;h4&gt;Вы используете обратную proxy?&lt;/h4&gt;
&lt;p&gt;Мы просто используем встроенный в nginx proxy балансировщик нагрузки.&lt;/p&gt;
&lt;h4&gt;Как вы развертываете вышу систему в датацентре?&lt;/h4&gt;
&lt;p&gt;Мы используем хостинг выделенных серверов, Softlayer.&lt;/p&gt;
&lt;h4&gt;Какова ваша стратегия хранения данных?&lt;/h4&gt;
&lt;p&gt;Мы используем резервное копирование NAS помимо внутренних SCSI RAID
массивов.&lt;/p&gt;
&lt;h4&gt;Какой объем дискового пространства вам доступен?&lt;/h4&gt;
&lt;p&gt;На всех серверах в сумме около 5 TB.&lt;/p&gt;
&lt;h4&gt;Как вы наращиваете объем дискового пространства?&lt;/h4&gt;
&lt;p&gt;Спонтанно. Мы еще не выполнили каких-либо исследований в планировании
дискового пространство, но это было явно зря не сделано.&lt;/p&gt;
&lt;h4&gt;Вы используйте какой-либо сервис хранения информации?&lt;/h4&gt;
&lt;p&gt;Нет.&lt;/p&gt;
&lt;h4&gt;Вы используете виртуализацию хранимых данных?&lt;/h4&gt;
&lt;p&gt;Нет.&lt;/p&gt;
&lt;h4&gt;Как организована работа с сессиями?&lt;/h4&gt;
&lt;p&gt;На данный момент она поручена СУБД, но передача их обслуживания напрямую
memcached - достаточно несложная задача.&lt;/p&gt;
&lt;h4&gt;Как организована архитектура вашей БД?&lt;/h4&gt;
&lt;p&gt;На данный момент - "master/slave". Мы осуществляем переход к нескольким
"slave" с proxy балансировщиком нагрузки для режима "только для чтения".&lt;/p&gt;
&lt;h4&gt;Как организована балансировка нагрузки?&lt;/h4&gt;
&lt;p&gt;На программном уровне средствами nginx.&lt;/p&gt;
&lt;h4&gt;Какой framework / AJAX библиотеку вы используете?&lt;/h4&gt;
&lt;p&gt;Rails.&lt;/p&gt;
&lt;h4&gt;Какие средства распределенного управления задачами вы используете?&lt;/h4&gt;
&lt;p&gt;&lt;a href="/tag/starling/"&gt;Starling&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Как вы управляете рекламой в проекте?&lt;/h4&gt;
&lt;p&gt;Мы участвуем в нескольких рекламных сетях. Мы оцениваем эффективность
каждой рекламной сети с помощью eCPM на уровне приложения.&lt;/p&gt;
&lt;h4&gt;Имеете ли вы стандартную API на вашем сайте?&lt;/h4&gt;
&lt;p&gt;Нет.&lt;/p&gt;
&lt;h4&gt;Сколько человек в вашей команде?&lt;/h4&gt;
&lt;p&gt;2 разработчика.&lt;/p&gt;
&lt;h4&gt;Какими наборами способностей обладают участники вашей команды?&lt;/h4&gt;
&lt;p&gt;Я: дизайн пользовательского интерфейса, разработка, ограниченные знания
в Rails, оптимизация MySQL, развертывание Rails.&lt;/p&gt;
&lt;p&gt;Alex: разработка логики приложения, дизайн пользовательского интерфейса,
программная инженерия в целом.&lt;/p&gt;
&lt;h4&gt;Какие средства разработки вы используете?&lt;/h4&gt;
&lt;p&gt;Alex работает в OS X, а я предпочитаю Ubuntu. Для контроля за версиями
используется &lt;a href="/tag/svn/"&gt;SVN&lt;/a&gt;. В качестве текстового редактора я
использую VIM, а Alex - TextMate.&lt;/p&gt;
&lt;h4&gt;Как проходит процесс разработки?&lt;/h4&gt;
&lt;p&gt;На логическом уровне все упирается в тесты, мы проводим их достаточно
экстенсивно. На уровне приложения все ограничивается быстрыми итерациями
и не менее быстры тестированием.&lt;/p&gt;
&lt;h4&gt;Какова ваша стратегия кэширования объектов и контента?&lt;/h4&gt;
&lt;p&gt;Мы используем &lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt; без TTL и просто вручную
очищаем кэш при необходимости.&lt;/p&gt;
&lt;h4&gt;Как происходит кэширование на клиентской стороне?&lt;/h4&gt;
&lt;p&gt;Никак.&lt;/p&gt;
&lt;h4&gt;Как вы проверяете глобальную доступность и моделируете производительность для конечных пользователей?&lt;/h4&gt;
&lt;p&gt;Мы используем &lt;a href="/tag/pingdom/"&gt;Pingdom&lt;/a&gt; для внешнего мониторинга за
сайтом - они отлично справляются.&lt;/p&gt;
&lt;h4&gt;Как вы проверяете работоспособность ваших серверов и сетей?&lt;/h4&gt;
&lt;p&gt;На данный момент мы полагаемся на внешний мониторинг и ping мониторинг
от Softlayer. В перспективе мы рассматриваем FiveRuns как возможное
решение для мониторинга серверов.&lt;/p&gt;
&lt;h4&gt;Как вы строите на графиках или диаграммах сетевую и серверную статистику, а также тенденции?&lt;/h4&gt;
&lt;p&gt;Мы не занимаемся этим.&lt;/p&gt;
&lt;h4&gt;Как вы тестируете систему?&lt;/h4&gt;
&lt;p&gt;Сначала мы разворачиваем ее на тестовом сервере и проводим несколько
тестов, после чего разворачиваем систему уже на серверах приложений.&lt;/p&gt;
&lt;h4&gt;Как вы анализируете производительность?&lt;/h4&gt;
&lt;p&gt;Мы отслеживаем каждый SQL-запрос в процессе разработки, это позволяет
нам убедиться, что не выполняются никакие ненужные запросы или создание
экземпляра модели. Помимо этого мы не выполняем каких-либо тестов на
производительность.&lt;/p&gt;
&lt;h4&gt;Как вы обеспечиваете безопасность?&lt;/h4&gt;
&lt;p&gt;Тщательно.&lt;/p&gt;
&lt;h4&gt;Как вы решаете какие возможности добавить или оставить?&lt;/h4&gt;
&lt;p&gt;Решения основываются на отзывах пользователей и критическом взгляде на
них. Мы верим в простоту, так что нам приходится как следует все
взвесить перед добавлением каких-либо существенных возможностей.&lt;/p&gt;
&lt;h4&gt;Как вы реализуете веб-аналитику?&lt;/h4&gt;
&lt;p&gt;Мы используем собственную систему оценок для оптимизации вирусного
эффекта, но помимо этого пользуемся и услугами &lt;a href="https://www.insight-it.ru/goto/d303d8e3/" rel="nofollow" target="_blank" title="http://www.google.com/analytics"&gt;Google
Analytics&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Используете ли вы A/B тестирование?&lt;/h4&gt;
&lt;p&gt;Да, время от времени мы используем их для тонкой настройки аспектов
дизайна для того, чтобы оптимизировать его под вирусный эффект.&lt;/p&gt;
&lt;h4&gt;Как вы выполняете резервное копирование и восстановление?&lt;/h4&gt;
&lt;p&gt;Мы используем LVM для создания ежедневных и еженедельных инкрементальных
резервных копий.&lt;/p&gt;
&lt;h4&gt;Как выполняются обновления оборудования и программного обеспечения?&lt;/h4&gt;
&lt;p&gt;На данный момент мы делаем это вручную, за исключением развертывания
&lt;a href="/tag/rails/"&gt;Rails&lt;/a&gt; приложения. Для обновления и перезапуска серверов
приложений мы используем &lt;a href="/tag/capistrano/"&gt;Capistrano&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Как вы выполняете глобальные изменения в структуре базы данных при обновлениях?&lt;/h4&gt;
&lt;p&gt;Обычно мы начинаем переход с второстепенных серверах баз данных, а затем
просто переключаем основные.&lt;/p&gt;
&lt;h4&gt;Каковы ваши планы насчет защиты от сбоев и развития бизнеса?&lt;/h4&gt;
&lt;p&gt;Не самым лучшим образом...&lt;/p&gt;
&lt;h4&gt;Есть ли у вас отдельная операционная команда, работающая над сайтом?&lt;/h4&gt;
&lt;p&gt;Было бы неплохо, но нет :)&lt;/p&gt;
&lt;h4&gt;Используете ли вы &lt;abbr title="Content Delivery Network"&gt;CDN&lt;/abbr&gt;? Если да, то какую и для каких целей?&lt;/h4&gt;
&lt;p&gt;Нет.&lt;/p&gt;
&lt;h4&gt;Как выглядит модель ваших доходов?&lt;/h4&gt;
&lt;p&gt;&lt;abbr title="Costs per thousand impressions"&gt;CPM&lt;/abbr&gt;: больше просмотров страниц - больше денег. Помимо этого у нас бывают прямые
поощрительные предложения через нашу виртуальную валюту.&lt;/p&gt;
&lt;h4&gt;Как вы продвигаете ваш продукт?&lt;/h4&gt;
&lt;p&gt;Это же социальная сеть. Мы просто используем вирусный эффект для
поддержания роста проекта.&lt;/p&gt;
&lt;h4&gt;Используете ли вы какие-либо особенно интересные технологии или алгоритмы?&lt;/h4&gt;
&lt;p&gt;Я думаю Ruby запросто мог бы подойти под это определение, но на самом
деле нет - мы не проводим научных исследований, мы просто стараемся быть
полезными для посетителей.&lt;/p&gt;
&lt;h4&gt;Храните ли вы изображения в базе данных?&lt;/h4&gt;
&lt;p&gt;Нет, это бы была не самая лучшая идея.&lt;/p&gt;
&lt;h4&gt;Как много работы над организацией взаимодействия с пользователями приходится выполнять?&lt;/h4&gt;
&lt;p&gt;Я бы сказал, что никакой, если вам не приходилось раньше масштабировать
что-либо, и достаточно много, если приходилось. Достаточно сложно
сказать что именно станет проблемой до тех пор, пока на самом деле с
ними не столкнешься. Как только ты пройдешь через это, у тебя будет
достаточно знаний, чтобы осознанно проводить какую-либо работу в этом
направлении.&lt;/p&gt;
&lt;h4&gt;Приходилось ли вам сталкиваться с какими-либо сюрпризами, положительными или отрицательными?&lt;/h4&gt;
&lt;p&gt;Было удивительно, насколько ненадежным может оказаться поставщик
оборудования, и как может отличаться уровень технической поддержки
одного хостинг-провайдера по сравнению с другим. Одной из основных
вещей, которая вам понадобится при масштабировании системы - хостинг,
способный поддерживать ваши потребности.&lt;/p&gt;
&lt;p&gt;С другой стороны, было удивительно насколько далеко смогла наз завести
архитектура с одним "master" и несколькими "slave" на самом обыкновенном
оборудовании. Я думаю, что даже миллиард просмотров страниц в месяц
достижим при таком подходе к базе данных.&lt;/p&gt;
&lt;h4&gt;Как ваша система эволюционирует для соответствия новым требованиям к масштабируемости?&lt;/h4&gt;
&lt;p&gt;По большому счету она этого не делает, мы просто исправляем узкие места
в системе и смотрим что же будет дальше.&lt;/p&gt;
&lt;h4&gt;Кем вы восхищаетесь?&lt;/h4&gt;
&lt;p&gt;Brad Fitzpatrick за изобретение memcache, а также каждым, кому успешно
удалось горизонтально масштабировать свой проект.&lt;/p&gt;
&lt;h4&gt;Каковы ваши планы по изменению архитектуры в будущем?&lt;/h4&gt;
&lt;p&gt;Скоро предется переходить к сегментированной по пользователям базе
данных, так как скоро мы достигнем пределов базы данных по операциям
записи и размерам.&lt;/p&gt;
&lt;h3 id="ikh-mysli-o-virusnom-effekte-facebook"&gt;Их мысли о вирусном эффекте Facebook&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Facebook моделирует социальную сеть в цифровой форме максимально
    точно и полно, по крайней мере насколько это возможно.&lt;/li&gt;
&lt;li&gt;Построение социальной сети более важно, чем возможности,
    предоставляемые пользователям.&lt;/li&gt;
&lt;li&gt;Facebook позволяет быстро распространять новые приложения через
    социальную сеть.&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;Friends for Sale - социальный проект, так как предоставляет
    возможность торговать своей частью социального графа.&lt;/li&gt;
&lt;li&gt;Он затягивает, так как в основе лежит в какой-то степени сумасшедшая
    идея, ненавязчивая, слегка флиртующая, и немного циничная.&lt;/li&gt;
&lt;li&gt;Он универсальный, так как все люди в какой-то степени самовлюбленны,
    знают себе цену, и хотят флиртовать с "горячими" людьми.&lt;/li&gt;
&lt;li&gt;Каждая часть приложения является потенциальной для вовлечения новых
    пользователей.&lt;/li&gt;
&lt;li&gt;Каждый пользователь в среднем приводит 1.4 новых, что является
    залогом экспонентациального роста.&lt;/li&gt;
&lt;li&gt;Для каждого нового пользователя отслеживается количество
    приглашений, нотификаций, записей на "стене", кликов в профиле и
    других факторов.&lt;/li&gt;
&lt;li&gt;Для каждого канала поступления новых пользователей вычисляются
    проценты нажавших, успешно вовлеченных и выходов из проекта.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="podvodim-itogi"&gt;Подводим итоги&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;На Facebook требуется масштабирование с самого начала. Дорога до
    миллиона просмотров страниц в сутки заняла 4 недели.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/ruby-on-rails/"&gt;Ruby on Rails&lt;/a&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;Социальная сеть - это реальность. Количество новых пользователей в
    хорошо реализованном Facebook приложении на самом деле ошеломляет.&lt;/li&gt;
&lt;li&gt;Большая часть проблем с производительностью в итоге сводится к базе
    данных. Лишний раз обратите внимание на конфигурацию СУБД, запросы и
    использование индексов.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Люди до сих пор пользуются Vi!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Mon, 17 Mar 2008 21:44:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-03-17:highload/2008/arkhitektura-friends-for-sale/</guid><category>Capistrano</category><category>CentOS</category><category>Facebook</category><category>Friends for Sale</category><category>LVM</category><category>Memcached</category><category>mongrel</category><category>MySQL</category><category>nginx</category><category>online</category><category>Pingdom</category><category>Rails</category><category>RoR</category><category>Ruby on Rails</category><category>Starling</category><category>SVN</category><category>архитектура</category><category>интернет</category><category>Масштабируемость</category><category>социальные сети</category></item><item><title>Архитектура Amazon</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-amazon/</link><description>&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/300f3b10/" rel="nofollow" target="_blank" title="http://amazon.com"&gt;Amazon&lt;/a&gt; вырос из крошечной книжной лавки в один из
крупнейших магазинов вселенной. Они добились этого благодаря их
инновационному подходу к обзорам, рекомендациям и оценке продукции.-more--&amp;gt;&lt;/p&gt;
&lt;h3 id="istochniki-informatsii"&gt;Источники информации&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Как и &lt;a href="https://www.insight-it.ru/highload/"&gt;многие статьи&lt;/a&gt; об архитектурах высоконагруженных
систем на этом блоге, эта запись представляет собой перевод
&lt;a href="https://www.insight-it.ru/goto/59bb645b/" rel="nofollow" target="_blank" title="http://highscalability.com/amazon-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 Hoff&lt;/a&gt;.
Источниками информации для оригинала послужили:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/292cd03b/" rel="nofollow" target="_blank" title="http://glinden.blogspot.com/2006/05/early-amazon-end.html"&gt;Ранний Amazon&lt;/a&gt;
    от Greg Linden&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/7a5f17fb/" rel="nofollow" target="_blank" title="http://news.com.com/2100-1001-275155.html"&gt;Как Linux позволил Amazon сэкономить миллионы&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/de1af2aa/" rel="nofollow" target="_blank" title="http://www.se-radio.net/index.php?post_id=157593"&gt;Интервью с Werner Vogels'ом&lt;/a&gt; -
    техническим директором Amazon&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/a27efde/" rel="nofollow" target="_blank" title="http://www.webperformancematters.com/journal/2007/8/21/asynchronous-architectures-4.html"&gt;Асинхронные архитектуры&lt;/a&gt; -
    краткий пересказ речи Werner Vogels'а от Cris Loosley&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/5439ba1f/" rel="nofollow" target="_blank" title="http://www.acmqueue.com/modules.php?name=Content&amp;amp;pa=showpage&amp;amp;pid=388"&gt;Познание технологической платформы Amazon&lt;/a&gt; -
    диалог с Werner Vogels&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/bf438042/" rel="nofollow" target="_blank" title="http://www.allthingsdistributed.com/"&gt;Блог Werner Vogels'а&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/oracle/"&gt;Oracle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/c/"&gt;C++&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/perl/"&gt;Perl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/mason/"&gt;Mason&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/jboss/"&gt;Jboss&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/servlet/"&gt;Сервлеты&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="statistika"&gt;Статистика&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Более чем 55 миллионов учетных записей активных покупателей.&lt;/li&gt;
&lt;li&gt;Более миллиона активных розничных партнеров по всему Миру.&lt;/li&gt;
&lt;li&gt;Для построения страницы осуществляется доступ к 100-150 сервисам.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="arkhitektura"&gt;Архитектура&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Что мы на самом деле подразумеваем под словом
    &lt;a href="/tag/masshtabiruemost/"&gt;"масштабируемость"&lt;/a&gt;? Обычно говорят, что
    сервис является масштабируемым, если в случае расширения ресурсов
    системы производительность растет пропорционально. Рост
    производительности обычно означает увеличение количества выполняемых
    в единицу времени работ, но с другой стороны он может означать и
    рост объемов выполняемых работ, например размер обрабатываемых
    наборов данных.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; пришлось претерпеть большое архитектурное
    преобразование в процессе перехода от двух-уровневой монолитной
    системы к полностью распределенной децентрализованной платформе для
    сервисов и приложений.&lt;/li&gt;
&lt;li&gt;Все началось с одного приложения, обменивающегося данными с
    внутренним интерфейсом, написанного на &lt;a href="/tag/c/"&gt;C++&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Оно росло. За годы усилий, направленных на масштабирование,
    &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; сфокусировался на масштабировании &lt;a href="/tag/bd/"&gt;баз данных&lt;/a&gt; для хранения постоянно растущего объема информации
    о предметах, покупателях, заказах, для поддержки нескольких
    интернациональных сайтов. В 2001 году стало ясно, что исходное
    веб-приложение больше не в состоянии
    &lt;a href="/tag/masshtabiruemost/"&gt;масштабироваться&lt;/a&gt; такими темпами. Базы
    данных были разбиты на маленькие части и для каждой их них был
    построен отдельный &lt;a href="/tag/interfejs/"&gt;интерфейс&lt;/a&gt;, выполненный в виде
    сервиса, который являлся единственным способом получить доступ к
    данным.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/bd/"&gt;Базы данных&lt;/a&gt; стали общим ресурсом, что затрудняло рост
    бизнеса в целом. Интерфейсы, связанные с пользователями и базами
    данных, были сильно ограничены в своей эволюции, так как они
    одновременно использовались множеством разных команд разработчиков и
    процессов.&lt;/li&gt;
&lt;li&gt;Их &lt;a href="/tag/arkhitektura/"&gt;архитектура&lt;/a&gt; тесно связана и построена вокруг
    сервисов. Ориентированная на сервисы архитектура дала им необходимый
    уровень изоляции для построения множества программных компонентов
    быстро и независимо.&lt;/li&gt;
&lt;li&gt;Система выросла до сотен сервисов и не меньшего количества серверов
    приложений, агрегирующих информацию, полученную от сервисов.
    Приложение, генерирующее страницы для
    &lt;a href="https://www.insight-it.ru/goto/300f3b10/" rel="nofollow" target="_blank" title="http://amazon.com"&gt;Amazon.com&lt;/a&gt;, является одним из таких серверов.
    То же самое можно сказать и про приложения, служащие в роли
    интерфейса для Веб-сервисов, сервиса, обслуживающего покупателя,
    интерфейса для продавцов.&lt;/li&gt;
&lt;li&gt;Многие другие &lt;a href="/tag/tekhnologiya/"&gt;технологии&lt;/a&gt; очень трудно
    масштабировать до размеров &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt;, особенно
    технологии коммуникационной инфраструктуры. Они отлично работают до
    какого-то предела в размерах системы, а после перестают справляться
    с выполнения своих обязанностей. Именно это подтолкнуло
    &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; на создание своих
    &lt;a href="/tag/tekhnologiya/"&gt;технологий&lt;/a&gt; в этой области.&lt;/li&gt;
&lt;li&gt;Не ограничиваясь одним конкретным подходом, некоторые части системы
    используют &lt;a href="/tag/java/"&gt;Java&lt;/a&gt;/&lt;a href="/tag/jboss/"&gt;Jboss&lt;/a&gt;, но они являются
    всего лишь &lt;a href="/tag/servlet/"&gt;сервлетами&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/c/"&gt;C++&lt;/a&gt; используется для обработки запросов, в то время как
    &lt;a href="/tag/perl/"&gt;Perl&lt;/a&gt; и &lt;a href="/tag/mason/"&gt;Mason&lt;/a&gt; - для составления контента.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; предпочитает не пользоваться промежуточным
    &lt;a href="/tag/po/"&gt;программным обеспечением&lt;/a&gt;, так как оно в большинстве
    случаев является каркасом, а не средством разработки. Если
    используется промежуточное &lt;a href="/tag/po/"&gt;программное обеспечение&lt;/a&gt;, то
    разработчик становится &lt;em&gt;заперт&lt;/em&gt; в использование тех принципов
    разработки, которые выбрал разработчик промежуточного &lt;a href="/tag/po/"&gt;ПО&lt;/a&gt;.
    Если появится необходимость использовать какие-либо другие решения,
    ничего не выйдет - вы заперты. Один и тот же цикл используется для
    обработки всех типов событий: сообщений, задержек в передаче данных,
    &lt;em&gt;AJAX&lt;/em&gt;, и так далее. Слишком громоздко. Если бы промежуточное
    &lt;a href="/tag/po/"&gt;программное обеспечение&lt;/a&gt; было бы доступно в виде более
    мелких компонентов, скорее на правах средства разработки, чем
    каркаса для системы, тогда &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; был бы более
    заинтересован в нем.&lt;/li&gt;
&lt;li&gt;Кажется, что &lt;a href="/tag/soap/"&gt;SOAP&lt;/a&gt; веб стек собирается заново решать все
    те же проблемы распределенных систем.&lt;/li&gt;
&lt;li&gt;Если предложить разработчиком на выбор работу над &lt;a href="/tag/soap/"&gt;SOAP&lt;/a&gt;
    и &lt;a href="/tag/rest/"&gt;REST&lt;/a&gt; веб-сервисами, то только 30% выберут
    &lt;a href="/tag/soap/"&gt;SOAP&lt;/a&gt;, это скорее всего будут разработчики на .NET и
    &lt;a href="/tag/java/"&gt;Java&lt;/a&gt;, привыкшие использовать WSDL файлы для генерации
    интерфейсов удаленных объектов. Оставшиеся 70% выберут
    &lt;a href="/tag/rest/"&gt;REST&lt;/a&gt; - это будут пользователи &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt; и
    &lt;a href="/tag/perl/"&gt;Perl&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Обе категории разработчиков имеют возможность получить интерфейс к
    объектам &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt;. Разработчики заинтересованы просто
    выполнить свою работу, не заботясь о том, что происходит на другом
    конце провода.&lt;/li&gt;
&lt;li&gt;Идея &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; заключалась в построении открытого
    сообщества вокруг своих сервисов. Веб-сервисы были выбраны благодаря
    своей простоте. Но так это выглядит только снаружи. Внутри же
    находится архитектура, ориентированная на сервисы. Доступ к данным
    может быть получен только через соответстыующий
    &lt;a href="/tag/interfejs/"&gt;интерфейс&lt;/a&gt;. Этот процесс описан в WSDL, но они
    используют свои собственные механизмы транспортировки и инкапсуляции
    данных.&lt;/li&gt;
&lt;li&gt;Команды разработчиков очень небольшие и организуются вокруг сервисов&lt;ul&gt;
&lt;li&gt;Сервисы являются независимыми единицами предоставления функционала
в рамках &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Если у разработчика возникает новая бизнес-идея или проблема,
которую ему хотелось бы решить, он собирает команду для ее решения
или реализации. Количество участников ограничено 8-10 людьми.
Команды из такого количества человек обычно называют
&lt;em&gt;пиццерийными&lt;/em&gt;, так как для того, чтобы ее накормить достаточно двух
пицц.&lt;/li&gt;
&lt;li&gt;Команды очень небольшие, но они уполномочены решать поставленную
задачу любыми доступными способами, именно так, как они считают
нужным.
&amp;ndash; В качестве примера задачи, поставленной перед такой командой,
может служить поиск фраз в рамках книги, уникальных для конкретного
текста.
&amp;ndash; Экстенсивное A/B тестирование используется для интеграции новых
сервисов. Они смотрят на произведенное влияние на систему и
выполняют экстенсивные измерения.&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;Результатом развертывания является виртуальная машина, которая
запускается с помощью &lt;strong&gt;EC2&lt;/strong&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;Разработчики принуждаются работать в первую очередь с упором на
предоставление пользователям новых возможностей, а не на внедрение
новых технологий и уже после этого осознавание того, зачем это
делалось&lt;/li&gt;
&lt;li&gt;Все начинается с пресс-релиза о новых возможностях,
предоставляемых пользователям, а после чего ведется работа по
определению того факта, планировалось ли все же что-то значимое для
пользователей или нет?&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;Не все, но многие операции имеют состояния. Например, оформление
покупки продукта.&lt;/li&gt;
&lt;li&gt;Сервис отслеживания последних открытых страниц использует
рекомендации, базирующиеся на идентификационных номерах сессий.&lt;/li&gt;
&lt;li&gt;Они следят за всем, так что в любом случае цель вовсе не в
поддержании состояний. Достаточно небольшой набор состояний требует
поддержания с помощью сессий. Сервисы уже хранят всю необходимую
информацию, остается лишь ими воспользоваться.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Три свойства системы или теорема Eric Brewer'а:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;Три свойства системы: &lt;em&gt;стабильность, доступность, переносимость
возможных распадений сети&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;В большинстве случаев для любой системы с общими данными
выполняются два свойства из трех&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Возможность разделения:&lt;/em&gt; распределение узлов по небольшим
группам, которые могут иметь доступ к другим группам, но не могут
получить доступ к конкретному произвольному узлу системы&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Стабильность:&lt;/em&gt; запишите какие-либо данные, а затем прочитайте их
же - получите те же самые данные обратно. Для распределенных систем
это далеко не всегда так.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Доступность:&lt;/em&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;
&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;Для того, чтобы строить реально масштабируемые системы, Вам
    необходимо изменить свой склад ума. Вероятностный подход к хаосу
    может принести неплохие результаты. В традиционных системах мы
    представляем себе идеальный мир, где не происходит никаких
    чрезвычайных ситуаций, а затем мы в этом же мире пытаемся построить
    реализацию по-настоящему сложных алгоритмов. При первом же удобном
    случае вся система гарантированно рушится, это реальность, пора бы
    уже к этому привыкнуть. Например, неплохим решением мог бы стать
    подход, использующий быструю перезагрузку и тем самым быстрое
    восстановление работоспособности. При достаточной избыточности
    данных и сервисов этот подход может дать практически 100%
    отказоустойчивость. Необходимо создание самовосстанавливающихся и
    самоорганизующихся операций.&lt;/li&gt;
&lt;li&gt;Создание инфраструктуры, в которой компоненты ничего друг с другом
    не разделяют. Сама инфраструктура может стать общим ресурсом для
    разработки и развертывания с теми же недостатками, что и совместные
    ресурсы в логике и на уровне данных. Это может вызвать запирание и
    блокировку данных. &lt;a href="/tag/arkhitektura/"&gt;Архитектура&lt;/a&gt;, ориентированная
    на сервисы, позволяет создание параллельных изолированных процессов
    разработки, позволяющих масштабировать будущие разработки для
    соответствия темпам роста.&lt;/li&gt;
&lt;li&gt;Откройте систему с помощью собственной API для создания
    экосистемы вокруг Ваших приложений.&lt;/li&gt;
&lt;li&gt;Единственный способ управлять большой распределенной системой -
    разрабатывать ее как можно более простой. Это достигается благодаря
    отсутствию скрытых требований и зависимостей в ее структуре.
    Минимизируйте использование технологий до того уровня, который Вам
    необходим для решения конкретно Ваших проблем и задач. Создание
    дополнительных искуственных и ненужных уровней в системе никогда не
    пойдет ей на пользу.&lt;/li&gt;
&lt;li&gt;Организация вокруг сервисов дает гибкость. Параллельная работа
    возможна, так как на выходе получается сервис. Этот факт резко
    сокращает время, необходимое для выхода на рынок. Построение
    инфраструктуры позволяет сервисам реализовываться очень быстро.&lt;/li&gt;
&lt;li&gt;Определенно будут возникать проблемы со всем, что пускает пыль в
    глаза еще до реальной реализации.&lt;/li&gt;
&lt;li&gt;Для внутреннего управления сервисами стоит использовать SLA.&lt;/li&gt;
&lt;li&gt;Кто угодно может быстро добавлять веб-сервисы к их продукту.
    Достаточно лишь реализовать часть продукта в виде сервиса и начать
    его использовать.&lt;/li&gt;
&lt;li&gt;Построение инфраструктуры производится для обеспечения
    производительности, надежности и контролирования издержек. После ее
    построения Вы никогда не сможете сказать после очередной неудачи,
    что в этом виновата компания &lt;em&gt;Х&lt;/em&gt;. Ваше &lt;a href="/tag/po/"&gt;программное обеспечение&lt;/a&gt; не всегда является более надежным, чем любой
    другой, но зато у Вас появляется возможность быстро устранять
    неполадки и развертывать ее, в отличии от продуктов других компаний.&lt;/li&gt;
&lt;li&gt;Используйте систему оценивания и целенаправленные обсуждения для
    отделения "хорошего" от "плохого". Бывшие сотрудники
    &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; в своих презентациях неоднократно
    демонстрировали свою глубоко засевшую привычку ставить покупателей
    перед выбором и смотреть какой из вариантов сработает лучшим
    образом, и уже на результатах такого рода тестов строить свои
    решения.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/1a817e43/" rel="nofollow" target="_blank" title="http://www.kaushik.net/avinash/"&gt;Avinash Kaushik&lt;/a&gt; называет это
    избавлением от "гиппопотамов", наиболее высоко оплачиваемых людей.
    Осуществляется оно с помощью A/B тестирований и веб-аналитиков. Если
    у вас есть выбор пути развития, реализуйте оба, позвольте людям ими
    пользоваться, и посмотрите какой из альтернативных результатов
    приведет в лучшим результатам.&lt;/li&gt;
&lt;li&gt;Создайте экономичную культуру. &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; использовал
    двери в роли столов, например.&lt;/li&gt;
&lt;li&gt;Знайте, что Вам необходимо. &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; имеет печальный
    опыт с ранней системой рекомендаций, которая не сработала: "Это было
    не то, что требовалось &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt;. Рекомендации книг в
    &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; требовали работы с разбросанными данными,
    всего лишь несколько рейтингов или покупок. Она должна работать
    быстро. Система должна иметь необходимый
    &lt;a href="/tag/masshtabiruemost/"&gt;масштаб&lt;/a&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;a href="/tag/soa/"&gt;сервис-ориентированную архитектуру&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Во время интервью обращайте внимание на три критерия: энтузиазм,
    креативность, компетентность. Самым крупным залогом успеха
    &lt;a href="https://www.insight-it.ru/goto/300f3b10/" rel="nofollow" target="_blank" title="http://amazon.com"&gt;Amazon.com&lt;/a&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;Выберите путь инноваций. Перед лицом всей компании, Jeff Bezos может
    дать старый кроссовок Nike в роли награды "Просто сделай это" тому,
    кто привнес инновацию.&lt;/li&gt;
&lt;li&gt;Не платите за производительность. Предоставьте хороший повод задрать
    нос и высокую оплату труда, но оставляйте это простым. Распознать
    выдающуюся работу можно и другими методами. Оплата по заслугам
    звучит неплохо, но в условиях большой организации это практически
    невозможно. Используйте не-денежные награды, такие как тот старый
    кроссовок. Если преподнести это как способ сказать спасибо, кто-то
    оценит.&lt;/li&gt;
&lt;li&gt;Вырастайте быстро. Большие парни вроде Barnes и Nobel у Вас на
    хвосте. &lt;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt; не был ни первым, ни вторым, ни даже
    третим книжным магазинам в &lt;a href="/tag/internet/"&gt;Сети&lt;/a&gt;, но их взгляд на
    работу и драйв в итоге позволили им вырваться вперед.&lt;/li&gt;
&lt;li&gt;В дата-центрах персонал проводит только 30% времени в работе над
    вопросами создания инфраструктуры, остальные 70% они проводят за
    размещения поставок тяжелого оборудования, управлением программным
    обеспечением, балансировкой нагрузок, техническими работами,
    изменениями в масштабе и так далее.&lt;/li&gt;
&lt;li&gt;Запретите клиентам прямой доступ к базе данных. Это значит появление
    возможность масштабировать сервис и делать его более надежным не
    вовлекая при этом клиентов. Это очень похоже на возможность Google
    независимо вносить улучшения в части системы, что приводит к
    улучшениям в работе всех остальных ее компонентов.&lt;/li&gt;
&lt;li&gt;Создайте единый универсальный механизм получения доступа к сервисам.
    Это позволяет более легко агрегировать информацию, полученную от
    сервисов, децентрализованно прокладывать маршруты передачи запросов,
    распределенно следить за ними, а также получать доступ к другим
    инфраструктурным механизмам.&lt;/li&gt;
&lt;li&gt;Предоставление свободного доступа ко всем сервисам
    &lt;a href="https://www.insight-it.ru/goto/300f3b10/" rel="nofollow" target="_blank" title="http://amazon.com"&gt;Amazon.com&lt;/a&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;a href="/tag/amazon/"&gt;Amazon&lt;/a&gt;, подобно &lt;a href="/tag/google/"&gt;Google&lt;/a&gt;,
    является огромным конкурентным преимуществом. Они могут строить
    комплексные приложения на основе примитивных сервисов, которые сами
    по себе просты до безобразия. Они могут независимо масштабировать
    свою работу, поддерживать доступность не распараллеленной системы,
    быстро реализовывать новые сервисы без необходимости массивных
    изменений в конфигурации.&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sun, 17 Feb 2008 21:47:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-02-17:highload/2008/arkhitektura-amazon/</guid><category>Amazon</category><category>C++</category><category>Java</category><category>Jboss</category><category>Linux</category><category>Mason</category><category>online</category><category>Oracle</category><category>Perl</category><category>REST</category><category>Servlet</category><category>SOAP</category><category>архитектура</category><category>архитектура Amazon</category><category>интер информационные технологии</category><category>Масштабируемость</category></item><item><title>Отношения online</title><link>https://www.insight-it.ru//theory/2008/otnosheniya-online/</link><description>&lt;p&gt;Допустим, у Вас появилось желание оставить на своем интернет-ресурсе
ссылку на сайт своего старого друга. Объяснить этот факт простому
читателю достаточно просто:
&lt;code&gt;&amp;lt;a&amp;nbsp;href="www.site.ru"&amp;gt;Сайт&amp;nbsp;моего&amp;nbsp;друга&amp;lt;/a&amp;gt;&lt;/code&gt;, но поймет ли такую
надпись очередной раз инспектирующий Ваш сайт &lt;a href="/tag/crawler/"&gt;crawler&lt;/a&gt;
какой-нибудь поисковой системы? Может быть Вы просто злостно торгуете
ссылками со своего сайта?
&lt;!--more--&gt;
Как Вы могли уже догадаться, для решения этой достаточно
узкоспециализированной задачи - выражение отношений с владельцем сайта,
на который указывает ссылка - существует специальный
&lt;a href="/tag/mikroformaty/"&gt;микроформат&lt;/a&gt; под названием &lt;a href="/tag/xfn/"&gt;&lt;strong&gt;XFN&lt;/strong&gt;&lt;/a&gt;, что расшифровывается как &lt;em&gt;XHTML Friends Network&lt;/em&gt;. С
его помощью любой человек, у которого есть сайт может продемонстрировать
всем желающим в каких отношениях он находится с владельцем сайта, на
который он ссылается.&lt;/p&gt;
&lt;p&gt;Реализуется этот микроформат с помощью атрибута &lt;code&gt;rel&lt;/code&gt; тэга &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;,
возможные варианты значения (имеется возможность их комбинировать):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Категории значений&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Значения XFN&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;дружба:&lt;/td&gt;
&lt;td&gt;&lt;code&gt;friend&lt;/code&gt;(кто-либо, кого Вы считаете другом),  &lt;code&gt;acquaintance&lt;/code&gt; (знакомый, просто пару раз здоровались или недолго общались), &lt;code&gt;contact&lt;/code&gt; (кто-либо, с кем Вы знаете как связаться в случае необходимости)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;физические:&lt;/td&gt;
&lt;td&gt;&lt;code&gt;met&lt;/code&gt; (кто-либо, с кем вы когда-то лично встречались)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;профессиональные:&lt;/td&gt;
&lt;td&gt;&lt;code&gt;co-worker&lt;/code&gt; (коллега по работе),&lt;code&gt;colleague&lt;/code&gt; (коллега по учебе или иной форме активности)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;географические:&lt;/td&gt;
&lt;td&gt;&lt;code&gt;co-resident&lt;/code&gt; (живете на одной улице),&lt;code&gt;neighbor&lt;/code&gt; (сосед)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;семейные:&lt;/td&gt;
&lt;td&gt;&lt;code&gt;child&lt;/code&gt; (ребенок, в том числе и приемный),&lt;code&gt;parent&lt;/code&gt; (родители, в том числе и приемные),&lt;code&gt;sibling&lt;/code&gt; (все братья и сетры),&lt;code&gt;spouse&lt;/code&gt; (муж/жена), &lt;code&gt;kin&lt;/code&gt; (дальний родственник)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;романтические:&lt;/td&gt;
&lt;td&gt;&lt;code&gt;muse&lt;/code&gt; (муза, источник вдохновения), &lt;code&gt;crush&lt;/code&gt; (кто-либо, к кому у Вас страстное увлечение), &lt;code&gt;date&lt;/code&gt; (кто-либо, с кем Вы встречаетесь), &lt;code&gt;sweetheart&lt;/code&gt; (кто-либо, в кого Вы влюбились"}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;личность:&lt;/td&gt;
&lt;td&gt;&lt;code&gt;me&lt;/code&gt; (ссылка на самого себя на другом сайте. Обязательно должна быть симметрична; отношение 'me' неявно подразумевается между поддиректорией и всем ее содержимым)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Как не трудно заметить, практически все возможные варианты отношений
могут быть описаны одним из значений или их комбинацией. Наш пример из
начала этого поста с использованием XFN выглядел бы:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"www.site.ru"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"friend&amp;nbsp;met"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Сайт&amp;nbsp;моего&amp;nbsp;друга
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Помимо этого есть еще один маленький нюанс, необходимый для того, чтобы
browser'ы и поисковые системы знали, что данная страница оффциально
поддерживает этот микроформат, для этого необходимо указать следующий
атрибут тэгу &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;head&lt;/span&gt; &lt;span class="na"&gt;profile=&lt;/span&gt;&lt;span class="s"&gt;"http://gmpg.org/xfn/11"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Этот пост был написан по мотивам &lt;a href="https://www.insight-it.ru/goto/faee6117/" rel="nofollow" target="_blank" title="http://www.gmpg.org/xfn/"&gt;официального сайта XFN&lt;/a&gt;, если Вас заинтересовал этот микроформат,
возможно имеет смысл посетить и его: там можно найти FAQ, утилиты для
автоматической генерации кода, а также всю остальную информацию по
данному микроформату (на английском естественно).&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sat, 16 Feb 2008 13:07:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-02-16:theory/2008/otnosheniya-online/</guid><category>online</category><category>xfn</category><category>XHTML</category><category>интернет</category><category>Микроформаты</category><category>семантика</category><category>Сеть</category><category>технология</category></item><item><title>Архитектура Flickr</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-flickr/</link><description>&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/f50a76e1/" rel="nofollow" target="_blank" title="http://www.flickr.com"&gt;Flickr&lt;/a&gt; является мировым лидером среди сайтов
размещения фотографий. Перед Flickr стоит впечатляющая задача, они
должны контролировать обширное море ежесекундно обновляющегося контента,
непрерывно пополняющиеся легионы пользователей, постоянный поток новых
предоставляемых пользователям возможностей, а делается все это при
постоянной поддержке отличной производительности. Как же они это
делают?
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="istochniki-informatsii"&gt;Источники информации&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Как и предыдущий пост &lt;a href="https://www.insight-it.ru/highload/2008/arkhitektura-google/"&gt;"Архитектура Google"&lt;/a&gt;, этот тоже является
переводом &lt;a href="https://www.insight-it.ru/goto/e7a0ee0d/" rel="nofollow" target="_blank" title="http://highscalability.com/flickr-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'а Hoff'а&lt;/a&gt;. Возможно
читателям &lt;a href="/tag/google/"&gt;Google&lt;/a&gt; был более интересен, но подход Flickr к
масштабируемости тоже более чем заслуживает внимания. Далее привожу
источники информации из оригинальной статьи:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/88014756/" rel="nofollow" target="_blank" title="http://www.niallkennedy.com/blog/uploads/flickr_php.pdf"&gt;Flickr и PHP&lt;/a&gt;
    (ранний документ)&lt;/li&gt;
&lt;li&gt;Планирование нагрузок на LAMP&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/6df1dabf/" rel="nofollow" target="_blank" title="http://www.bytebot.net/blog/archives/2007/04/25/federation-at-flickr-a-tour-of-the-flickr-architecture"&gt;Федерация Flickr: Тур по архитектуре Flickr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/9e0a13a1/" rel="nofollow" target="_blank" title="http://highscalability.com/book-building-scalable-web-sites"&gt;Построение масштабируемых веб-сайтов&lt;/a&gt;
    от Call Handerson'а из Flickr&lt;/li&gt;
&lt;li&gt;История войн баз данных #3: Tim O'Reilly о Flickr&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/d881b0d9/" rel="nofollow" target="_blank" title="http://www.iamcal.com/talks/"&gt;Cal Henderson's Talks&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/php/"&gt;PHP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/sql/"&gt;MySQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Сегментирование &lt;em&gt;(прим.: разбиение системы на части, обслуживающие
    каждая свою группу пользователей; называть можно было по-разному, но
    давайте остановимся на этом варианте перевода слова "Shards")&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/memcached/"&gt;Memcached&lt;/a&gt; для кэширования&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/squid/"&gt;Squid&lt;/a&gt; в качестве обратной-прокси для html и
    изображений&lt;/li&gt;
&lt;li&gt;&lt;a href="/linux"&gt;Linux&lt;/a&gt; (&lt;a href="/tag/redhat/"&gt;RedHat&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/smarty/"&gt;Smarty&lt;/a&gt; в роли шаблонизатора&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/perl/"&gt;Perl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PEAR для парсинга e-mail и XML&lt;/li&gt;
&lt;li&gt;ImageMagick для обработки изображений&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/apache/"&gt;Apache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/systemimager/"&gt;SystemImager&lt;/a&gt; для развертывания систем&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/ganglia/"&gt;Ganglia&lt;/a&gt; для мониторинга распределенных систем&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/subcon/"&gt;Subcon&lt;/a&gt; хранит важные системные конфигурационные файлы
    в SVN-репозитории для легкого развертывания на машины в кластере.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/cvsup/"&gt;Cvsup&lt;/a&gt; для распространения и обновления коллекций
    файлов по сети&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="statistika"&gt;Статистика&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Более четырех миллиардов запросов в день&lt;/li&gt;
&lt;li&gt;Примерно 35 миллионов фотографий в кэше &lt;a href="/tag/squid/"&gt;Squid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Около двух миллионов фотографий в оперативной памяти
    &lt;a href="/tag/squid/"&gt;Squid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Всего приблизительно 470 миллионов изображений, каждое представлено
    в 4 или 5 размерах&lt;/li&gt;
&lt;li&gt;38 тысяч запросов к &lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt; (12 миллионов
    объектов)&lt;/li&gt;
&lt;li&gt;2 петабайта дискового пространства&lt;/li&gt;
&lt;li&gt;Более 400000 фотографий добавляются ежедневно&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="arkhitektura"&gt;Архитектура&lt;/h3&gt;
&lt;p&gt;Симпатичное изображение архитектуры Flickr можно увидеть на &lt;a href="https://www.insight-it.ru/goto/d30e097b/" rel="nofollow" target="_blank" title="http://www.slideshare.net/techdude/scalable-web-architectures-common-patterns-and-approaches/138"&gt;этом слайде&lt;/a&gt;.
Краткое ее описание выглядит следующим образом:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Два ServerIron&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/squid/"&gt;Squid&lt;/a&gt; кэши&lt;/li&gt;
&lt;li&gt;Системы хранения NetApp&lt;/li&gt;
&lt;li&gt;Серверы &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt; приложений&lt;/li&gt;
&lt;li&gt;Менеджер хранения данных&lt;/li&gt;
&lt;li&gt;Master-master сегменты&lt;/li&gt;
&lt;li&gt;Центральная база данных, структурированная по принципу Dual
Tree&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/memcached/"&gt;Memcached&lt;/a&gt; кластер&lt;/li&gt;
&lt;li&gt;Поисковая система&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Хранение данных&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Структура Dual Tree является индивидуальным набором модификаций для
&lt;a href="/tag/sql/"&gt;MySQL&lt;/a&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;Отсутствие состояний заключается в том, что в случае необходимости
    они имеют возможность передать пользователей от сервера к серверу,
    что стало намного проще для них после создания своего API&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;a href="/tag/php/"&gt;PHP&lt;/a&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;li&gt;&lt;em&gt;Сегменты системы:&lt;/em&gt; Мои данные хранятся на моем сегменте, но
запись о Вашем комментарии хранится на Вашем сегменте.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Глобальное кольцо:&lt;/em&gt; Принцип работы схож с DNS, Вам необходимо
знать куда Вы хотите пойти и кто контролирует то место, куда Вы
собираетесь пойти.&lt;/li&gt;
&lt;li&gt;Логика на &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt; устанавливает соединение с сегментом и
поддерживает целостность данных (10 строк кода с комментариями!)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сегменты:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;Срез основной базы данных&lt;/li&gt;
&lt;li&gt;Активная репликация по принципу мастер-мастер: имеет несколько
недостатков в &lt;a href="/tag/sql/"&gt;MySQL&lt;/a&gt; 4.1. Автоматическое
инкрементирование идентификационных номеров используется для
поддержания системы в режиме одновременной активности обоих серверов
в паре&lt;/li&gt;
&lt;li&gt;Привязывание новых учетных записей к сегментам системы происходит
случайным образом&lt;/li&gt;
&lt;li&gt;Миграция пользователей проводится время от времени для того, чтобы
избавиться от проблем, связанных с излишне активными пользователями.
Необходима сбалансированность в этом процессе, особенно в случаях с
большим количеством фотографий&amp;hellip; 192 тысячи фотографий, 700 тысяч
тэгов, может занять несколько минут. Миграция выполняется вручную.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Нажатие на &lt;strong&gt;Favorite&lt;/strong&gt;:&lt;ul&gt;
&lt;li&gt;Получается информация об учетной записи владельца из кэша для
того, чтобы узнать к какому сегменту он привязан (допустим на
shard-5)&lt;/li&gt;
&lt;li&gt;Получается информация о моей учетной записи из кэша, более
конкретно - мой сегмент (например shard-13)&lt;/li&gt;
&lt;li&gt;Начинается "распределенная транзакция" для определения ответов на
вопросы: Кто добавил эту фотографию в избранное? Как изменился
список избранных фотографий?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Подобные вопросы могут задаваться любому сегменту, информация на них
    абсолютно избыточна.&lt;/li&gt;
&lt;li&gt;Для избавления от задержек, связанных с репликацией...&lt;ul&gt;
&lt;li&gt;при каждой загрузке страницы, пользователю предоставляется список
серверов&lt;/li&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;
&lt;li&gt;Периоды пиковой нагрузки также нарушают правило 50% нагрузки. В
    такие моменты система получает 6-7 тысяч запросов в секунду, в то
    время как на данный момент система может работать на
    пятидесятипроцентном уровне нагрузки только при четырех тысячах
    запросов в секунду.&lt;/li&gt;
&lt;li&gt;В среднем при загрузке одной страницы выполняется 27-35
    SQL-запросов. Списки избранных фотографий обрабатываются в реальном
    времени, ровно как и доступ через API к базе данных. Все требования
    к нагрузке в реальном времени выполняются без каких-либо
    недостатков.&lt;/li&gt;
&lt;li&gt;Более 36 тысяч запросов в секунду может выполняться не выходя за
    рамки возможностей системы, даже при резком росте трафика.&lt;/li&gt;
&lt;li&gt;Каждый сегмент содержит данные о более чем 400 тысячах
    пользователей.&lt;/li&gt;
&lt;li&gt;Многие данные хранятся в двух местах одновременно. Например,
    комментарий является частью между комментатором и автором
    комментируемого контента. Где его хранить? Как насчет обоих мест?
    Транзакции используются для предотвращения рассинхронизации данных:
    открывается первая транзакция, выполняется запись, открывается
    вторая транзакция, выполняется запись, подтверждается первая
    транзакция если все нормально, после чего вторая подтверждается
    только в случае если первая прошла успешно.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Поиск&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Используется два варианта поиска: поиск в рамках сегмента,
поддерживающий до 35 тысяч запросов в секунду, а также проприетарный
веб-поиск от Yahoo!&lt;/li&gt;
&lt;li&gt;В 90% случаев используется система от Yahoo!, за исключением
поиска по тэгу фотографий одного пользователя и массовых изменений
тэгов.&lt;/li&gt;
&lt;li&gt;Эту систему стоит рассматривать как аналог Lucene.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Оборудование&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;EMT64 под управлением RHEL 4 с 16 Gb оперативной памяти.&lt;/li&gt;
&lt;li&gt;6 жестких дисков с 15000rpm, объединены в RAID-10.&lt;/li&gt;
&lt;li&gt;Размер для пользовательских метаданных достигает 12 терабайт (это
не включает фотографии, для них цифры существенно больше).&lt;/li&gt;
&lt;li&gt;Используются 2U корпуса.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Резервное копирование данных&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;ibbackup выполняется регулярно посредством cron daemon'а, на
каждом сегменте настроен на разное время.&lt;/li&gt;
&lt;li&gt;Каждую ночь делается снимок со всего кластера баз данных.&lt;/li&gt;
&lt;li&gt;Запись или удаление нескольких больших файлов с резервными копиями
одновременно на реплицирующую систему хранения может сильно
сократить производительность системы вцелом на последующие несколько
часов из-за процесса репликации. Выполнение этого на активно
работающей системе хранения фотографий было бы не самой лучшей
идеей.&lt;/li&gt;
&lt;li&gt;Содержание нескольких резервных копий всех Ваших данных требует
существенных материальных затрат, но оно того стоит. Особенно это
актуально для тех ситуаций, когда Вы понимаете, что что-то пошло не
так только спустя несколько дней после того как это случилось, в
таких случаях неплохо иметь, например, резервные копии 1, 3, 10 и
30-дневной давности.&lt;/li&gt;
&lt;li&gt;Фотографии хранятся в системе хранения данных. После загрузки
изображения система выдает различные его размеры, на чем ее работа
заканчивается. Метаданные и ссылки на файловые системы, где
расположены фотографии, хранятся в базе данных.&lt;/li&gt;
&lt;li&gt;Агрегация данных проходит очень быстро, так как она ограничена
пределами сегмента.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max_connections = 400&lt;/code&gt; соединений на каждый сегмент, неплохой запас.
Значение для кэша потоков установлено равным 45, так как не бывает
ситуаций когда более 45 пользователей одновременно выполняют
какие-либо действия с одним конкретным сегментом.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Тэги&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Тэги плохо вписываются в традиционную нормализованную схему
реляционной базы данных. Денормализация или активное кэширование -
единственные способы сгенерировать облако меток для сотен миллионов
тэгов в течении миллисекунд.&lt;/li&gt;
&lt;li&gt;Некоторые данные обрабатываются отдельными вычислительными
кластерами, которые сохраняют результаты своей работы в MySQL, так
как иначе вычисление сложных отношений заняло бы все процессорное
время основных серверов баз данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Направления для развития&lt;/h4&gt;
&lt;p&gt;Ускорение работы с помощью создания
организационного плана для непрерывной работы всей системы на уровне
нескольких датацентров, таким образом чтобы все датацентры имели
возможность получать запросы на общий уровень данных (как сами БД,
так и memcache и прочее) все вместе одновременно. Если все части
системы постоянно активны - время простоя оборудования будет сведено
к минимуму.&lt;/p&gt;
&lt;h3 id="podvodim-itogi"&gt;Подводим итоги&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Старайтесь думать о своем приложении как о чем-то большем, чем просто
    веб-приложении, тогда у Вас возможно появятся поддержка различных
    API, RSS и Atom ленты и многие другие возможности.&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;li&gt;Создавайте четкие уровни абстракции между работой базы данных,
    бизнес-логикой, логикой страниц, разметкой страниц и презентационным
    уровнем. Это позволяет ускорить циклы итеративной разработки.&lt;/li&gt;
&lt;li&gt;Разделение приложения на уровни позволяет каждому заниматься своим
    делом: разработчики могут строить логику страниц, в то время как
    дизайнеры работают с удобством работы для пользователей.&lt;/li&gt;
&lt;li&gt;Делайте релизы как можно чаще, пускай даже это будет происходить
    каждые полчаса.&lt;/li&gt;
&lt;li&gt;Забудьте о всех небольших эффективных вещах, предварительная
    оптимизация является корнем всего зла в примерно 97% всех случаев.&lt;/li&gt;
&lt;li&gt;Тестируйте в работе. Постройте архитектурные механизмы (флаги
    конфигурации, балансировку нагрузки, и так далее), которые позволят
    Вам разворачивать новое оборудование в (и из) работу.&lt;/li&gt;
&lt;li&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;&lt;a href="/tag/sql/"&gt;MySQL&lt;/a&gt; (дисковый ввод/вывод?)&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/squid/"&gt;Squid&lt;/a&gt; (дисковый ввод/вывод? или процессорное время?)&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;Возможен ли резкий рост нагрузки, связанный с каким-либо событием?
Например: какое-либо бедствие, или может быть новость?&lt;/li&gt;
&lt;li&gt;Flickr получает на 20-40% больше новых фотографий в первый рабочий
день нового года, чем в любой пик в предыдущем году.&lt;/li&gt;
&lt;li&gt;По воскресеньям нагрузка в среднем на 40-50% выше, чем в любой
другой день недели.&lt;/li&gt;
&lt;/ul&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>Fri, 08 Feb 2008 22:41:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-02-08:highload/2008/arkhitektura-flickr/</guid><category>Apache</category><category>Cvsup</category><category>flickr</category><category>Ganglia</category><category>Java</category><category>Linux</category><category>Memcached</category><category>MySQL</category><category>online</category><category>Perl</category><category>PHP</category><category>RedHat</category><category>shard</category><category>Smarty</category><category>Squid</category><category>Subcon</category><category>SystemImager</category><category>архитектура</category><category>архитектура Flickr</category><category>интернет</category><category>кластер</category><category>Масштабируемость</category><category>сервер</category></item><item><title>На пути к идеалу</title><link>https://www.insight-it.ru//php/2008/na-puti-k-idealu/</link><description>&lt;blockquote&gt;
&lt;p&gt;...или 15 привычек, которые помогут ускорить PHP-приложение&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Практически каждый программист стремится в своих приложениях не только
максимально точно реализовать требуемый функционал, но и сделать это как
можно более эффективным методом. Для этого конечно же необходимо
проектирование, подходящий выбор используемых технологий, возможно
некоторый опыт в предметной области, этот список можно продолжать
достаточно долго, но я позволю себе этого не делать, так как речь
сегодня пойдет не об этом. Вместо этого хочу обратить Ваше внимание на
более простые и "приземленные" методы &lt;a href="/tag/optimizaciya/"&gt;оптимизации&lt;/a&gt;
PHP-кода, которые может быть и не так эффективны по сравнению с
указанными выше, но зато не требуют каких-либо усилий со стороны кодера
и/или программиста, достаточно лишь воспринимать их как "не вредные"
привычки.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;Прочитав достаточно солидный объем разного рода документации по
&lt;a href="/tag/php/"&gt;PHP&lt;/a&gt;, я часто натыкался на статьи и тексты, так или иначе
связанные с &lt;a href="/tag/proizvoditelnost/"&gt;производительностью&lt;/a&gt; PHP-скриптов.
Порой в такого рода источниках информации удавалось найти достаточно
интересные и неочевидные факты об этом языке программирования, которые
не смотря на свою простоту могли дать вполне заметный прирост к
&lt;a href="/tag/proizvoditelnost/"&gt;производительности&lt;/a&gt; итогового приложения. Я
почему-то очень серьезно стал относиться к производительности написанных
мной скриптов, и довольно часто стал испытывать на практике спорные
моменты в реализации, о которых узнавал из Сети или каких-либо
других источников, с помощью самописных или
&lt;a href="/tag/opensource/"&gt;opensource&lt;/a&gt; benchmark'ов, хотя порой и просто внедряя
в реальные приложения. Как ни странно, в большинстве случаев практика
подтверждала теорию, и я стал постоянно пользоваться этими простыми
правилами, о которых я и хочу Вам рассказать.&lt;/p&gt;
&lt;h4&gt;Повышения значения индекса с помощью ++\$i;&lt;/h4&gt;
&lt;p&gt;Этот факт был наверное одним из самых удивительных для меня, когда я
впервые о нем услышал, но действительно операция &lt;strong&gt;++&lt;span style="color: blue"&gt;\$i&lt;/span&gt;&lt;/strong&gt;; выполняется несколько быстрее, чем
&lt;strong&gt;&lt;span style="color: blue"&gt;\$i&lt;/span&gt;++;&lt;/strong&gt;. или другие вариации на ту
же тему вроде &lt;strong&gt;&lt;span style="color: blue"&gt;\$i&lt;/span&gt;+=&lt;span style="color: blue"&gt;1&lt;/span&gt;;&lt;/strong&gt;. Привычка использовать в качестве
индекса цикла переменную под названием i, казалось бы стара как Мир, мне
она досталась в наследство от &lt;strong&gt;C&lt;/strong&gt;, а в месте с ней "в комплекте" шла
привычка писать выражение &lt;strong&gt;i++&lt;/strong&gt; в заголовках циклов. Разница в
скорости обработки этих выражений, насколько мне известно, обусловлена
разным количеством элементарных машинных операций, которые необходимо
выполнить процессору (в точных цифрах не уверен, пишу по памяти, но
&lt;strong&gt;++&lt;span style="color: blue"&gt;\$i&lt;/span&gt;;&lt;/strong&gt; требует трех элементарных
операций, а &lt;strong&gt;&lt;span style="color: blue"&gt;\$i&lt;/span&gt;++;&lt;/strong&gt; &amp;ndash; четырех). В
справедливости этого факта не трудно убедиться, достаточно написать
простенький скрипт, состоящий из цикла с достаточно большим количеством
итераций, и замерить любым способом точное время его выполнения при
использовании разных способов инкрементации индекса цикла.&lt;/p&gt;
&lt;h4&gt;Вывод статического контента без помощи PHP&lt;/h4&gt;
&lt;p&gt;Сейчас тот факт, что использование интерпретатора PHP для вывода
статического контента сильно замедляет этот процесс, кажется мне
очевидным, но поначалу я использовал &lt;strong&gt;&lt;span style="color: #17349c"&gt;echo&lt;/span&gt;&lt;/strong&gt; там, где он был необходим, ничуть
не чаще, чем там, где он лишь замедляет работу скрипта. От использования
еще менее эффективного способа - &lt;strong&gt;&lt;span style="color: #17349c"&gt;print&lt;/span&gt;&lt;/strong&gt;, меня избавила моя лень: писать
каждый раз на одну букву больше дико не хотелось (в отличии от &lt;strong&gt;&lt;span style="color: #17349c"&gt;echo&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span style="color: #17349c"&gt;print&lt;/span&gt;&lt;/strong&gt; возвращает информацию об
успешности выполнения своей работы, что в большинстве случаев
просто-напросто не нужно). Проверить опять же не трудно - нужен лишь
объемистый текстовый файл, который достаточно вывести в browser разными
способами и засечь уходящее на это время.&lt;/p&gt;
&lt;h4&gt;Вывод статического контента из отдельного файла&lt;/h4&gt;
&lt;p&gt;Частенько при желании выполнить указанное в заголовке действие по
привычке используют &lt;strong&gt;&lt;span style="color: #a3a423"&gt;include&lt;/span&gt;&lt;/strong&gt;,
&lt;strong&gt;&lt;span style="color: #a3a423"&gt;require&lt;/span&gt;&lt;/strong&gt; или их &lt;strong&gt;&lt;span style="color: #a3a423"&gt;_once&lt;/span&gt;&lt;/strong&gt; версии, что является далеко не
самой лучшей идеей с точки зрения производительности. Самым быстрыми
быстрыми и экономичными поотношению к оперативной памяти являются
функции &lt;strong&gt;&lt;span style="color: #17349c"&gt;readfile&lt;/span&gt;&lt;/strong&gt; и &lt;strong&gt;&lt;span style="color: #17349c"&gt;fpassthru&lt;/span&gt;&lt;/strong&gt;. В качестве доказательства
этого факта приведу таблицу, демонстрирующую статистику выполнения этой
операции различными методами и позаимствованную с &lt;a href="https://www.insight-it.ru/goto/f18fa5ab/" rel="nofollow" target="_blank" title="http://www.raditha.com/wiki/Readfile_vs_include"&gt;одного англоязычного
сайта&lt;/a&gt;:&lt;/p&gt;
&lt;table align="center" border="1" cellspacing="0" width="100%"&gt;
&lt;tr&gt;
&lt;th align="center" rowspan="2" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial" valign="center"&gt;
Функция

&lt;/th&gt;
&lt;th align="center" colspan="2" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"&gt;
Время (сек.)

&lt;/th&gt;
&lt;th align="center" colspan="2" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"&gt;
Оперативная память (байт)

&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"&gt;
32Kb файл

&lt;/td&gt;
&lt;td align="center" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"&gt;
1Mb файл

&lt;/td&gt;
&lt;td align="center" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"&gt;
32Kb файл

&lt;/td&gt;
&lt;td align="center" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"&gt;
1Mb файл

&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
file\_get\_contents

&lt;/td&gt;
&lt;td align="right"&gt;
0.00152

&lt;/td&gt;
&lt;td align="right"&gt;
0.00564

&lt;/td&gt;
&lt;td align="right"&gt;
52480

&lt;/td&gt;
&lt;td align="right"&gt;
1067856

&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
fpassthru

&lt;/td&gt;
&lt;td align="right"&gt;
**0.00117**

&lt;/td&gt;
&lt;td align="right"&gt;
0.00184

&lt;/td&gt;
&lt;td align="right"&gt;
20016

&lt;/td&gt;
&lt;td align="right"&gt;
20032

&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
fgets

&lt;/td&gt;
&lt;td align="right"&gt;
0.00195

&lt;/td&gt;
&lt;td align="right"&gt;
0.07190

&lt;/td&gt;
&lt;td align="right"&gt;
30760

&lt;/td&gt;
&lt;td align="right"&gt;
30768

&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
file

&lt;/td&gt;
&lt;td align="right"&gt;
0.00157

&lt;/td&gt;
&lt;td align="right"&gt;
0.06464

&lt;/td&gt;
&lt;td align="right"&gt;
87344

&lt;/td&gt;
&lt;td align="right"&gt;
2185624

&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
require\_once

&lt;/td&gt;
&lt;td align="right"&gt;
0.00225

&lt;/td&gt;
&lt;td align="right"&gt;
0.08065

&lt;/td&gt;
&lt;td align="right"&gt;
67992

&lt;/td&gt;
&lt;td align="right"&gt;
2067696

&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
readfile

&lt;/td&gt;
&lt;td align="right"&gt;
**0.00117**

&lt;/td&gt;
&lt;td align="right"&gt;
0.00191

&lt;/td&gt;
&lt;td align="right"&gt;
**19192**

&lt;/td&gt;
&lt;td align="right"&gt;
19208

&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;h4&gt;Вывод переменных&lt;/h4&gt;
&lt;p&gt;Наверняка вам известно, что переменные можно выводить с помощью
конструкции вроде &lt;strong&gt;&lt;span style="color: #17349c"&gt;echo&lt;/span&gt; &lt;span style="color: red"&gt;"&lt;/span&gt;&lt;span style="color: blue"&gt;\$var&lt;/span&gt; &lt;span style="color: red"&gt;text"&lt;/span&gt;;&lt;/strong&gt;, что является одним из самых удобных
вариантов решения этой задачи благодаря минимальному количеству
символов, которые необходимо набрать, но с точки зрения быстродействия
этот вариант далек от идеала, так как влечет за собой достаточно
серьезные преобразования в памяти сервера, эффект которых порой бывает
заметен невооруженным глазом. Частично ущерб производительности можно
сгладить заменой этой конструкции на &lt;strong&gt;&lt;span style="color: #17349c"&gt;echo&lt;/span&gt; &lt;span style="color: blue"&gt;\$var&lt;/span&gt;.&lt;span style="color: red"&gt;"
text"&lt;/span&gt;;&lt;/strong&gt;, что приводит к несколькому усложнению внешнего вида
кода и несколько поправляет ситуацию со скоростью выполнения. Но как
известно знак . обозначает конкатенацию двух строк, что тоже требует
некоторых вычислений и затрат памяти, но и от нее можно избавиться,
заменив на запятую. Выражение &lt;strong&gt;&lt;span style="color: #17349c"&gt;echo&lt;/span&gt;
&lt;span style="color: blue"&gt;\$var&lt;/span&gt;,&lt;span style="color: red"&gt;"
text"&lt;/span&gt;;&lt;/strong&gt; ничем по своему эффекту не отличается от предложенных
ранее вариантов, за исключением максимального быстрого выполнения,
обусловленного отсутствием дополнительных преобразований в процессе
передачи просто последовательности из константы и переменной.&lt;/p&gt;
&lt;h4&gt;Избегайте выполнения лишних действий&lt;/h4&gt;
&lt;p&gt;Достаточно абстрактное утверждение, но тем не мение постоянное
напоминание себе о нем может избавить Вас от совершения массы ошибок.
Самой широкораспространенной является наверное вызов какой-либо функции
(чаще всего &lt;strong&gt;&lt;span style="color: #17349c"&gt;count&lt;/span&gt;();&lt;/strong&gt; или &lt;strong&gt;&lt;span style="color: #17349c"&gt;strlen&lt;/span&gt;();&lt;/strong&gt;) в проверке условия выхода из
цикла. Когда-нибудь доводилось писать видеть в собственном или чужом
коде выражение вида &lt;strong&gt;&lt;span style="color: #a3a423"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;\$i&lt;/span&gt; = &lt;span style="color: #a3a423"&gt;0&lt;/span&gt;;
&lt;span style="color: blue"&gt;\$i&lt;/span&gt; \&amp;lt; &lt;span style="color: #17349c"&gt;count&lt;/span&gt;(&lt;span style="color: blue"&gt;\$array&lt;/span&gt;); ++&lt;span style="color: blue"&gt;\$i&lt;/span&gt;) { ... }&lt;/strong&gt;? А задумываться о
последовательности выполнения действий при его обработке? Стоит только
немного начать размышлять и ошибка становится очевидной: &lt;strong&gt;&lt;span style="color: #17349c"&gt;count&lt;/span&gt;();&lt;/strong&gt; выполняется при каждой итерации
цикла, что приводит к подсчету количества элементов массива при каждой
проверки условия выхода из цикла - почему бы не посчитать это значение
заранее и сравнивать значения индекса с переменной, а не с результатом
выполнения функции?&lt;/p&gt;
&lt;h4&gt;@&lt;/h4&gt;
&lt;p&gt;Использование этого оператора стоит избегать при каждой возможности.
Казалось бы такое простое действие, как сокрытие вывода возможного
сообщения об ошибке, влечет за собой достаточно трудоемкую
последовательность действий: устанавливает значение параметра
PHP-интерпретатора &lt;strong&gt;error_reporting = 0&lt;/strong&gt;, выполняет указанное за этим
оператором действие, возвращает значение &lt;strong&gt;error_reporting&lt;/strong&gt; в исходное
состояние.&lt;/p&gt;
&lt;h4&gt;Маленькие мелочи&lt;/h4&gt;
&lt;p&gt;Развивая тему предыдущего подраздела, хочется обратить внимания, что
даже на еще более элементарных вещах можно сэкономить драгоценное
процессорное время:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Вместо условия &lt;strong&gt;&lt;span style="color: #a3a423"&gt;if&lt;/span&gt;(&lt;span style="color: blue"&gt;\$variableOne&lt;/span&gt; == &lt;span style="color: blue"&gt;\$variableTwo&lt;/span&gt;) { ... }&lt;/strong&gt; можно написать
    &lt;strong&gt;&lt;span style="color: #a3a423"&gt;if&lt;/span&gt;(&lt;span style="color: blue"&gt;\$variableOne&lt;/span&gt; === &lt;span style="color: blue"&gt;\$variableTwo&lt;/span&gt;) { ... }&lt;/strong&gt;, что избавит от
    проверки на соответствие типов данных и приведения их друг к другу,
    в некоторых случаях эти действия эти случаях эти действия конечно же
    и бывают необходимы, но бывает это далеко не часто.&lt;/li&gt;
&lt;li&gt;Глядя на выражения вроде &lt;strong&gt;&lt;span style="color: #a3a423"&gt;if&lt;/span&gt;(&lt;span style="color: blue"&gt;\$boolean&lt;/span&gt; == true) { ... }&lt;/strong&gt;, я чаще
    всего вспоминаю цитату из одного малоизвестного интернет-ресурса:
    &lt;strong&gt;if (b.ToString().length \&amp;lt; 5) { ... }&lt;/strong&gt;. Хоть и не имет никакого
    отношения к PHP, но суть проблемы отражает очень ярко.&lt;/li&gt;
&lt;li&gt;Самым очевидным способом проверить попадает ли длина строки в
    какой-либо диапазон является использование функции &lt;strong&gt;&lt;span style="color: #17349c"&gt;strlen&lt;/span&gt;();&lt;/strong&gt; и сравнение полученного
    результата с фиксированными значениями, но зачем выполнять лишний
    вызов функции, если можно воспользоваться услугами конструкцией
    языка PHP &lt;strong&gt;&lt;span style="color: #17349c"&gt;isset&lt;/span&gt;();&lt;/strong&gt; для
    определения наличия в строке определенных символов. &lt;strong&gt;&lt;span style="color: #a3a423"&gt;if&lt;/span&gt;(&lt;span style="color: #17349c"&gt;isset&lt;/span&gt;(&lt;span style="color: blue"&gt;\$str&lt;/span&gt;{&lt;span style="color: blue"&gt;5&lt;/span&gt;})) { ... }&lt;/strong&gt; приведет к абсолютно тем
    же результатам, что и &lt;strong&gt;&lt;span style="color: #a3a423"&gt;if&lt;/span&gt;(&lt;span style="color: #17349c"&gt;strlen&lt;/span&gt;(\$str)&amp;gt;4){ ... }&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Битовые операции выполняются намного быстрее относительно обычных
    арифметических действий. Об этом факте редко вспоминают, да и
    работать с ними умеет далеко не каждый, но порой они бывают очень
    актуальны, особенно при частой работе с числами кратными двойке.&lt;/li&gt;
&lt;li&gt;Угадайте, что делает интерпретатор при виде надписи &lt;strong&gt;&lt;span style="color: blue"&gt;1&lt;/span&gt;/&lt;span style="color: blue"&gt;2&lt;/span&gt;&lt;/strong&gt;?
    Правильно: делит &lt;strong&gt;&lt;span style="color: blue"&gt;1&lt;/span&gt;&lt;/strong&gt; на &lt;strong&gt;&lt;span style="color: blue"&gt;2&lt;/span&gt;&lt;/strong&gt;. Зачем лишний раз утруждать его,
    когда можно написать просто половину - &lt;strong&gt;&lt;span style="color: blue"&gt;0.5&lt;/span&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;При возвращении значения переменной из функции при помощи &lt;strong&gt;&lt;span style="color: #17349c"&gt;global&lt;/span&gt;&lt;/strong&gt; выполняется на порядок больше
    действий, чем при классическом &lt;strong&gt;&lt;span style="color: #17349c"&gt;return&lt;/span&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Конечно же фраза &lt;strong&gt;&lt;span style="color: blue"&gt;\$array&lt;/span&gt;[text];&lt;/strong&gt;
    интерпритируется практически точно так же, как и &lt;strong&gt;&lt;span style="color: blue"&gt;\$array&lt;/span&gt;[&lt;span style="color: red"&gt;'text'&lt;/span&gt;];&lt;/strong&gt;, но зачем выполнять лишнее
    преобразование из необъявленной константы в строку, проверять, что
    такой константы все же не существует, выводить сообщение типа
    &lt;strong&gt;E_NOTICE&lt;/strong&gt;, если можно всего этого не делать?&lt;/li&gt;
&lt;li&gt;По возможности не используйте &lt;strong&gt;&lt;span style="color: #17349c"&gt;require_once&lt;/span&gt;();&lt;/strong&gt; или &lt;strong&gt;&lt;span style="color: #17349c"&gt;include_once&lt;/span&gt;();&lt;/strong&gt; неоднократно по
    отношению к одному и тому же файлу. При отсутствии какого-либо
    эффекта, попусту тратится время на обработку повторного запроса.&lt;/li&gt;
&lt;li&gt;Даже "безобидных" ошибок стоит избегать, лишняя проаерка потратит не
    так много процессорного времени, как генерирование достаточно
    длинного сообщения об ошибке и вывод его в &lt;em&gt;stdout&lt;/em&gt;, &lt;em&gt;stderr&lt;/em&gt; или
    &lt;em&gt;лог-файл&lt;/em&gt;, а также не стоит забывать, что даже "безобидные" ошибки
    могут стать потенциальной угрозой безопасности приложения вцелом.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;В заключении...&lt;/h4&gt;
&lt;p&gt;...хотелось бы упомянуть одну из первых статей по
&lt;a href="/tag/optimizaciya/"&gt;оптимизации&lt;/a&gt; &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt;, которые мне доводилось
читать, до сих пор храню ссылку на нее в bookmark'ах, именно она и
выступала в роли &lt;em&gt;&lt;a href="https://www.insight-it.ru/goto/ce3d47c9/" rel="nofollow" target="_blank" title="http://mgccl.com/php-speed-freaks"&gt;одного из основных источников
информации&lt;/a&gt;&lt;/em&gt; для этого текста. В
качестве возможных вариантов продолжения чтения про &lt;a href="/tag/php/"&gt;PHP&lt;/a&gt;
хотелось бы предложить Вам соответствующие &lt;a href="/category/php/"&gt;раздел сайта&lt;/a&gt;, &lt;a href="https://www.insight-it.ru/dzhentelmenskij-nabor-php-programmista/"&gt;серию
статей&lt;/a&gt;, &lt;a href="/tag/php/"&gt;тэг&lt;/a&gt; и
&lt;a href="/feed/"&gt;RSS-ленту&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 07 Feb 2008 15:39:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-02-07:php/2008/na-puti-k-idealu/</guid><category>online</category><category>PHP</category><category>интернет</category><category>информационные технологии</category><category>код</category><category>кодинг</category><category>оптимизация</category><category>Программирование</category><category>производительность</category></item><item><title>Архитектура Google</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-google/</link><description>&lt;p&gt;&lt;em&gt;Эта статья датируется 2008 годом, новая версия: &lt;a href="https://www.insight-it.ru/highload/2011/arkhitektura-google-2011/"&gt;Архитектура Google 2011&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="/tag/google/"&gt;Google&lt;/a&gt;&lt;/strong&gt; - Король масштабируемости.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Каждый хоть раз слышал о &lt;a href="/tag/google/"&gt;Google&lt;/a&gt; благодаря их
всеобъемлющему, "умному" и быстрому поисковому сервису, но ни для кого
не секрет, что они не ограничиваются только им. Их платформа для
построения масштабируемых приложений позволяет выпускать множество
удивительно конкурентноспособных интернет-приложений, работающих на
уровне всего Интернета вцелом. Они ставят перед собой цель постоянно
строить все более и более производительную и масштабируемую архитектуру
для поддержки своих продуктов. Как же им это удается?
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="istochniki-informatsii"&gt;Источники информации&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Сразу хочу сказать, что эта запись является переводом с английского,
автор &lt;a href="https://www.insight-it.ru/goto/31bfd110/" rel="nofollow" target="_blank" title="http://highscalability.com/google-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 Hoff&lt;/a&gt;. Оригинал написан приблизительно в середине 2007 года, но по-моему до сих пор очень даже актуально.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Далее следует перечисление источников информации из оригинала:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/741bec4c/" rel="nofollow" target="_blank" title="http://video.google.com/videoplay?docid=-5699448884004201579"&gt;Video: Построение больших систем в Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/fae0d413/" rel="nofollow" target="_blank" title="http://labs.google.com/papers/gfs.html"&gt;Google Lab: Файловая система Google (GFS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/39138d08/" rel="nofollow" target="_blank" title="http://labs.google.com/papers/mapreduce.html"&gt;Google Lab: MapReduce: упрощенная обработка данных на больших кластерах&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/8667b351/" rel="nofollow" target="_blank" title="http://labs.google.com/papers/bigtable.html"&gt;Google Lab: BigTable.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/dab5470e/" rel="nofollow" target="_blank" title="http://video.google.com/videoplay?docid=7278544055668715642"&gt;Video: BigTable: система распределенного хранения данных.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/87fff9b2/" rel="nofollow" target="_blank" title="http://www.baselinemag.com/article2/0,1540,1985514,00.asp"&gt;Как работает Google&lt;/a&gt;
    от David Carr в Baseline Magazine.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/a426f3de/" rel="nofollow" target="_blank" title="http://labs.google.com/papers/sawzall.html"&gt;Google Lab: интерпретирование данных. Параллельный анализ с помощью Sawzall.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/ed8bca67/" rel="nofollow" target="_blank" title="http://www.25hoursaday.com/weblog/2007/06/25/GoogleScalabilityConferenceTripReportMapReduceBigTableAndOtherDistributedSystemAbstractionsForHandlingLargeDatasets.aspx"&gt;Записи с конференции по масштабированию от Dare Obasonjo.&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/python/"&gt;Python&lt;/a&gt;,
    &lt;a href="/tag/java/"&gt;Java&lt;/a&gt;, &lt;a href="/tag/c/"&gt;C++&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="chto-vnutri"&gt;Что внутри?&lt;/h3&gt;
&lt;h4&gt;Статистика&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;На 2006 год система включала в себя 450000 недорогих серверов&lt;/li&gt;
&lt;li&gt;За 2005 год было проиндексировано 8 миллиардов страниц. На данный
    момент&amp;hellip; кто знает?&lt;/li&gt;
&lt;li&gt;На момент написания оригинала Google включает в себя более 200
    &lt;a href="/tag/gfs/"&gt;GFS&lt;/a&gt; кластеров. Один кластер может состоять из 1000 или
    даже 5000 компьютеров&lt;/li&gt;
&lt;li&gt;Десятки и сотни тысяч компьютеров получают данные из &lt;a href="/tag/gfs/"&gt;GFS&lt;/a&gt;
    кластеров, которые насчитывают более 5 петабайт дискового
    пространства. Суммарные пропускная способность операций записи и
    чтения между дата центрами может достигать 40 гигабайт в секунду&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/bigtable/"&gt;BigTable&lt;/a&gt; позволяет хранить миллиарды ссылок (URL),
    сотни терабайт снимков со спутников, а также настройки миллионов
    пользователей&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;// Цифры не первой свежести конечно, но тоже неплохо.&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;Стек&lt;/h4&gt;
&lt;p&gt;&lt;a href="/tag/google/"&gt;Google&lt;/a&gt; визуализирует свою инфраструктуру в виде
трехслойного стека:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Продукты:&lt;/em&gt; поиск, реклама, электронная почта, карты, видео, чат,
    блоги&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Распределенная инфраструктура системы:&lt;/em&gt; &lt;a href="/tag/gfs/"&gt;GFS&lt;/a&gt;,
    &lt;a href="/tag/mapreduce/"&gt;MapReduce&lt;/a&gt; и &lt;a href="/tag/bigtable/"&gt;BigTable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Вычислительные платформы:&lt;/em&gt; множество компьютеров во множестве
    датацентров&lt;/li&gt;
&lt;li&gt;Легкое развертывание для компании при низком уровне издержек&lt;/li&gt;
&lt;li&gt;Больше денег вкладывается в оборудование для исключения возможности
    потерь данных&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Надежное хранение данных с помощью &lt;a href="/tag/gfs/"&gt;GFS&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Надежное масштабируемое хранение данных крайне необходимо для любого
    приложения. &lt;strong&gt;GFS&lt;/strong&gt; является основой их платформы хранения
    информации&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/tag/gfs/"&gt;GFS&lt;/a&gt;&lt;/strong&gt; - большая распределенная файловая система, способная хранить и обрабатывать огромные объемы информации&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Зачем строить что-либо самим вместо того, чтобы просто взять это с полки?&lt;/em&gt; Они контролируют абсолютно всю систему и именно эта платформа отличает их от всех остальных.&lt;/p&gt;
&lt;p&gt;Она предоставляет:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;высокую надежность дата центров&lt;/li&gt;
&lt;li&gt;масштабируемость до тысяч сетевых узлов
&amp;ndash; высокую пропускную способность операций чтения и записи&lt;/li&gt;
&lt;li&gt;поддержку больших блоков данных, размер которых может измеряться в
гигабайтах&lt;/li&gt;
&lt;li&gt;эффективное распределение операций между датацентрами для
избежания возникновения "узких мест" в системе&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;В системе существуют мастер-сервера и сервера, собственно хранящие
    информацию:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Мастер-сервера хранят метаданные для всех файлов. Сами данные
    хранятся блоками по 64 мегабайта на остальных серверах. Клиенты
    могут выполнять операции с метаданными на мастер-серверах, чтобы
    узнать на каком именно сервере расположены необходимые данные.&lt;/li&gt;
&lt;li&gt;Для обеспечения надежности один и тот же блок данных хранится
    в трех экземплярах на разных серверах, что обеспечивает
    избыточность на случай сбоев в работе какого-либо сервера.&lt;/li&gt;
&lt;li&gt;Новые приложения могут пользоваться как существующими
    кластерами, так и новыми, созданными специально для них.&lt;/li&gt;
&lt;li&gt;Ключ успеха заключается в том, чтобы быть уверенными в том,
    что у людей есть достаточно вариантов выбора для реализации их
    приложений. &lt;strong&gt;&lt;a href="/tag/gfs/"&gt;GFS&lt;/a&gt;&lt;/strong&gt; может быть настроена для
    удовлетворения нужд любого конкретного приложения.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Работаем с данными при помощи MapReduce&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Теперь, когда у нас есть отличная система хранения, что же делать с
    такими объемами данных? Допустим, у нас есть много терабайт данных,
    равномерно распределенных между 1000 компьютерами. Коммерческие базы
    данных не могут эффективно масштабироваться до такого уровня, именно
    в такой ситуации в дело вступает технология
    &lt;strong&gt;&lt;a href="/tag/mapreduce/"&gt;MapReduce&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/tag/mapreduce/"&gt;MapReduce&lt;/a&gt;&lt;/strong&gt; является программной моделью и
    соответствующей реализацией обработки и генерации больших наборов
    данных. Пользователи могут задавать функцию, обрабатывающую пары
    ключ/значение для генерации промежуточных аналогичных пар, и
    сокращающую функцию, которая объединяет все промежуточные значения,
    соответствующие одному и тому же ключу. Многие реальные задачи могут
    быть выражены с помощью этой модели. Программы, написанные в таком
    функциональном стиле автоматически распараллеливаются и адаптируются
    для выполнения на обширных кластерах. Система берет на себя детали
    разбиения входных данных на части, составления расписания выполнения
    программ на различных компьютерах, управления ошибками, и
    организации необходимой коммуникации между компьютерами. Это
    позволяет программистам, не обладающим опытом работы с параллельными
    и распределенными системами, легко использовать все ресурсы больших
    распределенных систем.&lt;/li&gt;
&lt;li&gt;Зачем использовать &lt;strong&gt;&lt;a href="/tag/mapreduce/"&gt;MapReduce&lt;/a&gt;&lt;/strong&gt;?
    &amp;ndash; Отличный способ распределения задач между множеством компьютеров
    &amp;ndash; Обработка сбоев в работе
    &amp;ndash; Работа с различными типами смежных приложений, таких как поиск или
    реклама. Возможно предварительное вычисление и обработка данных,
    подсчет количества слов, сортировка терабайт данных и так далее
    &amp;ndash; Вычисления автоматически приближаются к источнику ввода-вывода&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/tag/mapreduce/"&gt;MapReduce&lt;/a&gt;&lt;/strong&gt; использует три типа серверов:&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Master:&lt;/em&gt; назначают задания остальным типам серверов, а также
следят за процессом их выполнения&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Map:&lt;/em&gt; принимают входные данные от пользователей и обрабатывают
их, результаты записываются в промежуточные файлы&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Reduce:&lt;/em&gt; принимают промежуточные файлы от Map-серверов и
сокращают их указанным выше способом&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Например, мы хотим посчитать количество слов на всех страницах. Для
    этого нам необходимо передать все страницы, хранимые в &lt;strong&gt;GFS&lt;/strong&gt;, на
    обработку в &lt;strong&gt;MapReduce&lt;/strong&gt;. Этот процесс будет происходить на тысячах
    машин одновременно с полной координацией действий, в соответствии с
    автоматически составленным расписанием выполняемых работ, обработкой
    потенциальных ошибок, и передачей данных выполняемыми автоматически.&lt;ul&gt;
&lt;li&gt;Последовательность выполняемых действий выглядела бы следующим
образом: &lt;code&gt;GFS &amp;rarr; Map &amp;rarr; перемешивание &amp;rarr; Reduce &amp;rarr; запись результатов обратно в GFS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Технология &lt;strong&gt;MapReduce&lt;/strong&gt; состоит из двух компонентов:
соответственно &lt;em&gt;map&lt;/em&gt; и &lt;em&gt;reduce&lt;/em&gt;. Map отображает один набор данных в
другой, создавая тем самым пары ключ/значение, которпыми в нашем
случае являются слова и их количества.&lt;/li&gt;
&lt;li&gt;В процессе перемешивания происходит агрегирование типов ключей.&lt;/li&gt;
&lt;li&gt;Reduction в нашем случае просто суммирует все результаты и
возвращает финальный результат.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;В процессе индексирования &lt;a href="/tag/google/"&gt;Google&lt;/a&gt; подвергает поток
    данных обработке около 20 разных механизмов сокращения. Сначала идет
    работа над всеми записями и агрегированными ключами, после чего
    результат передается следующему механизму и второй механизм уже
    работает с результатами работы первого, и так далее.&lt;/li&gt;
&lt;li&gt;Программы могут быть очень маленькими, всего лишь от 20 до 50 строк
    кода.&lt;/li&gt;
&lt;li&gt;Единственной проблемой могут быть "отстающие компьютеры". Если один
    компьютер работает существенно медленнее, чем все остальные, это
    будет задерживать работу всей системы в целом.&lt;/li&gt;
&lt;li&gt;Транспортировка данных между серверами происходит в сжатом виде.
    Идея заключается в том, что ограничивающим фактором является
    пропускная способность канала и ввода-вывода, что делает резонным
    потратить часть процессорного времени на компрессию и декомпрессию
    данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Хранение структурированных данных в BigTable&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BigTable&lt;/strong&gt; является крупномасштабной, устойчивой к потенциальным
    ошибкам, самоуправляемой системой, которая может включать в себя
    терабайты памяти и петабайты данных, а также управлять миллионами
    операций чтения и записи в секунду.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BigTable&lt;/strong&gt; представляет собой распределенный механизм хэширования,
    построенный поверх &lt;strong&gt;&lt;a href="/tag/gfs/"&gt;GFS&lt;/a&gt;&lt;/strong&gt;, а вовсе не реляционную базу
    данных и, как следствие, не поддерживает &lt;a href="/tag/sql/"&gt;SQL&lt;/a&gt;-запросы и
    операции типа Join.&lt;/li&gt;
&lt;li&gt;Она предоставляет механизм просмотра данных для получения доступа к
    структурированным данным по имеющемуся ключу. &lt;strong&gt;&lt;a href="/tag/gfs/"&gt;GFS&lt;/a&gt;&lt;/strong&gt;
    хранит данные не поддающиеся пониманию, хотя многим приложениям
    необходимы структурированные данные.&lt;/li&gt;
&lt;li&gt;Коммерческие базы данных попросту не могут масштабироваться до
    такого уровня и, соответственно, не могут работать с тысячами машин
    одновременно.&lt;/li&gt;
&lt;li&gt;С помощью контролирования своих низкоуровневых систем хранения
    данных, &lt;a href="/tag/google/"&gt;Google&lt;/a&gt; получает больше возможностей по
    управлению и модификации их системой. Например, если им понадобится
    функция, упрощающая координацию работы между датацентрами, они
    просто могут написать ее и внедрить в систему.&lt;/li&gt;
&lt;li&gt;Подключение и отключение компьютеров к функционирующей системе никак
    не мешает ей просто работать.&lt;/li&gt;
&lt;li&gt;Каждый блок данных хранится в ячейке, доступ к которой может быть
    предоставлен как по ключу строки или столбца, так и по временной
    метке.&lt;/li&gt;
&lt;li&gt;Каждая строка может храниться в одной или нескольких таблицах.
    Таблицы реализуются в виде последовательности блоков по 64
    килобайта, организованных в формате данных под названием
    &lt;strong&gt;SSTable&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;В &lt;strong&gt;&lt;a href="/tag/bigtable/"&gt;BigTable&lt;/a&gt;&lt;/strong&gt; тоже используется три типа серверов:&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Master:&lt;/em&gt; распределяют таблицы по Tablet-серверам, а также следят
за расположением таблиц и перераспределяют задания в случае
необходимости.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Tablet:&lt;/em&gt; обрабатывают запросы чтения/записи для таблиц. Они
разделяют таблицы, когда те превышают лимит размера (обычно 100-200
мегабайт). Когда такой сервер прекращает функционирование по
каким-либо причинам, 100 других серверов берут на себя по одной
таблице и система продолжает работать как-будто ничего не произошло.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Lock:&lt;/em&gt; формируют распределенный сервис ограничения одновременного
доступа. Операции открытия таблицы для записи, анализа
Master-сервером или проверки доступа должны быть
взаимоисключающими.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Локальная группировка может быть использована для физического
    хранения связанных данных вместе, чтобы обеспечить лучшую
    локализацию ссылок на данные.&lt;/li&gt;
&lt;li&gt;Таблицы по возможности кэшируются в оперативной памяти серверов.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="oborudovanie"&gt;Оборудование&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Как эффективно организовать большую группу компьютеров с точки
    зрения издержек и производительности?&lt;/li&gt;
&lt;li&gt;Используется самое обыкновенное ультра-дешевое оборудование и поверх
    него строится программное обеспечение, способное спокойно пережить
    смерть любой части оборудования.&lt;/li&gt;
&lt;li&gt;Тысячекратный рост вычислительной мощности может быть достигнут с
    издержками в 33 раза меньшими, если воспользоваться толерантной к
    сбоям инфраструктурой, по сравнению с инфраструктурой, построенной
    на высоконадежных компонентах. Надежность строится поверх ненадежных
    компонентов.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/linux/"&gt;Linux&lt;/a&gt;, домашнее размещение серверов, материнские платы
    предназначенные для персональных компьютеров, дешевые средства
    хранения данных.&lt;/li&gt;
&lt;li&gt;Цена за каждый ватт энергии в расчете на производительность не
    становится меньше, что ведет к большим проблемам связанным с
    энергообеспечением и охлаждением.&lt;/li&gt;
&lt;li&gt;Использование совместного размещения в своих и арендуемых
    датацентрах.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="raznoe"&gt;Разное&lt;/h3&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;
&lt;h3 id="puti-razvitiia"&gt;Пути развития&lt;/h3&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;
&lt;h3 id="podvodim-itogi"&gt;Подводим итоги&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Инфраструктура может быть конкурентным преимуществом.&lt;/strong&gt; Это
    определенно так для Google. Они могут выпускать новые интернет
    сервисы быстрее, с меньшими издержками, на таком уровне, что мало
    кто сможет составить им конкуренцию. Подход многих компаний сильно
    отличается от подхода &lt;a href="/tag/google/"&gt;Google&lt;/a&gt;, эти компании
    рассматривают инфраструктуру как статью расходов, они обычно
    используют совсем другие технологии и совсем не задумываются о
    планировании и организации своей системы. Google позиционирует себя
    как компанию по построению систем, что является очень современным
    подходом к разработке программного обеспечения.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Охватывание нескольких дата центров до сих пор является нерешенной проблемой.&lt;/strong&gt; Большинство сайтов базируется в одном или двух дата
    центрах. Полное распределение сайта между несколькими датацентрами
    является хитрой задачей.&lt;/li&gt;
&lt;li&gt;Взгляните на &lt;em&gt;&lt;a href="https://www.insight-it.ru/goto/30a7481/" rel="nofollow" target="_blank" title="http://hadoop.apache.org/core/"&gt;Hadoop&lt;/a&gt;&lt;/em&gt;, если у Вас
    нет времени на собственноручное построение всей архитектуры с нуля.
    &lt;em&gt;Hadoop&lt;/em&gt; является opensource воплощением в жизнь многих идей здесь
    представленных.&lt;/li&gt;
&lt;li&gt;Часто недооцениваемым преимуществом платформенного подхода является
    тот факт, что даже неопытные разработчики могут быстро и качественно
    реализовывать трудоемкие приложения на базе платформы. Но если бы
    каждый проект требовал одинаково распределенной архитектуры, то это
    создало бы много проблем, так как люди, которые понимают как это
    делается, являются достаточно большой редкостью.&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;/li&gt;
&lt;li&gt;Всему, что было сделано Google, предшествовало искусство, а не
    только крупномасштабное развертывание системы.&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>Thu, 31 Jan 2008 18:05:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-31:highload/2008/arkhitektura-google/</guid><category>BigTable</category><category>featured</category><category>GFS</category><category>Google</category><category>MapReduce</category><category>online</category><category>Sawzall</category><category>архитектура</category><category>архитектура Google</category><category>интернет</category><category>кластер</category><category>Масштабируемость</category><category>поиск</category><category>сервер</category><category>хранение данных</category></item><item><title>Защита интернет-ресурсов в картинках</title><link>https://www.insight-it.ru//php/2008/zashhita-internet-resursov-v-kartinkax/</link><description>&lt;p&gt;Этой статьей мне хотелось бы открыть мою первую &lt;a href="https://www.insight-it.ru/dzhentelmenskij-nabor-php-programmista/"&gt;серию статей "Джентельменский набор PHP программиста"&lt;/a&gt;. Как и во всей остальной серии здесь пойдет речь о программировании на PHP для интернет-проектов, но в каждой статье я буду выбирать один узкий аспект
и на протяжении всей статьи буду стараться показать возможные варианты
его реализации и применения.&lt;/p&gt;
&lt;p&gt;Сегодня таким аспектом станет защита интернет-ресурса от возможного
возникновения нежелательного контента со стороны пользователей с помощью
технологии captcha (точнее о "графическом" варианте ее реализации), о
которой уже &lt;a href="https://www.insight-it.ru/security/2008/otkuda-voznikaet-spam-i-kak-s-nim-borotsya/"&gt;неоднократно шла речь&lt;/a&gt;.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;Начать имеет смысл с небольшого напоминания о принципе работы этой
технологии: перед потенциальным посетителем ставится некое препятствие,
которое ему необходимо преодолеть для продолжения работы с
интернет-ресурсом. Существует множество &lt;a href="https://www.insight-it.ru/security/2008/7-sposobov-zashhitit-svoj-internet-resurs-ot-nezhelatelnoj-informacii/"&gt;вариантов такого рода
препятствий&lt;/a&gt;.
Как уже упоминалось, сегодня мы будем реализовывать только один наиболее
распространенный тип - "графический". В простейшем случае он
представляет собой просьбу переписать с изображения некий набор
символов. В процессе генерирования изображения, символы сильно
искажаются с целью предотвращения возможности их распознавания любой
программой с помощью технологии OCR.&lt;/p&gt;
&lt;h3 id="podgotovka"&gt;Подготовка&lt;/h3&gt;
&lt;p&gt;Прежде чем начать писать код стоит более детально осознать какая же цель
перед нами стоит: нам необходимо написать скрипт, генерирующий
искаженное изображение некоторого набора символов и незаметно для
пользователя передающее этот набор какому-либо другому скрипту, который
нас пока мало интересует, но ясно лишь, что собственно проверкой будет
заниматься именно он на основе данных полученных от пользователя и
нашего скрипта. Способов исказить текст существует огромное количество,
в ходе написания статьи постараюсь упомянуть несколько самых эффективных
и широкоиспользуемых из них.&lt;/p&gt;
&lt;p&gt;В первую очередь стоит подготовить некий каркас кода, который мы будем
впоследствии заполнять. Он будет состоять из двух частей:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Описание класса, генерирующего изображение&lt;/li&gt;
&lt;li&gt;Файл, который будет вызываться browser'ом. В нем будет подключено
    описание нашего класса, выбор настроек данного конкретного
    изображения и выполнено создание объекта класса, в соответствии с
    выбранными настройками.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Для начала давайте определимся со списком параметров, которые будет
иметь наш класс. Во-первых, нужно решить какой текст будет
генерироваться, самый простой и распространенный вариант - просто четыре
цифры, я в примере на нем и остановлюсь, а реально же можно использовать
абсолютно любые приходящие в голову варианты. Во-вторых, размеры
изображения и текста - их лучше подобрать фиксированными так, чтобы было
максимально читабельно, при минимальных размерах изображения, но при
желании можно сделать и возможность изменения их извне. Последним в
списке параметров будет цвет фона и текста - их как раз лучше задавать
вне класса, так как основным действием, необходимым при переносе этого
скрипта с одного сайт на другой - подбор используемых цветов таким
образом, чтобы изображение смотрелось не очень ужасно при текущем
варианте дизайна, изменения в других параметрах требуются на порядок
реже.&lt;/p&gt;
&lt;p&gt;Итак, создание объекта будем производить максимально простым способом,
параметрами укажем белый и черный цвета. Заготовка для самого класса будет выглядеть примерно следующим образом
(предположим, что он хранится в файле &lt;em&gt;captcha.class.php&lt;/em&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Captcha&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// генерируемый текст&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$bgcol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// основной цвет фона&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$fgcol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// основной цвет текста&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// высота изображения&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// ширина изображения&lt;/span&gt;
   &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$bgcol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$fgcol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// конструктор, вызывается при создании экземпляра класса&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="zadaem-parametry"&gt;Задаем параметры&lt;/h3&gt;
&lt;p&gt;Первым делом при создании объекта необходимо задать остальные параметры,
размеры изображения можно указать прямо в конструкторе, а для генерации
текста лучше написать отдельную функцию:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;// генерация изображения&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$fgcol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$bgcol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;generateSymbols&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateSymbols&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="c1"&gt;// генерация четырех цифр&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;leadingZero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;leadingZero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// дополнения числа num лидирующими нулями&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;                        &lt;span class="c1"&gt;// до длины length&lt;/span&gt;
  &lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;strrev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="o"&gt;.=&lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;strrev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Этих данных нам должно хватить для написания функции, генерирующей
изображение.&lt;/p&gt;
&lt;h3 id="generiruem-izobrazhenie"&gt;Генерируем изображение&lt;/h3&gt;
&lt;p&gt;Если забыть, что текст необходимо искажать, то функция, генерирующая
изображение выглядела бы просто как:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;// генерация изображения&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="o"&gt;=@&lt;/span&gt;&lt;span class="nb"&gt;imagecreatetruecolor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nv"&gt;$bcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
   &lt;span class="nv"&gt;$fcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
   &lt;span class="nb"&gt;imagefill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$bcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nb"&gt;imagettftext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$fcol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"./font/font_name.ttf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: image/png'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nb"&gt;imagepng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nb"&gt;imagedestroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="card yellow lighten-4"&gt;&lt;div class="card-content"&gt;
В данном методе используются
функции модуля PHP под названием GD, основывающегося на одноименной
библиотеке, убедитесь, что на Вашем хостинге этот модуль
установлен.
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Реально же ей пользоваться не стоит - такое изображение с легкостью
поддается OCR. Полученный текст необходимо тем или иным образом
исказить. Для вывода изображения используется формат PNG, но никто не
мешает воспользоваться JPEG или GIF, для этого достаточно заменить везде
png на название соответствующего формата.&lt;/p&gt;
&lt;h3 id="iskazhaem-tekst"&gt;Искажаем текст&lt;/h3&gt;
&lt;p&gt;Вот списочек тех, способов искажения текста, которыми я буду
пользоваться в примере, пользоваться всеми сразу естественно никто не
заставляет, да и включив воображение можно придумать много модификаций
приведенных мной способов или абсолютно других:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;использование нестандартных шрифтов&lt;/em&gt; - функция imagettftext
    позволяет использовать произвольный шрифт в формате Truetype, чем и
    необходимо воспользоваться. В Сети можно найти огромное количество
    бесплатных шрифтов в этом формате. По возможности стоит выбирать
    шрифты, максимально не похожие на любой стандартный, но при этом
    легко читающиеся.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;использование нескольких шрифтов&lt;/em&gt; - сделав подборку подходящих
    шрифтов, можно не останавливаться на каком-то одном, а сделать выбор
    текущего шрифта случайным из списка.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;случайный выбор цветов&lt;/em&gt; - усложняет работу OCR и в большинстве
    случаев не сильно мешает восприятию человеком.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;случайное расположение символов&lt;/em&gt; - еще один способ усложнить работу
    программам, пытающимся прочитать текст.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;неравномерный фон&lt;/em&gt; - изобразив на фоне какой-либо абстрактный набор
    любых фигур, можно заставить программу-посетителя подумать что
    какая-то часть из них является символом. Например, пересечение двух
    прямых линий часто распознается как буква T или L. Неплохим
    вариантом является написание на фоне других символов другим цветом,
    сильно отличающимся от основного и близким к цвету фона.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для начала этого вполне хватит, перейдем к реализации, в комментариях
постараюсь указывать все особенности:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// генерация изображения&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="o"&gt;=@&lt;/span&gt;&lt;span class="nb"&gt;imagecreatetruecolor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// создаем пустое изображение&lt;/span&gt;
   &lt;span class="nv"&gt;$mcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// выбираем случайным образом&lt;/span&gt;
   &lt;span class="nv"&gt;$kcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// несколько цветов&lt;/span&gt;
   &lt;span class="nv"&gt;$lcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nv"&gt;$bcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
   &lt;span class="nv"&gt;$fcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
   &lt;span class="nb"&gt;imagefill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$bcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// заполняем изображение фоном&lt;/span&gt;
   &lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// список названий подходящих шрифтов&lt;/span&gt;
   &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;  &lt;span class="c1"&gt;// наугад выбираем из них один&lt;/span&gt;
   &lt;span class="nv"&gt;$m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$lcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// создаем на фоне несколько линий&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$lcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// и еще несколько&lt;/span&gt;
   &lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;   Генерируем текст: две строки на фон, а также интересующие нас символы по одному.&lt;/span&gt;
&lt;span class="cm"&gt;   */&lt;/span&gt;
   &lt;span class="nb"&gt;imagettftext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$kcol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"./font/"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;".ttf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;randomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="nb"&gt;imagettftext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$mcol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"./font/"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;".ttf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;randomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$istring&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="nb"&gt;imagettftext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;0.73&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$fcol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"./font/"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;".ttf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$m&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$mcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// еще линии&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$mcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// и еще немного&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$fcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// и еще чуть-чуть&lt;/span&gt;
   &lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: image/png'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nb"&gt;imagepng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nb"&gt;imagedestroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;randomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// генерируем случайный набор символов заданной длины&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ!@#$%^&amp;amp;**()-=_+.,&amp;lt;&amp;gt;/\|;:"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="o"&gt;.=&lt;/span&gt;&lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;mt_rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Стоит заметить, что конкретные цифры необходимо подбирать индивидуально,
в примере они указаны абсолютно произвольно. Использование конкретно
этих же цифр приведет к далеко не самым лучшим результатам.&lt;/p&gt;
&lt;h3 id="sborka"&gt;Сборка&lt;/h3&gt;
&lt;p&gt;Не стоит забывать, что помимо генерации самого изображения, необходимо
передать написанный текст другому скрипту, который будет сверять данные.
Удобнее всего это делать через глобальный массив &lt;code&gt;$_SESSION&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Собрав все написанное выше, и учтя передачу текста, можно получить
следующий класс:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Captcha&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// генерируемый текст&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$bgcol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// основной цвет фона&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$fgcol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// основной цвет текста&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// высота изображения&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// ширина изображения&lt;/span&gt;
   &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$bgcol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$fgcol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// конструктор, вызывается при создании экземпляра класса&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$fgcol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$bgcol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;generateSymbols&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// генерация изображения&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="o"&gt;=@&lt;/span&gt;&lt;span class="nb"&gt;imagecreatetruecolor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// создаем пустое изображение&lt;/span&gt;
      &lt;span class="nv"&gt;$mcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// выбираем случайным образом&lt;/span&gt;
      &lt;span class="nv"&gt;$kcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// несколько цветов&lt;/span&gt;
      &lt;span class="nv"&gt;$lcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;$bcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;bgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="nv"&gt;$fcol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;imagecolorallocate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fgcol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="nb"&gt;imagefill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$bcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// заполняем изображение фоном&lt;/span&gt;
      &lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// список названий подходящих шрифтов&lt;/span&gt;
      &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;  &lt;span class="c1"&gt;// наугад выбираем из них один&lt;/span&gt;
      &lt;span class="nv"&gt;$m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$lcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// создаем на фоне несколько линий&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$lcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// и еще несколько&lt;/span&gt;
      &lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;      Генерируем текст: две строки на фон, а также интересующие нас символы по одному.&lt;/span&gt;
&lt;span class="cm"&gt;      */&lt;/span&gt;
      &lt;span class="nb"&gt;imagettftext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$kcol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"./font/"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;".ttf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;randomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="nb"&gt;imagettftext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$mcol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"./font/"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;".ttf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;randomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$istring&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;imagettftext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;0.73&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$fcol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"./font/"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;".ttf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$m&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$mcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// еще линии&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$mcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// и еще немного&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;imageline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$fcol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// и еще чуть-чуть&lt;/span&gt;
      &lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: image/png'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;imagepng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;imagedestroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$im&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateSymbols&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="c1"&gt;// генерация четырех цифр&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;leadingZero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;leadingZero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// дополнения числа num лидирующими нулями&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;                        &lt;span class="c1"&gt;// до длины length&lt;/span&gt;
      &lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;strrev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="o"&gt;.=&lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;strrev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;randomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// генерируем случайный набор символов заданной длины&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ!@#$%^&amp;amp;**()-=_+.,&amp;lt;&amp;gt;/\|;:"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="o"&gt;.=&lt;/span&gt;&lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;mt_rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Слегка доработав его и приведя в более подходящий вид, можно добиться
генерации изображений, выглядящих например вот так:&lt;/p&gt;
&lt;p&gt;&lt;img alt="CAPTCHA Sample" class="responsive-img" src="https://www.insight-it.ru/images/captcha-sample.png" title="Пример получающегося изображения"/&gt;&lt;/p&gt;
&lt;p&gt;Специально не выкладываю уже доведенный до ума класс, чтобы у читателей
не возникало желания просто взять и воспользоваться им, это приведет
лишь к очередной серии captcha-клонов.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sun, 13 Jan 2008 22:30:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-13:php/2008/zashhita-internet-resursov-v-kartinkax/</guid><category>captcha</category><category>OCR</category><category>online</category><category>PHP</category><category>защита интернет-ресурсов</category><category>интернет</category><category>класс</category><category>код</category><category>кодинг</category><category>ООП</category></item><item><title>Related Posts 2.04. Русская версия</title><link>https://www.insight-it.ru//misc/2008/related-posts-204-russkaya-versiya/</link><description>&lt;div class="card orange darken-3"&gt;
&lt;p&gt;&lt;div class="card-content white-text center"&gt;
&lt;strong&gt;Данный пост морально устарел и оставлен лишь из исторических соображений.&lt;/strong&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;На досуге перевел на русский язык плагин под названием &lt;a href="https://www.insight-it.ru/goto/3db242e9/" rel="nofollow" target="_blank" title="http://wasabi.pbwiki.com/Related%20Entries"&gt;Related Posts&lt;/a&gt;, являющийся альтернативой одноименной функции из Simple Tags, с несколько другим алгоритмом. Не вижу ни одной причины почему бы не выложить в публичный доступ то, что у меня получилось. О качестве перевода не мне конечно судить, но по-моему вполне адекватно получилось.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3 id="instruktsiia-po-ustanovke"&gt;Инструкция по установке&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Разместите файл &lt;code&gt;related-posts.php&lt;/code&gt; в ваш каталог &lt;code&gt;/wp-content/plugins/&lt;/code&gt; и активируйте плагин.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;a) В меню Плагины появится пункт &amp;ldquo;Настройка Related Posts&amp;rdquo;. Если Вы
    впервые устанавливаете этот plug-in на этот блог нажмите на ссылку а
    нижней части страницы настроек плагина. Это действие необходимо
    производить только при первичной установке. Если в автоматическом режиме
    не удалось составить индекс, то читайте дальше &amp;hellip;
    b) В случае если автоматической создание индекса не удалось, Вам
    придется создать его вручную. Не волнуйтесь - это не трудно. Необходимо
    зайти в Вашу базу данных через phpMyAdmin или любым другим известным Вам
    способом и выполнить следующий запрос (просто скопируйте и вставьте):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;wp_posts&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;
&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="n"&gt;FULLTEXT&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;post_related&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;post_name&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;post_content&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Замечание:&lt;/strong&gt; Возможно Вам придется заменить &lt;code&gt;wp_posts&lt;/code&gt; на что-либо
еще в случае если Вы используете другой префикс, что часто бывает,
когда установлено несколько копий WordPress на одном сервере.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Разместите вызов плагина внутри цикла WordPress, и вуаля - плагин работает!&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="parametry"&gt;Параметры&lt;/h3&gt;
&lt;p&gt;Начиная с версии 2.0 у Вас есть возможность изменять внешний вид и вывод
плагина с помощью страницы настроек. Последующее руководство же
предназначено для ручного изменения настроек.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$limit&lt;/code&gt; - Количество записей для отображения. (По-умолчанию: 5)
&lt;code&gt;$len&lt;/code&gt; - Длина отрывка из записи (количество слов). (По-умолчанию: 10)
&lt;code&gt;$before/after_title&lt;/code&gt; - Текст перед/после заголовка.
&lt;code&gt;$before/after_post&lt;/code&gt; - Текст перед/после отрывка записи, если
включено.
&lt;code&gt;$show_pass_post&lt;/code&gt; - Показывать/скрывать записи, защищенные паролем.
(По-умолчанию выключено)
&lt;code&gt;$show_excerpt&lt;/code&gt; - Показывать/скрывать отрывки из записей. (По-умолчанию
выключено)&lt;/p&gt;
&lt;p&gt;Например, можно создать непронумерванный список (вывод отсортирован по
количеству совпавших ключевых слов) состоящий максимум из 5 записей.&lt;/p&gt;
&lt;h3 id="ruchnaia-ustanovka-kliuchevykh-slov"&gt;Ручная установка ключевых слов&lt;/h3&gt;
&lt;p&gt;Это функция была написана человеком по имени &lt;a href="https://www.insight-it.ru/goto/d7f5a701/" rel="nofollow" target="_blank" title="http://mike.blogdns.org/mikelu/archives/2004/07/27/related-post-plugin-v13-en/"&gt;Mike&lt;/a&gt;
и позволят вручную &amp;ldquo;связывать&amp;rdquo; записи в случаях когда заголовок никак не
связан с содержанием записи.&lt;/p&gt;
&lt;p&gt;Ключевые слова обозначаются с помощью тэга &lt;code&gt;&amp;lt;!&amp;mdash;&amp;mdash;kw=keyword1 keyword2&amp;mdash;&amp;mdash;&amp;gt;&lt;/code&gt; размещенного внутри статьи. Плагин будет хранить эти
ключевые слова в отдельном поле и использовать их для поиска совпадений,
при их отсутствии используется заголовок.&lt;/p&gt;
&lt;h3 id="problemy-voprosy-predlozheniia"&gt;Проблемы / Вопросы / Предложения&lt;/h3&gt;
&lt;p&gt;Проблемы, вопросы и предложения, связанные с самим плагином имеет смысл
сообщать авторам плагина на http://www.w-a-s-a-b-i.com или
http://mike.blogdns.org/mikelu/.
Все что связано с переводом же - пишите мне в комментариях к этой теме.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Tue, 08 Jan 2008 00:15:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-08:misc/2008/related-posts-204-russkaya-versiya/</guid><category>Life</category><category>online</category><category>plug-in</category><category>related posts</category><category>WordPress</category><category>перевод</category><category>плагин</category></item><item><title>7 способов защитить свой интернет-ресурс от нежелательной информации</title><link>https://www.insight-it.ru//security/2008/7-sposobov-zashhitit-svoj-internet-resurs-ot-nezhelatelnoj-informacii/</link><description>&lt;p&gt;В одном из предыдущих постов я поднял &lt;a href="https://www.insight-it.ru/security/2008/otkuda-voznikaet-spam-i-kak-s-nim-borotsya/"&gt;тему о технологии под названием captcha&lt;/a&gt;, которая является одним из самых распространенных и эффективных способов борьбы с автоматическим заполнением интернет-ресурсов нежелательным контентом. В этом же посте хотелось бы развить начатый разговор повествованием о различных способах воплощения этой технологии в жизнь.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3 id="1-klassicheskii-variant-graficheskaia-realizatsiia"&gt;1. Классический вариант - графическая реализация&lt;/h3&gt;
&lt;p&gt;Самым популярным вариантом реализации является "графическая" captcha
(позволю себе "обращаться" к этому слову в женском роде, просто из-за
того, что по-моему оно так лучше звучит, не смотря на то, что по логике
все же стоило использовать "он", так как при дословном переводе
получилось бы слово "тест" с кучкой прилагательных
и определений). Она представляет собой изображение, содержащее чаще
всего какой-либо сильно искаженный текст или набор цифр, и перед
посетителем ставится задача воспроизведения в текстовом поле,
находящемся неподалеку, того что он/она видит на изображении.
Большинству людей не составит труда прочесть и набрать на клавиатуре
даже искаженный до неузнаваемости текст, а вот для программы данная
задача является как минимум нетривиальной.&lt;/p&gt;
&lt;p&gt;Существует некоторое количество алгоритмов (называются &lt;a href="/tag/ocr/"&gt;&lt;abbr title="Optical Character Recognition"&gt;OCR&lt;/abbr&gt;&lt;/a&gt;), позволяющих программе
пытаться понять что же за текст расположен на изображении. Эти алгоритмы
разрабатывались для вполне мирных целей - для оцифровки книг и любых
других напечатанных на бумаге документов. Но все же эти алгоритмы
предназначены для распознавания аккуратно написанного текста черным
шрифтом на белом фоне и являются плохо приспособленными для
распознавания &lt;a href="/tag/captcha/"&gt;captch'и&lt;/a&gt;. Но все же существует довольно
большое количество модификаций этих алгоритмов, приспособленных для
чтения даже искаженного текста.&lt;/p&gt;
&lt;p&gt;Казалось бы это существование таких алгоритмов делает бессмысленным
использованием такого рода "защиты", но на практике это далеко не так:
большинство из них пригодны только для распознавания только узкого
набора реализаций графических &lt;a href="/tag/captcha/"&gt;captch&lt;/a&gt;, особенно это
актуально для популярных готовых решений реализации этого типа защиты
находящимся в свободном доступе в сети Интернет, а также сервисов,
предоставляющих услуги по генерации такого рода изображений. Что делает
довольно актуальным написание собственной реализации графической
&lt;a href="/tag/captcha/"&gt;captch'и&lt;/a&gt; для появления уверенности в отсутствии готовой
модификации &lt;a href="/tag/ocr/"&gt;&lt;abbr title="Optical Character Recognition"&gt;OCR&lt;/abbr&gt;&lt;/a&gt; алгоритма, для преодоления используемой
преграды. Об этом и пойдет речь в &lt;a href="https://www.insight-it.ru/php/2008/zashhita-internet-resursov-v-kartinkax/"&gt;записи про собственноручную реализацию технологии CAPTCHA.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Но запись еще далека от завершения, ведь описанная выше графическая
реализация, не является единственной. Во-первых, стоило упомянуть пару
несколько реже используемые модификации визуальных тестов:&lt;/p&gt;
&lt;h3 id="2-sommon-sense"&gt;2. Сommon sense&lt;/h3&gt;
&lt;p&gt;Эта категория модификаций основывается на вопросах построенных на так
называемом &lt;em&gt;common sense&lt;/em&gt;, то есть на каких-то общеизвестных вещах,
очевидных для любого человека, но не поддающимся четкому осознаванию
программой с помощью какого-либо алгоритма. К сожалению, этот факт
вместе с тем порождает и основной недостаток этой категории проверок-
такой тест невозможно автоматически сгенерировать, что делает реализацию
существенно более трудоемкой и неэффективной, что собственно и
обуславливает редкость их применения на практике.&lt;/p&gt;
&lt;h3 id="3-matematicheskii-test"&gt;3. Математический тест&lt;/h3&gt;
&lt;p&gt;Помимо просто перенабирания некоторого набора цифр с изображения, авторы
captch'и могут попросить своего посетителя выполнить какую-либо
несложную операцию (например: &lt;code&gt;2 x 2 = ???&lt;/code&gt;). Но такого рода тесты также далеки от идеала, так как в подавляющем большинстве алгоритм их решения прост для безобразия - вполне достаточно бывает базового &lt;a href="/tag/ocr/"&gt;&lt;abbr title="Optical Character Recognition"&gt;OCR&lt;/abbr&gt;&lt;/a&gt; и реализации калькулятора внутри &lt;a href="/tag/crawler/"&gt;crawler&lt;/a&gt;'a, чтобы он смог преодолеть такого рода барьер.&lt;/p&gt;
&lt;h3 id="4-vybor-izobrazheniia"&gt;4. Выбор изображения&lt;/h3&gt;
&lt;p&gt;Хочется также упомянуть один из достаточно оригинальных вариантов
реализации, являющийся по сути вариацией на тему common sense captch'и,
который меня как минимум удивил, когда я его впервые увидел на сайте
одного из мобильных операторов рядом с формой для &lt;strong&gt;online&lt;/strong&gt; отправки SMS. Суть его заключалось в том, что предлагался набор небольших фотографий, из которых предлагалось выбрать 2-4 изображения обладающих каким-либо свойством, например являющимися живыми объектами. Помимо позитивненького оформления и симпатичных фотографий, чисто технически такой подход является достаточно эффективным и легко реализуемым, единственное предъявляемое к такой реализации требование - достаточно обширная база данных изображений.&lt;/p&gt;
&lt;h3 id="5-vykhod-za-ramki-standartov"&gt;5. Выход за рамки стандартов&lt;/h3&gt;
&lt;p&gt;Большинство вещей, предназначенных для массового использования, принято
делать по принципу "чем проще тем лучше". Обусловлено это тем, что
количество пользователей обратно пропорционально уровню требований, к
ним предъявляемых. Формы на интернет-страницах, как ни странно,
исключением из этого принципа не являются, что является причиной их
построения с использованием только базовых языков разметки -
&lt;a href="/tag/html/"&gt;HTML&lt;/a&gt;, &lt;a href="/tag/xhtml/"&gt;XHTML&lt;/a&gt; или в крайнем случае
&lt;a href="/tag/xml/"&gt;XML&lt;/a&gt;. Именно такую форму и ожидает увидеть spider, попадая на
страницу. Но если поступиться этим принципом - легко поставить программу
в тупиковое положение, задействовав какую-либо непривычную для нее
технологию. В качестве примера в голову приходит Flash-ролик вместо
изображения в &lt;em&gt;графическом&lt;/em&gt; варианте реализации.&lt;/p&gt;
&lt;p&gt;Этот способ является очень эффективным, но обладает существенными
недостатками, такими как, например, необходимость использования
современных браузеров с определенными plug-in'ами.&lt;/p&gt;
&lt;h3 id="6-skrytie-razmetki"&gt;6. Скрытие разметки&lt;/h3&gt;
&lt;p&gt;В качестве продолжения предыдущей мысли: &lt;em&gt;&lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt;&lt;/em&gt;
предоставляет далеко не один способ скрыть внутри себя код разметки, что
позволяет сделать вид, что формы &lt;em&gt;как бы&lt;/em&gt; не существует (в основном
базирующиеся на обратимом шифровании), заставляя программу подумать "да
тут и заполнять-то нечего" и пройти мимо на какой-нибудь другой сайт.
Все бы хорошо, только посетители сайта с отключенным
&lt;em&gt;&lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt;&lt;/em&gt;'ом формы тоже не увидят...&lt;/p&gt;
&lt;h3 id="7-zvukovoe-voploshchenie"&gt;7. Звуковое воплощение&lt;/h3&gt;
&lt;p&gt;Как не трудно было заметить, что все варианты, которые я упомянул до
этого момента, так или иначе базировались на визуальном восприятии
информации. И вполне обосновано - для большинства людей зрение играет
роль основного чувства, но существуют и интернет-ресурсы, для которых
важен абсолютно каждый посетитель, в том числе и люди с ограниченными
способности, для которых стандартные проверки являются непреодолимыми.
Для такой категории людей были сделаны альтернативные варианты,
основывающиеся на таком чувстве, как слух. Суть же от этого изменилась:
посетителя просят набрать с клавиатуры нечто услышанное при
воспроизведении аудио-записи, либо ответить на какой-либо вопрос,
основывающийся на уже упомянутом принципе &lt;em&gt;common sense&lt;/em&gt; и заданный тоже
с помощью в аудио-файле.&lt;/p&gt;
&lt;p&gt;Вместо заключения хотелось бы предложить Вам &lt;a href="/feed/"&gt;подписаться на RSS этого блога&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 03 Jan 2008 20:41:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-03:security/2008/7-sposobov-zashhitit-svoj-internet-resurs-ot-nezhelatelnoj-informacii/</guid><category>captcha</category><category>common sense</category><category>JavaScript</category><category>OCR</category><category>online</category><category>защита интернет-ресурсов</category><category>изображение</category><category>классификация</category><category>проверка</category><category>реализация</category><category>технология</category><category>форма</category></item><item><title>Откуда возникает спам и как с ним бороться</title><link>https://www.insight-it.ru//security/2008/otkuda-voznikaet-spam-i-kak-s-nim-borotsya/</link><description>&lt;p&gt;На сегодняшний день далеко не каждый пользователь &lt;a href="/net"&gt;Сети&lt;/a&gt; является
человеком, возможно это покажется странным для не интересующегося ИТ
читателя, но существует множество программ, способных передвигаться по
сайтам, следуя по гипер-ссылкам, как внутри одного сайта, так и переходя
с одного сайта на другой (в целом такой тип программ называется
&lt;a href="/tag/spider/"&gt;spider&lt;/a&gt; или &lt;a href="/tag/crawler/"&gt;crawler&lt;/a&gt;). Такие программы
могут иметь совершенно разное предназначение, самый распространенный
пример: поисковые системы используют &lt;a href="/tag/crawler/"&gt;crawler&lt;/a&gt;'ов для
пополнения своих индексов, но, к сожалению, далеко не все программы
этого класса написаны для благих целей.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3 id="good-vs-evil"&gt;Good vs Evil&lt;/h3&gt;
&lt;p&gt;Большая часть "хороших" &lt;a href="/tag/spider/"&gt;spider&lt;/a&gt;'ов используется лишь для
сбора информации о сайте и следуют пожеланиям владельцев сайтов,
оставленных ими в специальном файле под названием &lt;code&gt;robots.txt&lt;/code&gt;, либо
внутри &lt;a href="/tag/html/"&gt;HTML&lt;/a&gt;-разметки с помощью специально предназначенных
для этого тэгов (этот механизм выходит за рамки данного повествования,
так что позволю себе его пропустить, оставив как тему для отдельного
разговора).&lt;/p&gt;
&lt;p&gt;Но даже сбор информации во время автоматизированного путешествия
программы по сайтам можно использовать в корыстных целях - на многих
сайтах люди размещают свою контактную информацию для тех или иных целей,
и некоторые сайты эту информацию "публикуют". &lt;a href="/tag/spider/"&gt;Spider&lt;/a&gt;,
настроенный на сбор контактной информации (в основном адресов
электронной почты и номеров ICQ и прочих служб обмена сообщениями) может
в очень сжатые сроки насобирать длинный список адресов, пригодный,
например, для рассылки нежелательной рекламы, в простонародье называемой
&lt;em&gt;&lt;a href="/tag/spam/"&gt;спам&lt;/a&gt;&lt;/em&gt;. Избежать попадания своей контактной информации в
такие списки относительно просто - достаточно лишь следить за тем, чтобы
она либо не публиковалась, либо была защищена любым из простейших
способов защиты от такого рода программ, начиная от банального
требования регистрации для просмотра контактных данных пользователей,
заканчивая выводом адресов через изображения или шифрование посредством
&lt;em&gt;JavaScript&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Среди прочих функций, которые может выполнять такого рода программа,
одной из наиболее часто используемых является возможность заполнения
такой неотъемлемой составляющей практически любого сайта, как &lt;em&gt;формы&lt;/em&gt;.
Имея возможность заполнения существенно б&lt;em&gt;о&lt;/em&gt;льшего количества форм в
единицу времени, чем человек, такие программы служат основным источником
&lt;em&gt;&lt;a href="/tag/spam/"&gt;спама&lt;/a&gt;&lt;/em&gt; в гостевых книгах, форумах и блогах. Еще одним из
возможных применений автоматического заполнения форм является
регистрация на множестве интернет-ресурсов с целью получения какой-либо
выгоды, например регистрация сайтов в каталогах. Помимо этого
&lt;a href="/tag/crawler/"&gt;crawler&lt;/a&gt; перемещается по сайту с относительно высокой
скоростью, что резко увеличивает нагрузку на &lt;a href="/tag/server/"&gt;сервер&lt;/a&gt;,
особенно при недостаточно оптимизированном движке сайта и/или недостатке
ресурсов сервера, выделяемых на выполнение скриптов сайта.&lt;/p&gt;
&lt;h3 id="zashchita-form-ot-avtomaticheskogo-zapolneniia"&gt;Защита форм от автоматического заполнения&lt;/h3&gt;
&lt;p&gt;Наверняка многие из вас раньше слышали термин &lt;a href="/tag/captcha/"&gt;CAPTCHA&lt;/a&gt;,
но боялись спросить: что же он значит? Как не трудно догадаться этот
термин является аббревиатурой :). Расшифровывается она как
"&lt;strong&gt;C&lt;/strong&gt;ompletely &lt;strong&gt;A&lt;/strong&gt;utomated &lt;strong&gt;P&lt;/strong&gt;ublic &lt;strong&gt;T&lt;/strong&gt;uring test to tell
&lt;strong&gt;C&lt;/strong&gt;omputers and &lt;strong&gt;H&lt;/strong&gt;umans &lt;strong&gt;A&lt;/strong&gt;part". Для меня до сих пор остается
загадкой по какому принципу выбирались слова для составления этой
аббревиатуры, наверное тупо случайным образом :). Смысл этой фразы в
переводе на русский можно передать как "полностью автоматический способ
отличить человека от компьютера". Конечно же имеется ввиду не внешние
различия, а особенности их поведения на просторах сети Интернет. В роли
"компьютера" в данном случае как раз выступают программы, о которых шла
речь в самом начале. Эта технология позволяет владельцам сайтов,
желающих исключить (по крайней мере чисто теоретически, на практике же -
минимизировать) посещение своего ресурса "плохими" "компьютерами",
крайне затруднить их использование.&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;li&gt;Не должна полагаться на тот факт, что потенциальный "злоумышленник"
    просто не знаком с принципом работы данной проверки.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Более подробно о возможностях этой &lt;a href="/tag/tekhnologiya/"&gt;технологии&lt;/a&gt; можно
узнать, прочитав &lt;a href="https://www.insight-it.ru/security/2008/7-sposobov-zashhitit-svoj-internet-resurs-ot-nezhelatelnoj-informacii/"&gt;запись о нескольких вариантах ее реализации&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 03 Jan 2008 20:25:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-03:security/2008/otkuda-voznikaet-spam-i-kak-s-nim-borotsya/</guid><category>captcha</category><category>crawler</category><category>online</category><category>PHP</category><category>spider</category><category>защита интернет-ресурсов</category><category>интернет</category><category>проверка</category><category>Сеть</category><category>спам</category><category>электронная почта</category></item><item><title>Привет, мир!</title><link>https://www.insight-it.ru//misc/2008/privet-mir/</link><description>&lt;p&gt;Не смотря на то, что данная запись была сгенерирована &lt;code&gt;WordPress&lt;/code&gt;'ом автоматически при установке, заголовок ее
совпал по большому счету с темой первой записи, которую &lt;a href="https://www.insight-it.ru/author/"&gt;мне&lt;/a&gt; хотелось бы написать сразу же после установки блога, по этому позволю
себе оставить тему оставить практически неизменной, добавив лишь явно
пропущенную запятую.&lt;/p&gt;
&lt;p&gt;Какой-либо смысловой нагрузки для этого поста не предполагалось,
по-этому пожалуй продолжу приводить &lt;a href="https://www.insight-it.ru/about/"&gt;все это дело&lt;/a&gt; в порядок.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 03 Jan 2008 19:36:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-03:misc/2008/privet-mir/</guid><category>online</category><category>welcome</category><category>WordPress</category></item></channel></rss>