<?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/internet/feed/index.xml" rel="self"></atom:link><lastBuildDate>Sun, 03 Jan 2010 23:59:00 +0300</lastBuildDate><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>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>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>Архитектура YouTube</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-youtube/</link><description>&lt;p&gt;Рост &lt;a href="https://www.insight-it.ru/goto/628b8f6a/" rel="nofollow" target="_blank" title="http://www.youtube.com"&gt;YouTube&lt;/a&gt; был феноменально быстр,
количество просмотров видео превысило 100 миллионов в сутки при том, что
только около пяти человек работало над масштабированием проекта. Как им
удается управлять предоставлением всех этих видеороликов своим
посетителям? Как они развивались с тех пор, как были приобретены
&lt;a href="/tag/google/"&gt;Google&lt;/a&gt;?
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="platforma"&gt;Платформа&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/tag/apache/"&gt;Apache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/python/"&gt;Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/linux/"&gt;Linux&lt;/a&gt; (SuSe)&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/psyco/"&gt;psyco&lt;/a&gt;, динамический компилятор &lt;a href="/tag/python/"&gt;Python&lt;/a&gt; &amp;rarr;
    &lt;a href="/tag/c/"&gt;C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/lighttpd/"&gt;lighttpd&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;Поддержка обработки более 100 миллионов видеороликов в сутки&lt;/li&gt;
&lt;li&gt;Сервис был запущен в феврале 2005 года&lt;/li&gt;
&lt;li&gt;В марте 2006 года в среднем производилось около 30 миллионов
    просмотров видео в день&lt;/li&gt;
&lt;li&gt;К июлю 2006 года эта цифра достигла 100 миллионов просмотров в день&lt;/li&gt;
&lt;li&gt;Над проектом работают: 2 системных администратора, 2 архитектора
    масштабируемости программного обеспечения, 2 разработчика новых
    возможностей, 2 инженера по сетям, 1 архитектор баз данных&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Рецепт управления огромными темпами роста&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;identify_and_fix_bottlenecks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;notice_new_bottleneck&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Этот цикл проходит далеко не одну итерацию ежедневно.&lt;/p&gt;
&lt;h3 id="veb-servery"&gt;Веб-серверы&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/tag/netscalar/"&gt;NetScalar&lt;/a&gt; используется для балансировки нагрузки и
    кэширования статического контента.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/apache/"&gt;Apache&lt;/a&gt; работает с включенным &lt;code&gt;mod_fast_cgi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Запросы отправляются на обработку с помощью серверного приложения на
    &lt;a href="/tag/python/"&gt;Python&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Приложение взаимодействует с различными базами данных и другими
    источниками информации для формирования финальной
    &lt;a href="/tag/html/"&gt;HTML&lt;/a&gt;-страницы.&lt;/li&gt;
&lt;li&gt;Масштабирование обычно происходит просто добавлением дополнительных
    компьютеров.&lt;/li&gt;
&lt;li&gt;Код на &lt;a href="/tag/python/"&gt;Python&lt;/a&gt; обычно не является узким местом
    системы, он проводит большую часть времени заблокированным RPC.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/python/"&gt;Python&lt;/a&gt; предоставляет быстроту и гибкость в процессе
    разработки и развертывания. Этот факт является очень актуальным,
    если учесть кто является их конкурентами.&lt;/li&gt;
&lt;li&gt;На формирование страницы обычно уходит не более 100 миллисекунд.&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/psyco/"&gt;psyco&lt;/a&gt;, динамический компилятор &lt;a href="/tag/python/"&gt;Python&lt;/a&gt; &amp;rarr;
    &lt;a href="/tag/c/"&gt;C&lt;/a&gt;, использует JIT подход к компилированию для оптимизации
    внутренних циклов&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/html/"&gt;HTML&lt;/a&gt; хранится в
    кэше.&lt;/li&gt;
&lt;li&gt;Кэширование данных в &lt;a href="/tag/subd/"&gt;СУБД&lt;/a&gt; на уровне строк.&lt;/li&gt;
&lt;li&gt;Кэшируются полностью сформированные объекты &lt;a href="/tag/python/"&gt;Python&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Некие данные вычисляются и отправляется каждому серверу для
    кэширования в локальной оперативной памяти. Эта стратегия годится
    далеко не всегда, чаще всего более эффективен другой метод: самым
    быстрым кэшем является само серверное приложение, а отправка уже
    готовых данных остальным серверам для дальнейшей обработки обычно не
    занимает так много времени. Для организации такого подхода
    необходимы агенты, осуществляющие отслеживание изменений,
    предварительную обработку и отправку данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="upravlenie-video"&gt;Управление видео&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Издержки включают в себя затраты на пропускную способность каналов
    связи, приобретение нового оборудования и оплату огромных счетов за
    электроэнергию.&lt;/li&gt;
&lt;li&gt;Каждый видеоролик расположен на мини-кластере, что означает
    управление работой с ним группой из нескольких компьютеров.&lt;/li&gt;
&lt;li&gt;Использование кластеров влечет за собой:
    &amp;ndash; увеличение производительности пропорционально количеству дисков,
    на которых расположен контент;
    &amp;ndash; возможность поддержания функционирования всей системы даже в
    случае прекращения работоспособности части компьютеров;
    &amp;ndash; возможность организации создания резервных копий
    &lt;a href="/tag/online/"&gt;online&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;В роли HTTP-сервера для работы с видео используется
    &lt;a href="/tag/lighttpd/"&gt;lighttpd&lt;/a&gt;:
    &amp;ndash; Он способен дать фору &lt;a href="/tag/apache/"&gt;Apache&lt;/a&gt; в плане
    производительности предоставления статического контента;
    &amp;ndash; Для работы с событиями ввода-вывода используется &lt;strong&gt;epoll&lt;/strong&gt;;
    &amp;ndash; Многопоточная конфигурация способна обрабатывать большее
    количество соединений одновременно;&lt;/li&gt;
&lt;li&gt;Самая популярная часть контента размещается в &lt;abbr title="Content Delivery Network"&gt;CDN&lt;/abbr&gt;
    &amp;ndash; &lt;abbr title="Content Delivery Network"&gt;CDN&lt;/abbr&gt; реплицирует весь контент в разных частях системы;
    &amp;ndash; Компьютеры &lt;abbr title="Content Delivery Network"&gt;CDN&lt;/abbr&gt; в основном предоставляют данные напрямую из кэша в оперативной памяти, так как ассортимент популярного видео с течением времени
    меняется достаточно медленно.&lt;/li&gt;
&lt;li&gt;Менее популярный контент, количество просмотров в день которого
    варьируется в диапазоне от одного до двадцати, обычно размещается на
    серверах &lt;a href="/tag/youtube/"&gt;YouTube&lt;/a&gt;, расположенных в датацентрах на
    &lt;em&gt;colocation&lt;/em&gt;:
    &amp;ndash; Не смотря на тот факт, что такое видео может быть просмотрено
    всего несколько раз за день, количество таких роликов велико, что
    приводит к случайным блокировкам данных на жестких дисках;
    &amp;ndash; В такой ситуации кэширование практически бесполезно, инвестиции в
    кэширование контента с низкой вероятностью востребованности обычно
    является пустой тратой средств;
    &amp;ndash; Более детальная настройка низкоуровневых компонентов системы,
    таких как, например, RAID-контроллеры, в этой ситуации может
    достаточно положительно повлиять на производительность;
    &amp;ndash; Выбор оптимального размера оперативной памяти на каждой машине
    также очень важен: как недостаточное, так и излишнее ее количество
    не являются эффективными решениями.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Ключевые моменты&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Чем &lt;strong&gt;проще&lt;/strong&gt; - тем &lt;strong&gt;лучше&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Старайтесь минимизировать количество устройств (маршрутизаторов,
    коммутаторов и тому подобных) между контентом и пользователями:
    далеко не факт, что все они будут способны выдерживать интенсивную
    нагрузку;&lt;/li&gt;
&lt;li&gt;Старайтесь использовать самое обыкновенное оборудование. Hi-end
    оборудование обычно влечет за собой рост издержек, связанных с
    сопутствующими процессами, например технической поддержкой, а также
    уменьшает вероятность нахождение решения той или иной проблемы с
    оборудованием в Сети;&lt;/li&gt;
&lt;li&gt;Используйте самые простые распространенные утилиты.
    &lt;a href="/tag/youtube/"&gt;YouTube&lt;/a&gt; использует идущий в комплекте с
    &lt;a href="/tag/linux/"&gt;Linux&lt;/a&gt; набор утилит для построения системы именно на их
    основе;&lt;/li&gt;
&lt;li&gt;Не забывайте о случайных доступах к жестким дискам, эту, казалось
    бы, мелочь тоже стоит настроить.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="upravlenie-miniatiurami-video"&gt;Управление миниатюрами видео&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;На удивление сложно решаемая задача, особенно если необходима
    эффективность;&lt;/li&gt;
&lt;li&gt;Для каждого видео хранится 4 миниатюры, что приводит к существенному
    преобладанию количества миниатюр над количеством видеороликов;&lt;/li&gt;
&lt;li&gt;Миниатюры хранятся всего на нескольких компьютерах;&lt;/li&gt;
&lt;li&gt;Некоторые проблемы наблюдаются в связи с работой с большим
    количеством маленьких объектов:
    &amp;ndash; Проблемы на уровне операционной системы, связанные с большим
    количеством запросов на поиск данных, а также кэшем страниц и
    &lt;em&gt;inode&lt;/em&gt;'ов файловой системы;
    &amp;ndash; Ограничение на количество файлов в одной директории (особенно
    актуально для &lt;strong&gt;ext3&lt;/strong&gt;), возможно частичное решение в виде перехода
    к более иерархической структуре хранения данных, а также переходе к
    ядру &lt;a href="/tag/linux/"&gt;Linux&lt;/a&gt; версии 2.6, что может привести к более чем
    стократному росту производительности, но в любом случае хранение
    такого огромного количества файлов в локальной файловой системе - не
    самая лучшая идея;
    &amp;ndash; Большое количество запросов в секунду, так как одна страница может
    содержать до 60 миниатюр различных видеороликов;
    &amp;ndash; В условиях таких нагрузок &lt;a href="/tag/apache/"&gt;Apache&lt;/a&gt; показывает плохую
    производительность;
    &amp;ndash; Проводились эксперименты с использованием &lt;a href="/tag/squid/"&gt;squid&lt;/a&gt;
    (обратной proxy) между &lt;a href="/tag/apache/"&gt;Apache&lt;/a&gt; и посетителями.
    Какое-то время такой вариант казался работоспособным, но с ростом
    нагрузки производительность начала падать. С обработки 300 запросов
    в секунду она упала до 20;
    &amp;ndash; Попытки использовать &lt;a href="/tag/lighttpd/"&gt;lighttpd&lt;/a&gt; также не
    завершились успехом: однопоточный режим не справлялся с задачей, а
    многопоточный требовал отдельного кэша для каждого потока, что
    сводило на нет его эффективность;
    &amp;ndash; С таким количеством изображений добавление в систему нового
    компьютера могло занимать более 24 часов;
    &amp;ndash; Перезагрузка занимала 6-10 часов, так как кэш должен был
    "разогреться" прежде чем перестать использовать данные с жестких
    дисков.&lt;/li&gt;
&lt;li&gt;Решением всех описанных выше проблем стала распределенная система
    хранения данных &lt;a href="/tag/bigtable/"&gt;BigTable&lt;/a&gt; от &lt;a href="/tag/google/"&gt;Google&lt;/a&gt;:
    &amp;ndash; Она позволяет избежать проблем, связанных с большим количеством
    файлов, так как объединяет маленькие файлы вместе.
    &amp;ndash; Она работает быстро и устойчива к сбоям, помимо этого она
    прекрасно приспособлена для работы по ненадежной сети.
    &amp;ndash; Уменьшает задержки, так как использует распределенный
    многоуровневый кэш, который способен работать даже между удаленными
    датацентрами.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="bazy-dannykh"&gt;Базы данных&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Раньше:
    &amp;ndash; &lt;a href="/tag/mysql/"&gt;MySQL&lt;/a&gt; использовалась для хранения данных:
    пользователей, тэгов, описаний и так далее.
    &amp;ndash; Данные хранились на монолитном RAID 10 массиве, состоящем из 10
    жестких дисков;
    &amp;ndash; Оборудование арендовалось, что негативно сказывалось на состоянии
    их кредитных карточек. В случае необходимости нового оборудования,
    на оформление заказа и доставку мог уходить далеко не один день.
    &amp;ndash; Они прошли через весь путь эволюции: сначала был один сервер,
    затем добавилось несколько дополнительных серверов, обслуживающих
    операции чтения, после чего они решили разбить базу данных на части,
    и, наконец, они пришли к полноценной распределенной архитектуре.
    &amp;ndash; Поначалу их система страдала от задержек, связанных с
    реплицированием. Основной сервер, обрабатывающий операции записи,
    являлся мощным сервером, работающим в многопоточном режиме, это было
    необходимо для своевременного выполнения большого объема работы.
    Второстепенные сервера, которые обрабатывали только операции чтения,
    асинхронно реплицировали данные в одном потоке, что влекло за собой
    возможность серьезного отставания некоторых из них.
    &amp;ndash; Обновления были причиной частого отсутствия необходимой информации
    в кэше, что заставляло сервера читать данные с жестких дисков. Этот
    факт сильно замедлял процесс чтения и репликации.
    &amp;ndash; Реплицирующая архитектура требует немалых вложений в оборудование,
    необходимого для поддержания постоянно растущих темпов записи
    информации.
    &amp;ndash; Основным из кардинальных решений, принятых в архитектуре системы
    было отделение обеспечения процесса просмотра видео от основного
    кластера. Основной целью посетителей является просмотр видео, а
    второстепенные задачи можно возложить и на менее производительный
    кластер.&lt;/li&gt;
&lt;li&gt;Сейчас:
    &amp;ndash; Используются распределенные базы данных;
    &amp;ndash; Сегментированная система &lt;em&gt;(прим.: &lt;a href="https://www.insight-it.ru/highload/2008/arkhitektura-flickr/"&gt;по аналогии с Flickr&lt;/a&gt;)&lt;/em&gt;;
    &amp;ndash; Распределенные чтение и запись;
    &amp;ndash; Более эффективное расположение кэша, что ведет к уменьшению работы
    с жесткими дисками;
    &amp;ndash; Такая архитектура привела к 30%-й экономии на оборудовании;
    &amp;ndash; Задержки в реплицировании сведены к нулю;
    &amp;ndash; Размеры базы данных могут расти практически неограниченно&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="strategiia-razmeshcheniia-v-datatsentrakh"&gt;Стратегия размещения в датацентрах&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Поначалу использовались хостинг провайдеры, предоставляющие услуги
    colocation. Не самый экономичный подход, но тогда не было другого
    выхода.&lt;/li&gt;
&lt;li&gt;Хостинг провайдеры не могут поспеть за темпами роста проекта. Не
    всегда получается получить контроль над необходимым оборудованием
    или сделать необходимые соглашения о предоставлению сетевых услуг.&lt;/li&gt;
&lt;li&gt;Решением этой проблемы стало создание собственной базы для
    размещения оборудования. Появилась возможность настраивать абсолютно
    все и подписывать свои собственные контракты такого рода.&lt;/li&gt;
&lt;li&gt;Было использовано 5 или 6 разных датацентров в дополнение к
    &lt;abbr title="Content Delivery Network"&gt;CDN&lt;/abbr&gt;.&lt;/li&gt;
&lt;li&gt;Видео поступает из случайного датацентра, никаких специальных
    проверок не проводится. Если ролик становится достаточно
    популярным - он перемещается в
    &lt;abbr title="Content Delivery Network"&gt;CDN&lt;/abbr&gt;.&lt;/li&gt;
&lt;li&gt;Основным фактором, влияющим на доступность того или иного ролика
    является пропускная способность канала связи.&lt;/li&gt;
&lt;li&gt;Для изображений же более актуальны задержки, особенно если на одной
    страницы должно быть размещено под 60 изображений.&lt;/li&gt;
&lt;li&gt;Репликация изображений производится средствами
    &lt;a href="/tag/bigtable/"&gt;BigTable&lt;/a&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; Креативные и рискованные трюки могут
    помочь справиться с задачей в краткосрочном периоде, но со временем
    понадобятся более продуманные решения.&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;a href="/tag/youtube/"&gt;YouTube&lt;/a&gt; использует
    &lt;abbr title="Content Delivery Network"&gt;CDN&lt;/abbr&gt; для распределения
    своего наиболее популярного контента. Создание своей собственной
    подобной сети стоило бы им слишком много и потребовало бы слишком
    много времени. Возможно у Вас появятся подобные возможности в
    отношении Вашей системы.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Будьте проще!&lt;/strong&gt; Простота позволяет изменять архитектуру более
    быстро, что позволяет своевременно реагировать на возникающие
    проблемы. Никто на самом деле не знает что такое &lt;em&gt;простота&lt;/em&gt;, но если
    Вы не боитесь делать изменения, то это неплохой знак что вашей
    системе свойственна та самая &lt;em&gt;простота&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сегментирование.&lt;/strong&gt; Сегментирование позволяет изолировать и
    ограничить дисковое пространство, процессорное время, оперативную
    память и ввод-вывод. Оно выполняется не только для повышения
    производительности операций записи.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Постоянная работа над поиском и устранением узких мест в
    системе:&lt;/strong&gt;
    &amp;ndash; на программном уровне это чаще всего бывает кэширование и работа с
    &lt;a href="/tag/subd/"&gt;СУБД&lt;/a&gt;;
    &amp;ndash; на уровне операционной системы - операции ввода-вывода;
    &amp;ndash; на уровне оборудования - оперативная память и RAID массивы.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Залог Вашего успеха - командная работа.&lt;/strong&gt; Хорошая команда разного
    рода специалистов должна понимать принцип системы вцелом и того, что
    лежит &lt;em&gt;под&lt;/em&gt; ней. Каждый должен знать свое дело: настраивать
    принтеры, подключать к системе новые компьютеры, строить сети и так
    далее. С отличной командой Вам по силам все что угодно.&lt;/li&gt;
&lt;/ul&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/ea16b832/" rel="nofollow" target="_blank" title="http://highscalability.com/youtube-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="https://www.insight-it.ru/highload/"&gt;коллекции&lt;/a&gt;, да и многим читателям, возможно,
покажется интересным. Что ж, перейдем к источнику информации оригинала:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/f5823d0b/" rel="nofollow" target="_blank" title="http://video.google.com/videoplay?docid=-6304964351441328559"&gt;Google Video&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sat, 01 Mar 2008 16:07:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-03-01:highload/2008/arkhitektura-youtube/</guid><category>Apache</category><category>BigTable</category><category>lighttpd</category><category>Linux</category><category>MySQL</category><category>NetScalar</category><category>psyco</category><category>Python</category><category>YouTube</category><category>архитектура</category><category>архитектура YouTube</category><category>интернет</category><category>Масштабируемость</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>Месяц</title><link>https://www.insight-it.ru//misc/2008/mesyac/</link><description>&lt;p&gt;Что ж, вот и прошел ровно месяц с того момента, как в мою голову пришла
мысль о создании этого блога, срок конечно же очень и очень скромный, но
уже можно провести своеобразную черту и подвести вое-какие итоги
прошедшего месяца.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;Внимательные читатели могли бы заметить, что официально блог был открыт
3 января 2008 года, но, к сожалению, выкроить достаточно свободного
времени чтобы дописать эту запись мне удалось лишь сегодня. Объемы
времени, которое приходится тратить на учебу, неуклонно растут, но так
или иначе я стараюсь как можно чаще находить свободную минутку, которую
можно было бы посветить блогу.&lt;/p&gt;
&lt;p&gt;Говорить о том удалась идея или нет еще определенно рано, возраст у
проекта еще маловат для такого рода громких слов. Но зато можно
посмотреть в статистику, и увидеть что некоторые из 23 постов, которые я
успел-таки написать за месяц каким-то загадочным образом умудрились
попасть на главные страницы некоторых крупных новостных порталов,
количество уникальных посетителей по разным данным очень сильно
колеблется, но так или иначе оно уже исчисляется тысячами.
Хостинг-провайдер на котором располагается блог, с радостью успел мне
сообщить, что за январь с моего сайта был скачано почти два гигабайта
информации, если учесть, что подавляющее большинство расположенного
здесь контента является просто текстом, а количество изображений и
JavaScript'ов минимально, то цифра выглядит более чем внушительно.&lt;/p&gt;
&lt;p&gt;За месяц я успел получать от читателей совершенно разные отзывы, начиная
от откровенно негативных, которые даже спам-фильтр не проходили из-за
мата, заканчивая добрыми и теплыми словами, которые всегда приятно
читать.&lt;/p&gt;
&lt;p&gt;Напоследок могу лишь пообещать, что буду и дальше прилагать все усилия,
чтобы мои читатели не жалели о том, что оказались на &lt;a href="https://www.insight-it.ru/about/"&gt;этом
сайте&lt;/a&gt;. А еще хочется извиниться за внушитльное количество опечаток, которое можно найти в моих текстах, если Вы вдруг что-либо
подобное обнаруживаете - не сочтите&amp;nbsp; пожалуйста за трудность написать об
этом в комментариях.&amp;nbsp; Окончательно ставя точку в этой записи,
воспользуюсь возможностью прорекламировать&amp;nbsp;&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>Mon, 04 Feb 2008 12:02:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-02-04:misc/2008/mesyac/</guid><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//theory/2008/mikroformaty/</link><description>&lt;p&gt;&lt;img alt="Microformats" class="left" src="https://www.insight-it.ru/images/microformats.png" title="Microformats"/&gt;&lt;/p&gt;
&lt;p&gt;Не смотря на тот факт, что эта технология еще только начинает получать
широкое распространение и применение на просторах Сети, слов о ней уже
написано немало, не вижу ни одной причины почему бы мне тоже не написать
несколько слов о &lt;a href="https://www.insight-it.ru/goto/b960d7c/" rel="nofollow" target="_blank" title="http://microformats.org"&gt;микроформатах.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Основной идеей микроформатов является попытка дополнить смыслом
существующие элементы стандартов разметки - XHTML и HTML, такого рода
смысл нынче модно назвать словом &lt;em&gt;семантика&lt;/em&gt;, что так или иначе влияет
как на людей, пользующихся услугами Сети, так и на программы,
обслуживающие ее функционирование.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3 id="chto-predstavliaiut-soboi-mikroformaty"&gt;Что представляют собой микроформаты?&lt;/h3&gt;
&lt;p&gt;Строго говоря, микроформаты являются набором форматов данных,
основывающихся на существующих широкораспространенных стандартах
представления данных (в частности XHTML), каждый из них предназначен для
решения конкретной узкоспециализированной задачи, то есть для
обеспечения конкретной семантикой конкретной части стандарта.&lt;/p&gt;
&lt;p&gt;Как не трудно догадаться, измение существующих и добавление новых тэгов
к стандарту XHTML в микроформатах недопустимо, ведь иначе документ
перестанет соответствовать исходному стандарту. Именно по-этому для
реализации микроформатов используются атрибуты тэгов XHTML, в которых
допускаются некоторые вольности - &lt;strong&gt;rel&lt;/strong&gt; и &lt;strong&gt;class&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="chto-zhe-mozhet-dat-osmyslennost-razmetki"&gt;Что же может дать осмысленность разметки?&lt;/h3&gt;
&lt;p&gt;В перспективе вся эта затея направлена на повышение качества сервисов,
предоставляемых в Сети. На данный момент большая часть сервисов,
основанных на анализе данных расположенных в Сети, способна лишь на
частичное использование разметки документа для уточнения смысла той или
иной информации. Показать это лучше всего на примере: тэги &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt; и
&lt;code&gt;&amp;lt;strong&amp;gt;&lt;/code&gt; говорят о том, что содержащаяся внутри них информация
имеет некий смысловой акцент, но в то же время многие другие тэги не
несут за собой никакой дополнительной смысловой информации, помимо
содержащегося внутри них текста. Одним из таких тэгов является
&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;, который говорит о наличии ссылки на некоторую
интернет-страницу, как-то связанную с текстом между открывающим и
закрывающим тэгами, а также расположенную по URL, указанному в атрибуте
&lt;code&gt;href&lt;/code&gt;, можно конечно к этому прибавить атрибут &lt;code&gt;title&lt;/code&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; и
предоставляет авторам документов возможность описать свое отношение к
другим авторам, на работы которых они ссылаются, выглядит это примерно
следующим образом:&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;"http://www.my-friend.ru"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"friend"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Сайт моего друга
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Теперь понять, что сайт, на который происходит ссылка, является сайтом
друга автора текущего документа, может не только читатель, но и
программа, занимающаяся индексированием страниц Сети для какого-либо
сервиса, например этот микроформат полезен для повышения качества работы
социальных сетей. Это была лишь небольшая часть возможностей
микроформата XFN, подробнее останавливаться на нем не буду - ведь каждый
из них явно заслуживает отдельной записи.&lt;/p&gt;
&lt;h3 id="klassifikatsiia"&gt;Классификация&lt;/h3&gt;
&lt;p&gt;Наверняка к Вам в голову приходила мысль: а почему необходимо
пользоваться именно вот этими микроформатами? Если в XHTML допускаются
любые значения тэгов &lt;code&gt;rel&lt;/code&gt; и &lt;code&gt;class&lt;/code&gt;, почему я не могу придумать
свои микроформаты и пользоваться ими? Ответ прост: микроформаты призваны
повысить качество Сети вцелом, а не какого-то конкретного сайта
отдельно. Только часть микроформатов получила широкое распространение, и
именно ими приходится пользоваться всем остальным сайтам под влиянием
&lt;em&gt;сетевого эффекта&lt;/em&gt; (т.е. того факта, что ценность технологии прямо
пропорциональна обширности ее применения, в нашем случае в рамках Сети),
просто чтобы быть совместимыми с остальной частью Интернета.&lt;/p&gt;
&lt;p&gt;Но не смотря на это - количество и разнообразие распространенных
микроформатов велико, и как-либо классифицировать их достаточно сложно.
Самым простым и точным вариантом можно назвать разделение по структуре
формата:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;элементарные&lt;/em&gt; - применимые только к одному конкретному типу тэгов.
    В эту группу попадают упомянутый выше &lt;strong&gt;XFN&lt;/strong&gt;, а также множество
    других, например &lt;em&gt;rel-tag&lt;strong&gt;, &lt;/strong&gt;rel-nofollow&lt;/em&gt;*, и так далее;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;композитные (или составные)&lt;/em&gt; - имеют более сложную структуру, и для
    своей реализации требуют модификации нескольких тэгов одного
    элемента. Микроформаты из этой категории предназначены для описания
    более сложной структуры, например &lt;strong&gt;hCard&lt;/strong&gt;, используемый для
    описания людей или организаций (можно посмотреть на пример его
    использования &lt;a href="https://www.insight-it.ru/author/"&gt;на моей странице "О себе"&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Это пожалуй единственный общепринятый тип классификации микроформатов,
можно конечно попытаться провести границы по типам используемых
атрибутов или модифицируемых тэгов, но такого рода классификации
несущественны и не являются широко распространенными.&lt;/p&gt;
&lt;h3 id="primenenie-na-praktike"&gt;Применение на практике&lt;/h3&gt;
&lt;p&gt;Вариантов их применения на сегодняшний день не так уж и много. Как я уже
упоминал, эта технология еще находится лишь на пути к получению
повсеместной распространенности на просторах Сети, но уже сейчас они
проявили себя достаточно, чтобы оказывать влияние на многие аспекты сети
Интернет:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Многие поисковые системы активно используют при составлении своего
    индекса микроформат &lt;strong&gt;rel-nofollow&lt;/strong&gt;, об этом мне уже &lt;a href="https://www.insight-it.ru/theory/2008/putevoditel-dlya-robotov/"&gt;доводилось
    упоминать в одной из предыдущих
    записей&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Plug-in для Firefox под названием
    &lt;a href="https://www.insight-it.ru/goto/c84adfbb/" rel="nofollow" target="_blank" title="https://addons.mozilla.org/en-US/firefox/addon/4106"&gt;&lt;em&gt;Operator&lt;/em&gt;&lt;/a&gt; -
    позволяет просматривать используемые на текущей странице
    микроформаты, а также предлагает небольшой ассортимент действий, с
    ними связанных. Например, &lt;strong&gt;hCard&lt;/strong&gt; предлагается экспортировать в
    адресную книгу, а для &lt;strong&gt;rel-tag&lt;/strong&gt; - осуществить поиск по скромному
    списку интернет-сервисов. &lt;img alt="Operator screenshot" class="right" src="https://www.insight-it.ru/images/firefox-operator.png" title="Operator menu"/&gt;
    Лично я уже достаточно его себе установил и всегда держу включенным,
    не для того, чтобы реально им пользоваться, а просто чтобы быть в
    курсе, что тот или иной ресурс вдруг начал поддерживать эту
    замечательную технологию;&lt;/li&gt;
&lt;li&gt;Появляется все больше и больше CMS, поддерживающих различные
    микроформаты "из коробки" или с помощью plug-in'ов, что ведет к все
    более активному расширению списка сайтов, следующих этим стандартам
    представления данных. &lt;a href="https://www.insight-it.ru/goto/92e8fc22/" rel="nofollow" target="_blank" title="http://wordpress.org"&gt;WordPress&lt;/a&gt;, &lt;del&gt;на которой работает этот блог&lt;/del&gt;, тоже относится к категории CMS, поддерживающих
    микроформаты, в чем вы можете убедиться, установив упомянутый в
    предыдущем пункте &lt;em&gt;Operator&lt;/em&gt;. Сам по себе этот факт какой-либо
    полезности не несет, но является лишним стимулом для разработчиков
    программного обеспечения и интернет-ресурсов, поддерживающих
    микроформаты.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Этот список можно было бы продолжать еще достаточно долго, так что
позволю себе остановиться, ограничившись лишь перечислением наиболее
актуальных с моей точки зрения аспектов применения микроформатов.&lt;/p&gt;
&lt;h3 id="podvodim-itogi"&gt;Подводим итоги&lt;/h3&gt;
&lt;p&gt;По сути являясь своеобразной "надстройкой" над XHTML, микроформаты
создаются по принципу "чем проще - тем лучше", но в то же время
благодаря своей узкой специализации и простоте, каждый из них способен
быть составной частью модульной структуры форматов данных, способной
поднять Сеть на качественно новый уровень развития.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sun, 27 Jan 2008 19:31:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-27:theory/2008/mikroformaty/</guid><category>hcard</category><category>hreview</category><category>html</category><category>xfn</category><category>XHTML</category><category>интернет</category><category>Микроформаты</category><category>семантика</category><category>смысл</category><category>технология</category></item><item><title>Шаблонизация</title><link>https://www.insight-it.ru//php/2008/shablonizaciya/</link><description>&lt;p&gt;Наверняка Вы часто замечали, что в пределах одного сайта все (или
покрайней мере большинство) страниц имеют много общего: структуру,
расположение элементов, дизайн и так далее. Основным различием обычно
является лишь содержание. Естественно, что делается это не спроста:
именно общие компоненты сайта создают в голове посетителей тот самый
образ, который производит общее подсознательное впечатление о сайте, а
также позволяет посетителям отличать сайт А от сайта Б.&lt;/p&gt;
&lt;p&gt;Продолжая разговор, начатый еще в
&lt;a href="https://www.insight-it.ru/php/2008/obshhaemsya-s-bazojj-dannykh/"&gt;одной&lt;/a&gt; из &lt;a href="https://www.insight-it.ru/dzhentelmenskij-nabor-php-programmista/"&gt;предыдущих
статей&lt;/a&gt;, рассмотрим организацию интерфейса между двумя другими составляющими практически любого
интернет-проекта: скриптов (все так же на примере PHP) и страницами,
отправляемыми посетителям посредством http-сервера.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;С точки зрения веб-разработчика было бы как минимум не логично мешать в
кучу постоянные части страниц с динамическими. Для этого существует
множество причин, в том числе, например, экономия вычислительной
мощности сервера на отсутствии необходимости каждый раз заново
генерировать статичные элементы или неминуемое сокращение объемов кода,
который необходимо написать, в случае если статический и динамический
контент разделены. Отделенную подобным образом статическую часть страниц
(слегка модифицированную с целью обозначить правила, по которым будет
проводиться "заполнение" ее динамическим контентом) принято называть
словом &lt;em&gt;"шаблон"&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Наверняка у Вас уже возникло два вполне логичных вопроса:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Как можно разделить таким образом контент?&lt;/li&gt;
&lt;li&gt;Как потом восстановить страницу в исходном виде?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Вариантов ответа на каждый из них можно придумать множество: начиная с
банальных вариаций на тему применения &lt;strong&gt;echo&lt;/strong&gt;, заканчивая применением
достаточно серьезных готовых решений вроде широкораспространенного
&lt;a href="https://www.insight-it.ru/goto/2915d764/" rel="nofollow" target="_blank" title="http://smarty.php.net"&gt;&lt;strong&gt;Smarty&lt;/strong&gt;&lt;/a&gt; или существенно более эффективного
&lt;a href="https://www.insight-it.ru/goto/8c8929a1/" rel="nofollow" target="_blank" title="http://alexeyrybak.com/blitz/blitz_ru.html"&gt;&lt;strong&gt;Blitz&lt;/strong&gt;&lt;/a&gt;. Каждый из них
имеет свои сильные и слабые стороны, но в целом любой из них можно
оценить по двум критериям: производительности и удобстве организации
кода.&lt;/p&gt;
&lt;p&gt;Какие-либо цифры оценки производительности приводить не буду, так как,
во-первых, в Сети можно найти много benchmark'ов, посвященных этой теме,
а, во-вторых, просто-напросто вовсе не о цифрах я хотел с Вами
поговорить. Как известно самым производительным по крайней мере с
теоретической точки зрения является метод под названием &lt;strong&gt;php mess&lt;/strong&gt;, заключается он в следующем: вся страница размещается в рамках
одного файла, при этом статическая часть документа пишется просто "как
есть" в соответствии с необходимым стандартом, а изменяемые части
организуются размещенным в необходимых местах PHP-кодом, окруженным
стандартной конструкцией &lt;code&gt;&amp;lt;?php&amp;nbsp;&amp;nbsp;&amp;nbsp;?&amp;gt;&lt;/code&gt;. Но огромнейший недостаток
очевиден - огромное количество информации расположенной в одном файле,
при отсутствии какого-либо более четкого разделения PHP-кода и
остального содержимого, чем указанная выше конструкция, приводит к
постоянной путанице в коде, а также существенным затратам времени
программиста при попытках исправить ту или иную часть документа.&lt;/p&gt;
&lt;p&gt;На противоположной стороне нашей шкалы &lt;em&gt;удобство-производительность&lt;/em&gt; я
бы расположил уже упомянутое выше решение под названием &lt;strong&gt;Smarty&lt;/strong&gt;.
Представляет оно собой целую систему, реализованную также на PHP, и
предоставляющую огромное количество возможностей по решению нашей
задачи. Шаблоны хранятся в отдельных файлах, для определения мест
расположения динамического контента используется специальный синтаксис,
который прост как три копейки, так как разрабатывался с расчетом не на
программистов, а по принципу "чем проще, тем лучше". Именно этот факт
сделал &lt;strong&gt;Smarty&lt;/strong&gt; одним из самых (если не самым) распространенных
движков шаблонизации (или как их принято правильно называть "Template
Engine"). Но, к сожалению, за удобство приходится платить, в этом случае
производительностью: вся система сама по себе громоздка и состоит из
множества файлов, между которыми все данные так или иначе передаются, а
так как написано она на PHP (который является далеко не самым
производительным языком программирования, в основном в силу своей
интерпритируемости и некоторых других особенностей), конкуренции в плане
производительности многим другим вариантам решения нашей задачи
&lt;strong&gt;Smarty&lt;/strong&gt; составить не в состоянии.&lt;/p&gt;
&lt;p&gt;Одним из лучших "компромиссных" вариантов, которые доступны на данный
момент, могу назвать также упомянутый выше &lt;strong&gt;Blitz&lt;/strong&gt;. Реализован он в
виде модуля PHP, написанного на языке &lt;strong&gt;C&lt;/strong&gt;, что является залогом его
отличной производительности. При этом общая его концепция близка к
&lt;strong&gt;Smarty&lt;/strong&gt;: шаблоны также хранятся в отдельных файлах и подчинены
незамысловатому синтаксису (который вообще можно понять и запомнить
буквально за 15-20 минут, прочитав статью, &lt;a href="https://www.insight-it.ru/goto/8c8929a1/" rel="nofollow" target="_blank" title="http://alexeyrybak.com/blitz/blitz_ru.html"&gt;ссылку на
которую&lt;/a&gt; я уже приводил
выше), а в PHP-скриптах после установки становится доступен специальный
класс для управления модулем. Но основное достоинство этого решения
является одновременно и его основным недостатком - редкий хостинг имеет
этот модуль в списке предустановленных (видимо в силу своей не очень
обширной известности, обусловленной ), а доступ к http-серверу и
PHP-интерпретатору, который необходим для установки PHP-модулей,
предоставляется чаще всего только на дорогих тарифах виртуального
хостинга или на различных вариантах VPS или арендуемых серверов.&lt;/p&gt;
&lt;p&gt;Помимо этого некоторые энтузиасты берутся на написание "собственных"
&lt;em&gt;Template Engine&lt;/em&gt;, базирующихся на различных вариантов использования
PHP-функций вроде &lt;strong&gt;preg_replace&lt;/strong&gt;. Если честно такие попытки редко
заканчиваются успехом: в лучшем случае удается добиться удобства
использования самим разработчиком, но чаще всего в ущерб
производительности. Заниматься подобными экспериментами я Вам не
советую, вместо этого я предлагаю написать &lt;em&gt;"обертку"&lt;/em&gt; к приглянувшемуся
распространенному &lt;em&gt;Template Engine&lt;/em&gt;, что позволит не только сделать его
использование более удобным конкретно для Вас, но и позволит заменить
его на другой с минимальными затратами сил и времени (например в случае,
если модуль &lt;strong&gt;Blitz&lt;/strong&gt; недоступен).&lt;/p&gt;
&lt;h3 id="razrabatyvaem-obertku"&gt;Разрабатываем "обертку"&lt;/h3&gt;
&lt;p&gt;Сразу скажу, что цели привести конкретный пример пригодного для
реального использования кода я перед собой не ставлю в этой части моего
повествования. Я лишь хочу показать направление, в котором можно
провести разработку с целью облегчения собственной же жизни, т.е.
предоставить Вам альтернативу простому использованию тех или иных
решений в том виде, в котором они предоставлены разработчиками.&lt;/p&gt;
&lt;p&gt;Если Ваш выбор всетаки пал на написание "оболочки", не смотря на
принесение в жертву несущественной части производительности, то стоит
для начала определиться: а что же мы будем "заворачивать"? В качестве
примера я, пожалуй, буду использовать &lt;strong&gt;Blitz&lt;/strong&gt;, как самый оптимальный
вариант (по крайней мере с моей точки зрения). Начать стоит как обычно с пустой заготовки для класса.&lt;/p&gt;
&lt;p&gt;Далее следует решить какие все же модификации мы будем производить для
собственного удобства над стандартным решением. Попробую привести
несколько примеров в отношении &lt;strong&gt;Blitz&lt;/strong&gt;, для начала хочу обратить
внимание, что при внимательном прочтении все той же статьи от
разработчика этого шаблонизатора, можно обнаружить, что модуль
показывает более высокие показатели производительности при однократном
вызове метода &lt;em&gt;set&lt;/em&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;TemplateEngine&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&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="c1"&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;engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Blitz&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./template/'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'.tpl'&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;em&gt;set&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;function&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$caption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&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;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$caption&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$value&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;em&gt;set&lt;/em&gt; можно использовать уже непосредственно
перед &lt;em&gt;parse&lt;/em&gt;, с указанием уже собранного массива в качестве параметра.
За компанию позволю произвести себе еще одну модификацию: в подавляющем
большинстве случаев &lt;em&gt;parse&lt;/em&gt; используется в совокупности с &lt;strong&gt;echo&lt;/strong&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;function&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;array&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;engine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;set&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;array&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;echo&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;engine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;parse&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;strong&gt;htmlspecialchars&lt;/strong&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;function&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$caption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&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;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$caption&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;html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;rawset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$caption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&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;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$caption&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$value&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;html&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;is_array&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$array&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$caption&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;$value&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;html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&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;$array&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;htmlspecialchars&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="nx"&gt;ENT_QUOTES&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;em&gt;Спасибо за то, что дочитали до конца это повествование.&lt;/em&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sat, 26 Jan 2008 15:25:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-26:php/2008/shablonizaciya/</guid><category>blitz</category><category>PHP</category><category>Smarty</category><category>template</category><category>template engine</category><category>интернет</category><category>ООП</category><category>разработка</category><category>шаблон</category><category>шаблонизация</category></item><item><title>Путеводитель для роботов</title><link>https://www.insight-it.ru//theory/2008/putevoditel-dlya-robotov/</link><description>&lt;p&gt;Ни для кого не секрет, что одним их основных факторов, влияющих на
расположение страниц интернет-ресурса на просторах поисковых систем,
является уникальность контента (или другими словами - содержания).
Конечно же простейшим способом избежать дублирующегося контента является
просто собственноручная его генерация (или в крайнем случае с помощью
наемных работников или посетителей Вашего сайта). Но, к сожалению, это
позволяет избежать лишь повторов между разными сайтами. Помимо этого
свою роль играют и повторы в рамках одного сайта. Наверняка Вы замечали,
что многие CMS размещают один и тот же текст на разных страницах сайта:
например на обычной странице, в RSS-ленте и каком-нибудь архиве.&lt;/p&gt;
&lt;p&gt;Именно для решения этой маленькой проблемы и была создана технология под
названием &lt;strong&gt;Robots Exclusion Protocol&lt;/strong&gt;. С ее помощью можно
минимизировать возможность повторов содержимого, проиндексированного
поисковыми системами в рамках одного сайта, а также исключить из индекса
неинформативные страницы.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;Надеюсь, что Вы представляете себе в чем заключается принцип работы
поисковых систем, но в любом случае не вижу причин для того чтобы не
рассказать вкратце об этом. Помимо собственно сайта, где пользователи
вводят ключевую фразу для поиска, любая поисковая система имеет еще две
части: базу данных (другими словами - индекс сайтов) и специальной
программы (которую чаще всего называют &lt;em&gt;пауком&lt;/em&gt; или по-английски -
&lt;em&gt;crawler&lt;/em&gt; или &lt;em&gt;spider&lt;/em&gt;, но иногда используется более общий термин -
&lt;em&gt;робот&lt;/em&gt;). Эта программа запущена на серверах поисковых систем во
множестве экземпляров и основной целью их работы является пополнение и
обновления индекса поисковой системы. Сам же сайт лишь делает выборку из
индекса в соответствии с запросом и сортирует результат.&lt;/p&gt;
&lt;p&gt;Принцип работы такого класса программ я уже упоминал в &lt;a href="https://www.insight-it.ru/security/2008/otkuda-voznikaet-spam-i-kak-s-nim-borotsya/" title="Откуда возникает спам и как с ним бороться"&gt;записи о борьбе со спамом&lt;/a&gt;,
так что повторюсь лишь вкратце в надежде, что Вы ее уже читали: они
перемещаются по просторам Сети следуя по гиперссылкам, и на каждой
странице, куда они попадают, стараются выполнить заранее определенное
действие, в нашем случае - проиндексировать ее.&lt;/p&gt;
&lt;p&gt;Обсуждаемая нами технология дает возможность веб-мастеру предоставить
crawler'ам, образно говоря, &lt;em&gt;путеводитель&lt;/em&gt; по его сайту. Методов для
этого имеется несколько:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Любой crawler прежде чем перейти на новый домен проверяет
    существование файла по адресу &lt;code&gt;http://www.некий-домен.ru/robots.txt&lt;/code&gt;.
    В таком файле веб-мастер может разместить директивы для
    потенциальных компьютеризированных посетителей в соответствии с
    &lt;a href="https://www.insight-it.ru/goto/32ecd79a/" rel="nofollow" target="_blank" title="http://www.robotstxt.org/norobots-rfc.txt"&gt;соответствующим стандартом&lt;/a&gt;. Если поисковый робот обнаруживает этот файл, то прочитав его он
    корректирует свой маршрут обхода всего интернет-ресурса в
    соответствии с указанными директивами.&lt;/li&gt;
&lt;li&gt;Внутри заголовка любой HTML-страницы или любого другого документа,
    передаваемого по http протоколу (с помощью заголовков самого
    протокола), можно разместить специальный meta-tag для роботов,
    который также должен соответствовать &lt;a href="https://www.insight-it.ru/goto/fef0ecbb/" rel="nofollow" target="_blank" title="http://www.robotstxt.org/meta.html"&gt;стандарту, опубликованному в 1996 году&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Основной частью &lt;em&gt;путеводителя&lt;/em&gt; чаще всего является карта &lt;a href="https://www.insight-it.ru/goto/9821991b/" rel="nofollow" target="_blank" title="http://sitemaps.org/"&gt;сайта в формате XML&lt;/a&gt;. С ее помощью программа может
    быстро определить весь ассортимент страниц, которые ей было бы
    неплохо проиндексировать.&lt;/li&gt;
&lt;li&gt;Самым последним был воплощен в жизнь метод, основанный на
    &lt;a href="https://www.insight-it.ru/goto/a9b68873/" rel="nofollow" target="_blank" title="http://microformats.org/wiki/rel-nofollow"&gt;микроформатах&lt;/a&gt;.
    Реализуется он с помощью параметра &lt;code&gt;rel="nofollow"&lt;/code&gt;, указанного
    внутри тэга &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;, который обозначает ссылку, не предназначенную для
    перехода по ней пауком.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Карты сайтов и директивы robots.txt предназначены для определения
маршрута путешествия crawler'а, в то время как микроформаты и
meta-тэги - для влияния на сам процесс индексации.&lt;/p&gt;
&lt;p&gt;У каждого из описанных выше методов есть своя узкая специализация:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;robots.txt предоставляет базовый набор директив для роботов, которым
    они следуют даже в случае конфликтов с другими использованными
    методами.&lt;/li&gt;
&lt;li&gt;Карта сайта влияет на последовательность и набор страниц, посещенных
    пауком, с помощью указания приоритетов страниц или времени последней
    модификации.&lt;/li&gt;
&lt;li&gt;Мета-тэги распространяют свое действие на весь документ и влияет на
    индексирование страниц (если они одновременно присутствуют как в
    заголовке (X)HTML документа, так и в заголовках &lt;code&gt;X-Robots-Tags&lt;/code&gt;
    HTTP-протокола, то приоритет считается выше у заголовков протокола).&lt;/li&gt;
&lt;li&gt;Микроформаты позволяют в случае необходимости переопределять
    параметры любого конкретного тэга документа, не смотря на указания в
    мета-тэгах.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;С синтаксисом robots.txt лучше всего ознакомиться прямо в
соответствующей спецификации, ссылку на которую я уже приводил (хотя
возможно в будущем я всетаки соберусь написать запись и по этому
поводу). Не знаю занимается ли кто-нибудь генерацией карт сайта вручную,
но для общего развития будет полезно изучить и ее формат, неплохим
примером может послужить &lt;a href="/sitemap.xml" title="XML Sitemap"&gt;XML-карта этого блога&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Fri, 18 Jan 2008 01:13:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-18:theory/2008/putevoditel-dlya-robotov/</guid><category>crawler</category><category>robots exclusion protocol</category><category>robots.txt</category><category>SEO</category><category>spider</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>Откуда возникает спам и как с ним бороться</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></channel></rss>