Tuesday, December 7, 2010

Асимметричная криптография

Ещё раз о вещах, которые мы должны помнить с университетской скамьи, но которые почему-то постоянно забываются :)


И так, ключевым понятием в асимметричной криптографии является пара публичный/приватный ключ. Использоваться эти ключи могут для либо для подтверждения личности отправителя, либо для защиты передаваемых данных. Рассмотрим два этих сценария более подробней на примере общения двух пользователей A и B, у каждого из которых есть сгенерированная (с помощью утилит типа OpenPGP или GPG) пара публичный/приватный ключ.


Подпись


Допустим, пользователь A хочет быть уверен, что данные ему будет отправлены именно пользователем B. В этом случае пользователь B шифрует данные своим приватным ключом. А пользователь A расшифровывает их с помощью открытого ключа пользователя B.


Защита данных


Допустим, А хочет быть уверен, что его данные сможет прочитать только пользователь B. В этом случае пользователь A шифрует данные публичным ключом пользователя B. A пользователь B расшифровывает их с помощью своего закрытого ключа.

Read more...

Saturday, November 27, 2010

Непрерывная интеграция на примере Hudson

Все мы прекрасно понимаем, что тестирование является неотъемлемой частью жизненного цикла разработки ПО. Чем чаще мы тестируем наш код, тем быстрее мы сможем обнаружить ошибку, вкравшуюся в него в ходе разработки, и быстрее её исправить. При этом стоит понимать, что тестирование крайне желательно проводить в окружении, максимально близком к боевому (ОС, ПО, Hardware, Нагрузка), что бы иметь возможность обнаружить ошибки, которые не проявляются на сервере разработки, но могут появиться в бою. Компануя два вышесказанных тезиса вместе мы получаем концепцию, называемую Continuous Integration.

Суть CI заключается в постоянной (например, после каждого commit'а) сборке и тестировании разрабатываемого ПО в максимально приближенной к боевой среде с целью как можно более раннего обнаружения ошибок и оповещения о них разработчиков. Сама идея CI принадлежит Martin Fowler, подробно описавшему её в своей статье.

Для автоматизации процесса непрерывной сборки существуют готовые решения (Hudson, CruiseControl), интеграцию одного из которых (Hudson) я и опишу в этой статье.



Задача


И так, допустим у нас есть два проекта: Java-сервис (со своей БД), и PHP-клиент (со своей БД) для него. Оба проекта распространяются в виде deb-пакетов. Необходимо настроить инфраструктуру непрерывной интеграции этих проектов.


Реализация


Для того, что бы иметь представление о том, чего же мы хотим в итоге добиться — начнём с конца: рассмотрим схему, которую мы хотим реализовать:




  • рабочая машина программиста — написание кода,

  • сервер SVN — хранение кода,

  • сервер Staging — установка и тестирование собранных проектов,

  • сервер Selenium — тестирование web-интерфейса,

  • сервер Repo — хранение собранных пакетов,

  • сервер CI — соединение всех узлов системы в единое целое.


Разработчик вносит изменения в проект на своей машине и commit'ит их в SVN. На сервере SVN срабатывает post-commit hook, который инициирует процесс build'а соответствующего проекта на сервере CI. Сервер CI обновляет версию пакета из SVN, компилирует проект, запускает unit-тесты, выкладывает проект на staging-сервер.

Для проектов без web-интерфейса запускаются интеграционные тесты, для проектов с web-интерфейсом запускаются тесты Selenium. Сервер CI формирует отчёты и при необходимости (в случае провала на любом из этапов сборки проекта) отправляет email-уведомление пользователю.

Выкладка пакетов проекта в репозитарий для боевых серверов производится разработчиком вручную во время релиза.


Hudson


Главным и самым интересным узлом в нашей системе является сервер CI. В данном случае это будет Hudson как одно из самых популярных и распространённых бесплатных решений.
Первым делом установим его. Hudson доступен в виде пакета, поэтому его установка довольно проста. Кроме того, всю свою конфигурацию Hudson хранит в файлах (/var/lib/hudson), в виду чего не требует интеграции с какой-либо БД.



Архитектура Hudson'а построена на основе plugin'ов. То есть по сути работа Hudson'а сводится к хранению настроек проектов/плагинов и сборке проекта. В свою очередь сборка проекта заключается в запуске в определённом порядке установленных плагинов, включённых в настройках проекта.
Плагины можно разделить на несколько условных групп, образующих цикл сборки проекта именуемый также как «pipeline» (настройка плагинов проекта доступна через меню «Настройки проекта»):

  • управление исходным кодом (получение/обновление кода проекта из репозитария),

  • триггеры сборки (настройка времени автозапуска для сборки проекта),

  • среда сборки (настройка среды сборки проекта: версия JVM),

  • сборка (основной этап: запуск плагинов, осуществляющих логику сборки, интеграции и тестирования),

  • послесборочные операции (формирование/публикация отчётов, нотификация).


К сожалению, Hudson позволяет изменять только порядок выполнения плагинов, входящих в группу «сборка» (порядок выполнения остальных плагинов в рамках своей группы определяется на основе значений аннотации @Execution коде плагинов). Поэтому, в случае если вам необходимо реализовать свой сценарий сборки, для которого не достаточно набора стандартных плагинов из группы «Сборка», можно пойти тремя путями:

  1. вызвать любой внешний исполняемый скрипт, реализующий этот сценарий (пункт ”Execute Shell” из меню ”Add build step”),

  2. подключить плагин системы сборки проекта (Phing, Ant, Maven) и указать необходимую цель,

  3. написать свой плагин.


По-умолчанию Hudson поставляется с уже установленными плагинами для работы с SVN и Maven. Этого могло бы быть вполне достаточно, если бы речь шла только о Java проектах. Однако допустим, что нам так же необходимо работать с PHP-проектами. В этом случае для сборки проекта логичнее использовать Phing, плагин для которого нужно установить отдельно. Делается это путём перехода в раздел «Настройка / Управление плагинами / Доступные обновления».



Обратите внимание, что некоторые плагины требуют запуска Hudson под Java 6. Изменить путь к JVM (ровно как и остальные конфигурационные опции) можно в файле /etc/default/hudson. В остальном все конфигурационные параметры касающиеся непосредственно работы Hudson могут быть отредактированы через браузер в web-интерфейсе.

Относительно настроек плагинов стоит также упомянуть, что плагин имеет как общие настройки («Настройка / Конфигурирование системы»), так и настройки проекта («Настройка / Имя проекта / Настроить проект»).



Теперь, когда все необходимые плагины установлены, мы можем создать новый проект/задачу, указав его имя и настройки для соответствующих плагинов: URL в репозитарии SVN и команду для сборки.





Обратите внимание, что вы можете производить сборку не по какому-то расписанию или при опросе репозитария при наличии изменений в проекте, а по коммиту в SVN. Благодаря тому, что Hudson имеет «Remote Access API», позволяющее кроме прочего инициировать сборку проекта, сделав GET-запрос, вы можете легко добавить соответствующий post-commit hook (например, с помощью svnlook) для вашего проекта.

Рассмотрим этап сборки:



На данный момент сборка пакета включает в себя получение данных из репозитария и выполнение цели Phing (сборка пакета). В принципе сюда же можно добавить запуск unit-тестов и deploy проекта на staging-сервер. Однако, тут стоит обратить внимание на несколько моментов.

Во-первых, конфиг для работы приложения на staging-сервере может отличаться от боевого конфига. В этом случае очевидным решением будет хранение в проекте конфига для staging-сервера и подмене им оригинального проекта при сборке (отдельная цель для сборки в случае Phing или профиль для Maven).

Во-вторых установить пакет на staging-сервер с помощью плагинов SCP и SSH (для работы плагина необходимо убедится, что параметр PasswordAuthentication в конфиге sshd выставлен в yes, а хост staging-сервера добавлен в known-хостов) не получится, так как плагин SSH относится этапу сборки проекта, а plugin SCP — к послесборочным операциям. Поэтому проблему deployment'a проекта на staging-сервер придётся решать с помощью Phing или Maven + AntRun.
Для того, что бы наш сценарий сборки мог производить действия на удалённых серверах необходимо сгенерировать ssh-ключи: приватный ключ оставить на сервере CI, a публичный раскидать по всем серверам, с которыми будет происходить взаимодействие: staging, repo, svn — добавив их в список известных хостов (known_hosts). Кроме того, для того, что бы Hudson смог установить пакет на удалённом сервере потребуется завести на удалённом сервере соответствующего пользователя (hudson) и дать ему sudo.

В-третьих, для успешной сборки java-приложений с помощью Maven потребуется определить настройки Maven для пользователя hudson на сервере CI (имеется ввиду каталог ~/.m2).

Следующим шагом после установки пакета на staging-сервер должен стать запуск интеграционных тестов. Они могут быть запущены на самом сервере CI, однако, предпочтительнее сделать это на staging-сервере. В первом случае всё довольно просто: вызываем соответствующую цель Phing / Maven или настраиваем плагин SeleniumHQ.
Однако, открытым остаётся вопрос, что же делать, если требуется запустить процесс тестирования на внешнем сервере — например, обратиться к серверу Selenium RC? Ответ тут как нельзя прост: Selenium RC имеет HTTP API для работы с ним, поэтому самым тривиальным решением в данном случае будет написание небольшого скрипта на любом угодном вам языке, который инициирует процесс тестирования и время от времени опрашивает удалённый сервер на предмет завершения теста. Далее этот скрипт подключается к сценарию сборки через плагин ”Execute Shell”. Добавлю ещё, что успех или неуспех работы скрипта определяется Hudson'ом на основе кода возврата вашего скрипта.



Настроив процесс сборки не забудем о самой важной части процесса — уведомлении разработчика о результатах сборки. Hudson позволяет настроить почтовые уведомления как для конкретных получателей, так и для авторов commit'ов, чьи изменения вызвали поломку.



В дополнение рекомендую всем, кто будет использовать Hudson для PHP-проектов ознакомиться с соответствующими статьями из Wiki Hudson'а.


Сервер Staging



Установка пакетов


И так, как уже говорилось выше, в нашей инфраструктуре должен присутствовать сервер по конфигурации максимально приближенный к боевому. На этот сервер Hudson будет устанавливать самые свежие пакеты проектов, собранных по trunk'у. Это даст нам возможность:

  1. проводить интеграционное тестирование в условиях максимально приближенных к боевым,

  2. позволит иметь своего рода площадку для демонстрации самой свежей функциональности.


Одной из основных проблем, которую придётся решить при настройке данного сервера, является «тихая» установка пакетов. Для того, что бы наши пакеты устанавливались без лишних диалогов (то есть могли быть установлены с помощью скриптов или плагинов Hudson'а) необходимо переконфигурировать debconf (dpkg-reconfigure debconf), указав ему уровень важности задаваемых вопросов выше, чем те, что используются в установочных скриптах вашего deb-пакета.



Кроме того, между устанавливаемыми на staging-сервер пакетами возможны зависимости. Так, например, проект «клиент» зависит от проекта «сервер». В этом случае мы должны явно следить за тем, что бы на staging-сервере при установке пакета «клиент» происходила установка необходимого ему пакета «сервер».

На первый взгляд очевидным решением, с учётом дистрибуции проекта через deb-пакеты,
будет управление зависимостями силами dpkg путём добавления в dependencies control-файла пакета «клиент» информации о пакете «сервер».
В этом случае нам также придётся выделить отдельный debian-репозитарий, в который будут сливаться все собранные сервером CI пакеты, и дополнить сценарий сборки командой копирования пакета в репозитарий. Кроме того, необходимо будет организовать механизм автообновления данных в этом репозитарии при добавлении нового пакета, организовать доступ к пулу репозитария (например, подняв веб-сервер) и добавить данный репозитарий в sources-list на staging-сервере. При организации автообновления вручную (запуском сканера пакетов после выкладки пакета в репозитарий) новый пакет можно будет ставить через apt, в случае если репозитарий будет обновляться по расписанию придётся изобретать фокусы типа dpkg -i package; apt-get -f install. Подробнее о настройке своего debian-репозитария можно почитать тут.

Однако, данный подход имеет ряд недостатков. Во-первых, зависимости могут быть установлены только на этот же сервер. Во-вторых, такой подход довольно значительно усложняет всю систему в целом, что противоречит принципу KISS (ну или «ЧМОКЕ», если по-русски :D).

Лучшим решением, на мой взгляд, тут будет использовать репозитарий только для взаимодействия с боевым сервером. При этом выкладка пакетов в репозитарий должна осуществляться не автоматически, а по решению разработчика. Что же касается staging-сервера — на нём будут устанавливаться пакеты из trunk'ов основного пакета и всех его зависимостей, что позволит значительной снизить сложность системы CI, при этом дав нам возможность иметь на staging-сервере последние актуальные версии
пакетов.


Работа с БД


Наши пакеты могут использовать БД. В этом случае БД также устанавливается на staging-сервер, а обновление структуры / данных БД производиться с помощью утилиты dbdeploy.
Интегрировать dbdeploy в проект двумя путями:

  1. под каждую БД выделяется отдельный проект в SVN и как следствие - в Hudson, со своим сценарием сборки, инициируемым по hook'у SVN (вариант имеет смысл, когда БД используется несколькими проектами),

  2. структура файлов dbdeploy становиться частью основного проекта, а вызов скрипта актуализации версии БД dbdeploy происходит в postinst-скрипте пакета.



Отдельно в данном случае встаёт вопрос об изменениях данных БД в ходе тестирования. Понятно, при написании модульных тестов мы не работаем с БД, а используем mock-объекты (мне, например, нравится Mockito).
Однако, как быть с интеграционными тестами, которым просто необходимо работать в «реальных» условиях? В случае XUnit-тестов мы можем выполнять каждый тест в рамках транзакции к БД. Такой подход на мой взгляд является более предпочтительным, так как с учётом версионирования БД через dbdeploy мы всегда знаем, какие данные у нас есть в БД на текущий момент и можем смело привязываться к ним в наших тестах. Однако, в случае тестирования web-интерфейса (например, с помощью Selenium) у нас нет возможности запускать каждый тест в рамках транзакции.
Поэтому вариантов тут на мой взгляд остаётся два: либо перед запуском тестирования web-интерфейса полностью переинициализировать данные в БД на основе имеющихся
патчей, либо строить тесты так, что бы они не привязывались к каким-то конкретным данным из БД (например, создавали необходимые для тестирования данные через web-интерфейс сами) и по возможности не оставляли после себя «мусора».


Cервер Selenium


В случае, когда приложение не имеет web-интерфейса, интеграционный тест на staging-сервере, как я уже писал выше, вполне может заключаться в запуске XUnit-тестов. Однако, при наличии пользовательского интерфейса крайне удобно провести полное тестирование всей цепочки от HTML до БД с помощью Selenuim'a.

Selenium — это мощная система тестирования web-приложений, которую условно можно разделить на две части:

  • Selenuim IDE — инструмент для разработки и запусков сценариев тестирования в браузере (доступно в виде plugin'a firefox),

  • Selenium RC — распределённая система из сервера Selenium и подчинённых ему клиентов, на которых запускаются тесты под разными браузерами.


По понятным причинам, нас интересует второй вариант. По скольку установка и настройка Selenuim'а — довольна большая тема, касаться её в этой статье я смысла не вижу: вся информация есть в документации.


Замечания


Стоит заметить, что CI можно проводить и в ручном режиме, каждый раз компилируя и тестируя код перед commit'ом. Однако, автоматизация данного процесса с помощью сервера CI на много целесообразней. Кроме того важно понимать, что CI и ночные сборки (nightly builds) — не одно и тоже. Последние позволяют выявить баги, но с большим запозданием, в то время как цель CI — скорейшее обнаружение ошибок. На мой взгляд ночные сборки могут послужить частичной заменой CI только в том, случае когда сборка и тестирование проекта — процесс, занимающей довольное большое количество времени. Кроме того, если в проекте есть как unit, так и интеграционные тесты, можно разбить сборку проекта на две части: первая (с unit-тестами) запускается каждый раз при commit'e, вторая с интеграционными тестами — раз в час/сутки.


Вывод


Описанное выше решение работает и приносит профит. Однако, как мы все знаем, теория, к сожалению, далеко не всегда соответствует практике. Внедрение системы CI потребовало решения ряда проблем, не все из которых были решены идеально.

Вероятность того, что для staging-сервера кто-то даст вам ресурсы, сравнимые про характеристикам с боевыми, крайне мала — скорее всего это будет средней мощности виртуальник на полузаброшенной хост-машине, что в корне подрывает один из принципов CI - тестирование в схожем окружении. Это в свою очередь влечёт за собой то, что интеграционные тесты, могут начать занимать гораздо большее время, чем планировалось изначально. Поэтому «непрерывностью» в моём случае пришлось поступиться и начать запускать тесты не по hook'ам SVN, а по расписанию.

В целом же при наличии в вашей команде некоторой культуры разработки (я имею в виду понимание того, что CI — не панацея, а лишь инструмент, который при должном умении обращения с ним может улучшить качество их работы) внедрение CI вполне оправдано.

Ну и наверное самое главное: как показала практика, интеграция системы CI - задача командная. Для её решения потребуется работа разработчиков, тестировщиков и администраторов.

Read more...

Wednesday, October 27, 2010

HighLoad++ 2010

На днях в Москве прошла "конференция разработчиков высоконагруженных систем" Highload++, участником котрой мне посчастливилось стать. Ниже я хочу кратко пройтись по докладам, которые посетил в рамках конференции, выделив в них интересные на мой взгляд моменты.



День 1


Первый день конференции полностью состоял для меня из англоязычных докладов. Доклады были очень интересными, за что организаторам большое спасибо.


Perfomance tweaks and tools for Linux


Довольно интересный доклад об утилитах Linux, котроые можно использовать при отладке приложений.

  • lsof - утилита для получения списка открытых файлов;

  • strace - утилита для просмотра системных вызовов и сигналов, происходящих при выполнении заданной команды;

  • ltrace - утилита для просмотра обращений к системным библиотекам, происходящих при выполнении заданной команды;

  • tcpdump / wireshark - утилита для просмотра сетевого трафика;

  • ab - утилита для нагрузочного тестирования HTTP-серверов;

  • sysbench - утилита для нагрузочного тестирования БД;

  • gdb - консольный отладчик приложений;

  • ioprofile - комбинация утилит lsof и strace для анализа I/O активности приложения;

  • /proc file system - псевдофайловая система для отображения ядерной информации (данные о конкретном процессе можно найти в каталоге/proc/PID/*);

  • iostat - утилита для мониторинга I/O опреций в системе;

  • ethtool - утилита для управления настройками Ethernet карт;

  • taskset - утилита для привязки процесса к заданному CPU;

  • irqbalance - утилита для распеределения прерываний оборудования между CPU.




Scaling to hundreds of millions of requests


Рассказ о развитии соц. сети для поклоников BSD BDSM :) Можно выделить следующие этапы развития проекта:

  • Проект располагается на одном сервере, возникают проблемы при масштабировании
    (scalability);

  • Проект переезжает на облака Амазона: очень удобно регулировать ресурсы, но переодически возникают внезапные кратковременные падения производительности ("spikes");

  • Проект переезжает обратно на выделенный хостинг. БД мигрирует на NoSQL решения (MongoDB), которые по началу показывают неплохие результаты. Однако, обнаруживается, что у MongoDB есть проблемы с конкурентными запросами (прим. проблема вроде бы уже решена), а с Cassandra у ребят возникли некие проблемы в бою;

  • Выбор БД останавливается на MySQL (master + slave) и Redis. В настоящий момент проект обрабатывает 70.000.000 requests per month.




Доклад о Facebook


Поверхностный рассказ об устройстве Facebook'a.

  • В разработке ребята из Facebook используют максимально короткие итерации, постоянно выкладывая изменения в бой. Это позволяет им сразу получать реакцию пользователей и исправлять баги. Естествено, что для каждого релиза составляется план отката;


  • Архитектура Facebook состоит из трёх слоёв: web-server'а, cache (memcache) и база данных (mysql без использования join'ов). Каждый из этих слоёв масштабируется горизонтально;


  • В системе нет ни одной единой точки отказа;


  • Пользовательский контент (картинки) храняться в MySQL (sic!). Используется шардинг (sharding) БД. На каждом узле (шарде) настроена репликация.




Shared Personalization Service - How to Scale to 15K RPS


Первый услышанный мною доклад от Microsoft, который мне вообщем-то понравился. Из интересных моментов можно выделить два:

  • При обновлении данных ребята сначала "подогревают"/обновляют кеш, и только потом пишут данные в БД;

  • Данные о пользователях шардятся по серверам. При этом соответсвие между Id пользователя и шардой вычисляется не автоматически, а храниться в отдельной (надо полагать key-value) БД.




Developing PostgreSQL perfomance


Общий рассказ о разработке PostgreSQL одним из авторов.

  • Регулярый benchmark перед каждым релизом;

  • При разработке приходится сталкиваться с проблемами, включающими в себя следующие аспекты: алгоритмы, системные библиотеки, оптимизация копилятора, работа с ОС, hardware;

  • Postgres может подойти под любые нужды - главное правильно подобрать настройки;

  • Postgres никогда не станет платным.




Managing replication of PostgreSQL


Доклад об особенностях репликации в PostgreSQL.

  • Существует два типа репликации: trigger-based (userspace) и log-based (integrated);

  • Примером trigger-based репликации является Slony;

  • Начиная с версии 9.0 PostgreSQL поддерживает log-based репликацию. На данный момент реализация асинхронная (на slave'ы данные поступают с задержкой в 200ms). Начиная с версии 9.1 (11.2010) добавится возможность синхронной репликации;

  • Log-based репликация не показала сколь-либо существенного падения производительности при 6-ти slave'ах;

  • При log-based репликации мастер не дожидается коммита транзакции, а сразу отсылает данные на slave/standby.




Scaling with Postgres


Своего рода "best practice" работы с PostgreSQL.

  • Культура разработки куда важнее новых технологий;

  • Программист должен работать в тесном сотрудничестве с DBA;

  • Для мониторинга Postgres'a пригодится утилита check_postgres.pl;

  • Для профилирования запросов к PostgreSQL пригодится утилита pgfouine;

  • Минимально допустимая для разумных людей версия PostgreSQL на данный момент 8.3;

  • Для реализации репликации стоит использовать следующие варианты:

    • Master - Master: Bucardo;

    • Master - StandBy: PostgreSQL 9.0;

    • Master - несколько Slave'ов: Slony.



  • Sharding: разбивайте БД на несколько, группируя таблицы по сервисам;

  • Pooling: открытие соединения - очень дорогая операция, так как требует создания нового процесса. Для ускорения работы приложения следует использовать пул соединений с БД.




Rapid upgrades with pg_upgrade


Рассказ о замечательной утилите pg_upgrade, позволяющей быстро и безболезненно обновить версию PostgreSQL.

  • База в 150GB обновляется с версии 8.3 до 9.0 в режиме link mode за 44 секунды, в режиме copy mode за 44 минуты.




Progressive downloads and rendering


Доклад разработчика Yahoo oб оптимизации времени загрузки HTML-страницы.

  • HTML5 позволяет асинхронную (async) и отложенную (defer) загрузку JS-файлов. В HTML4 эта функциональность доступна через DHTML;

  • Загрузка CSS-файлов блокирует rendering страницы. Для решения проблемы можно встраивать CSS в HTML-код страницы;

  • Для ускорения загрузки скриптов, расположенных в HTML-элементе HEAD можно насильно вызвать flush данных: <head></head><?php fluch();?>;

  • Приём с flush'ем также можно использовать для ускорения отрисовки обособленных блоков на странице;

  • Изображения можно хранить как часть HTML-страницы c помощью Data URI или Mime HTML;

  • Изображения можно загружать lazy-методом после загрузки основной страницы.





День 2


Второй день так же был весьма познователен, хотя на этот раз выступали уже только наши соотечественники.


Sphinx Real Time indexes


Рассказ о новой возможности поискового движка Sphinx - Real Time индексах.

  • RT индексы в несколько раз медленне на больших (2 млн) объёмах данных;

  • RT индексы для ускорения работы требуют большего количества оперативной памяти;

  • RT индексы на практике работаю медленее, хотя в теории при выделении достаточного объёма оперативной памяти могут работать быстрее.




Sphinx для высоконагруженных и масштабируемых проектах


Доклад о сервисе поиска по десяткам терабайт данных.

  • Используются классические, а не RT индексы, так как последние не достаточно обкатаны;

  • Индекс тупо шардится по серверам. Выделяется основной сервер, на котором сконфигурирован distributed индекс, конкатинирующий шарды.




Масштабируемая система голосования на базе PostgreSQL PgQ


По сути доклад сводится к описанию работы с очередью сообщений на основе PostgreSQL - PgQ.

  • При наличии большой таблицы скорость работы с ней в некоторых случаях можно увеличить, выделив редко используемые данные и поместив их в архивную таблицу;

  • Очередь - это кран в трубопроводе, которым можно регулировать поток/нагрузку на нижележащие узлы в системе (очередь PgQ имеет конфигурируемые пропускные параметры);

  • Очередь PgQ - часть проекта skytools: набор утилит для работы с PostgreSQL от Skype;

  • Производительность PostgreSQL можно увеличить следующими способами:

    • Настроить vacuum;

    • Отключить fsync (возможна потеря данных, довольно спорное решение);

    • Включить асинхронные коммиты;

    • Hardware решение - поставить SSD-диски.






Компиляция скриптов PHP


Доклад ради доклада, не особо интересно.

  • Цель компиляции PHP-скриптов - избежать избыточной работы по лексическому анализу и интерпритации токенов в opcode;

  • Компилироваться PHP может как в native код (Roadsend, Raven, Phc, Hiphop), так и в non-native (Project Zero для Java, Phalanger для .NET);

  • 100% кода Facebook компилируется через HipHop;

  • HipHop не поддерживает некоторые функции (eval, create_function, preg_replace), не поддерживает большинство модулей, не поддерживает PHP 5.3 и реализован только под 64-ый Linux;

  • На больших нагрузках ведёи себя чуть лучше, чем Apache/Nginx + APC;

  • Результатом работы компилятора HipHop является исполняемый файл со встроенным web-сервером;

  • Единственная Success Story - это Facrbook, сам докладчик переводить свой сайт (rbk.ru) почему-то не торопится :)




Goal driven performance optimization


Абстрактный доклад о том, что же такое производительность от главы Percona Петра Зайцева.

  • Выделение параметров производительности: время отклика, загруженность системы;

  • Метрики: среднее время, максимальное время, проценты (95% запросов выполняются за 10s);

  • Типы медлительности: случайная, характерная для определённого сервиса;

  • Типы пользователей: люди, боты, сервисы;

  • Инструменты для замера производительности.




InnoDB architecture and performance Optimization


Реклама Percona и описание возможностей их XTraDB на фоне рассказа о настройках InnoDB.

  • Традиционная OLTP архитектура на основе с Orcale;

  • Хранит данные по строкам;

  • Блокировка на уровне строк;

  • Write ahead log (WAL);

  • Thread per connection.




Доклады о ВКонтакте


Дуров произвёл довольно неприятное впечатление. И вообще, контакт пишут лучшие умы современности и многократные победители олимпиад :)

  • 32 фронтэнда + тысячи бекендов (4 датацентра + 2 строятся, в Москве и Питере);

  • Деплоймент "обычный" самописный;

  • Мониторинг "обычный" самописный, шлёт SMSки;


  • Пользовательская статика хранится на XFS. Общей сетевой файловой системы между бекендами нет, всё разруливается на уровне скриптов;


  • Личные сообщения хранятся в самописном in-memory storage engine;

  • Собственный memcache c persistence и сжатием данных;

  • Новости реализованы как демон на Си + MySQL + Memcache. Сами новости храняться вместе с пользователями, которые их сгенерировали. Сборку новостей в ленту осуществляет отдельный сервер. Инициирует сбор новостей в ленту, тот кто читает новости своих друзей;

  • Поиск по анкете: нереляционная БД со специальным форматом ключа, содержащим характеристики пользователя + демон на Си с интерфейсом Memcache;


  • Сервера: ОС Debian Linux (свои доработки), Железо не брендовое (Intel 8 Core, 64 GB RAM);

  • Сервера используются в нескольких аспектах сразу: диск для фото, память для memcache;


  • Балансировка нагрузки средствами Nginx;

  • ПО: nginx / apache + modphp + XCache;


  • Нагрузочное тестирование проводится на группе пользователей (первые 10.000 Id);


  • Защита от DDos: пасинг логов (выявление закономерностей) в realtime и переконфигурирование nginx, решение проблемы на маршрутизаторах;


  • История: Переход с одного сервера на 2 после 10.000 посетителей в день;

  • Фотографии не удаляются с жёстких дисков и остются доступны по прямой ссылке (для уменьшения фрагментации).




Мастер класс по хранимым процедурам в MySQL


Доклад/МастерКласс от сотрудника MySQL/Oracle.

  • Использовать хранимые процедуры стоит только в административных целях. Не надо размазывать бизнес логику из приложения в БД;

  • Процедуру можно запускать из-под определённого пользователя (ключевое слово DEFINER);

  • PL/SQL корнями уходит в язык Ada;

  • Курсор при открытии материализуется во временную таблицу;

  • Результат работы харнимой процедуры кешируется локально для соединения (в отличие от trigger'ов);

  • Реализация некоторой логики на хранимых процедурах в разы медленнее реализаций на популярных языках программирования;

  • Кореллированные запросы при прочих равных быстрее работают на хранимых процедурах.





P.S.



  • Заметил, что многие люди используют слово "функциональность", вместо распространённого "функционал". С точки зрения русского языка это должно быть верно... надо будет перенять модную московскую тенденцию :)

  • Прослушивание докладов на иностранном языке здорово повышает ЧСВ. В некоторые моменты я прямо-таки чуствовал, как моё переваливает за 9000 :) А если серьёзно, было бы здорово, если б все люди общались на одном языке и не было бы языковых преград для обмена опытом и знаниями.



Read more...

Wednesday, May 5, 2010

Извлечение фактов

Задача извлечения информации из текста сама по себе не нова: в этом направлении проделано довольно много работы как со стороны крупных компаний aka Яndex и Google, так и со стороны независимых разработчиков. Однако, говорить о том, что данная задача окончательно решена, увы, не приходится. В этой статье я хочу немного упорядочить свои знания по данному вопросу, поверхностно разобрав наработки, с которыми мне недавно пришлось столкнуться.


И так, пусть нам дано предложение "Визит Президента в Данию придаст новое дыхание диалогу двух стран". Для вычленения фактов из этого предложения потребуется пройти следующие этапы:


I. Токенизация

На данном этапе предстоит разбить предложение на отдельные слова. Проблем тут возникнуть не должно.


II. Морфологический анализ

После разбивки, для каждого слова необходимо получить морфологическую информацию о нём (часть речи, род, падеж, число и т.д.) и всевозможные атрибуты (например, является ли слово именем или географическим месторасположением). Для данной задачи необходимо наличие специальных словарей: в качестве реестра русских слов можно использовать словарь Зализняка или его проприетарные производные. В качестве готового решения можно рассмотреть утилиту Mystem от Яndex.

В случае использования утилиты Mystem исходное предложение будет разобрано следующим образом:

krestyaninov@localhost# echo "Визит Президента в Данию придаст новое дыхание диалогу двух стран" | ./mystem -niwg
Визит{визит=S,муж,неод=(им,ед|вин,ед)}
Президента{президент=S,муж,од=(род,ед|вин,ед)}
в{в=PR=|в=S,сокр=(им,ед|им,мн|род,ед|род,мн|дат,ед|дат,мн|вин,ед|вин,мн|твор,ед|твор,мн|пр,ед|пр,мн)}
Данию{дания=S,гео,жен,неод=вин,ед}
придаст{придавать=V=непрош,ед,изъяв,3-л,сов}
новое{новое=S,сред,неод=(им,ед|вин,ед)|новый=A=(им,ед,полн,сред|вин,ед,полн,сред)}
дыхание{дыхание=S,сред,неод=(им,ед|вин,ед)}
диалогу{диалог=S,муж,неод=дат,ед}
двух{два=NUM=(род|вин,жен,од|вин,муж,од|пр)}
стран{страна=S,жен,неод=род,мн}

III. Синтаксический разбор

На данном этапе определяются связанные подгруппы слов в предложении. Например, СУЩЕСТВИТЕЛЬНОЕ-ГЛАГОЛ: "визит-предаст". Установление этих связей позволит нам определится с неоднозначностями в морфологическом анализе. Так например, из словосочетания "новое дыхание" видно, что "новое" - это прилагательное, а не существительное (в чём не было уверенности после морфологического анализа).


IV. Семантический разбор

Задача семантического анализа заключается в построении полноценного дерева связей слов в предложении. Данный процесс имеет множество нюансов и в целом довольно сложен, для того, что бы быть описанным в этой статье. Подробней о семантическом анализе можно почитать здесь.


V. Извлечение фактов

Для извлечения фактов можно использовать следующие инструменты:
Поиск опорного элемента: В тексте ищется некоторое слово (например, "Президент"), на основе которого исходя из дерева связей строится факт;
Поиск по шаблону: Поиск данных по регулярному выражению (например, вычленение даты);
Поиск по онтологии: Поиск данных на основе предикативных правил, описанных на специальном языке. Пример.

Подробнее об извлечении фактов можно посмотреть по перечисленным ниже адресам:
Презентация "Яндекс.Пресс-портреты";
Презентация: "Автоматическое извлечение фактов из текста";


Существующие решения


Из существующих сколь-либо приемлемо работающих свободно распространяемых систем извлечения фактов мне удалось найти лишь систему под названием GATE. Система довольно интересная и многообещающая, однако нативной поддержки русского языка она, к сожалению, не имеет. Попробовать её в действии можно с помощь этого мануала.

Из платных систем можно отметить отечественную разработку RCO.


Дополнительные ссылки по теме


Извлечение ключевых слов с помощью Wikipedia;
Обзор Text Mining систем;
Обзор лингвистической системы "Semantix".


Read more...