Wednesday, October 24, 2012

HighLoad 2012

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



День 1



Хранение и доставка контента ВКонтакте



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

Изначально все файлы (фотографии) хранились на том же сервере, что и код - в папке upload. Этот подход прост, но имеет два изъяна: безопасность (заливка кода, XSS) и масштабируемость.

Далее ребята озадачились масштабируемостью, организовав следующую схему: файлы заливаются на основной сервер, а потом переносятся на вспомогательные (предназначенные специально для пользовательских данных). Каждому пользователю всегда соответствует один и тот же вспомогательный сервер, определяемый по id пользователя. Однако, у этого подхода есть bottle neck - основной сервер.

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

Поиск и устранение узких мест. Обычно самое узкое место одно - остальное узлы системы по сравнению с ним работают на порядок лучше. Bottle neck'и при хранении большого объёма пользовательских данных могут быть следующие:
  • резервирование данных (используется RAID, если выгорает весь массив из 2х дисков - файлы пользователя теряются безвозвратно);
  • кеширование (60% контента достаётся из кеша на клиенте);
  • трафик (решением является CDN, особенно для видео: у ВКонтакте в Москве стоят сервера, которые кешируют видео с дата-центра в Спб);

В качестве файловой системы используется XFS. Однако пользовательские файлы хранятся не в файловой системе, а в одном большом файле. Файл всегда открыт для чтения, индекс файла хранится в оперативке. Дальнейшее развитие данной технологии ребята видят в полном абстрагировании от физических носителей.

В виду того, что широко распространения WiFi ВКонтакте переходит на HTTPS. Так как серверов с контентом огромное количество - на каждый из них сертификат не купишь (слишком дорого). Поэтому у ВКонтакте стоит несколько серверов, которые проксируют контент через HTTPS.

Что каcается картинок:
  • всего более 30 000 000 000, в сутки добавляется 17 000 000;
  • изображения предварительно сжимаются на стороне клиента (Flash);
  • используется Graphics Magic;
  • при сохранении фотографии нарезаются сразу для всех необходимых разрешений;

Что касается аудио:
  • в сутки добавляется 130К;
  • пользователя имеют возможность "добавить" к себе данные со страницы другого, что на порядки снижает количество загружаемого аудио;
  • при запросах правообладателей файлы изначально искались по md5-хешу. Сейчас разработан алгоритм, который находит похожие аудио-записи по некоторым аудио-характеристикам;

Что касается видео:
  • в сутки добавляется 320К;
  • используется отложенная обработка видео через очередь - слишком дорого обрабатывать видео онлайн;
  • для обработки видео используется ffmpeg;
  • видео дублируется при повторной загрузке другими пользователями - это не проблема;
  • одно время у ВКонтакте был P2P для видео на flash (wat!?), сейчас уже справляются без него;

Вообще у меня сложилось ощущение, что контакт устроен относительно несложно. Несложно, но эффективно.


NoSQL в высоконагруженном проекте


Доклад о том, как NoSQL используется в Mamba. Особенности рассматриваемой системы заключаются в том, что более 30% выполняемых запросов - инкремент и чтение счётчиков.

Начинали поиск подходящего хранилища для данных как и полагается с Memcache. Не устроило отсутствие персистентности и RAM ONLY. Попробовали Radis - RAM ONLY. Кроме того при большой нагрузке производительность Memcached падает в 100 раз (Для тестирования нагрузки использовали инcтрумент Brutis).

Долго ли, коротко ли, ребята пришли к использованию TokyoTyrant. Однако, у него внезапно обнаружились проблемы с целостностью БД при выключении сервера из розетки :) Решили их новой разработкой от автора TokyoTyrant - KoytotTycoon. Однако, записать в базу 30М записей не удалось в виду архитектурных ограничений.

Поэтому ребята пошли в сторону LevelDB от Google. В этой БД используется технология LSM-tree. Данные хранятся в SSTable-файлах: отсортированные неизменяемые пары ключ-значение. Пишутся данные в аналогичную (но уже изменяемую) структуру в оперативной памяти. Время от времени происходит слияние поддеревьев из памяти на диск. Что бы не отхватить проблем при внезапном отключении питания - пишется Write Ahead Log.

Ребята ещё раз протестировали и получили, что в большинстве случаев библиотека LevelDB на порядок выигрывает у всех используемых ранее вариантов. Сейчас они держат 4700 get/sec и 1600 update/sec при 200М записей в БД.


MVCC unmasked


MultiVersion Concurency Control - механизм, позволяющий reader'ам не блокировать write'ов, а write'ам reader'ов. В общем - значительно уменьшает количество блокировок в БД. Присутствует в Oracle, Mysql InnoDB, PostgreSQl и некоторых других.

Каждая запись в таблицах MVCC систем имеет два атрибута: creaton (xmin) - номер транзакции, в которой запись была создана, expiration (xmax) - номер транзакции, в которой запись была удалена.

    INSERT xmin 40, xmax Null
    DELETE xmin 40, xmax 47 

    UPDATE xmin 64, xmax 78 / xmin 78, xmax NUll


При выполнении каждого statement'а создаётся MVCC snapshot, который определяет, какие данные в БД видимы/доступны statement'у. Алгоритм определения видимости строки следующий:
  • получаем номер последней завершенной транзакции (current);
  • считаем видимыми те записи, у которых:
    • xmin < current номера;
    • они не удалены (xmax = null), либо транзакция, в которой они удалены, не закомичена;

Поля xmin и xmax присутствуют в каждой таблице, но скрыты по-умолчанию. Однако, их можно всегда указать в выборке явно: SELECT xmin, xmax, * FROM test;

Получить id текущей транзакции можно с помощью запроса SELECT txid_current(). Данный запрос выбирает данные из таблицы pg_clog. Важно понимать, что откат транзакции - это просто установка соответствующего маркера для записи о транзакции в этой таблице. Ни какие данные при этом не удаляются. Транзакция просто помечается как откаченная.

Не MVCC CУБД требуют непосредственного изменения данных при изменении или удалении записей. MVCC СУБД лишены этой проблемы - все неактуальные данные чистятся отложено. Тут хочется добавить от себя, что отложенная чистка (так называемый VACUUM) - не так совершенен, как хотелось бы... но это тема для отдельного разговора.

Кстати, вот сайт докладчика, на котором он обещал много интересных статей.


MySQL в Google


Пожалуй, самое большое разочарование среди докладов. Если коротко, то суть его сводится к одному тезису: "Да, у нас есть слегка пропатченный нами MySQL". Может у меня завышенные требования, но я ожидал от Корпорации Добра чего-то более интересного.

Крупнейшие проекты: Ads, Checkout и, конечно же, YouTube.

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

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

Для того, что бы организовать масштабирование и отказоустойчивость ребята вводят много ограничений на работу с БД. Например, транзакция на запись не может идти дольше 30 секунд. Нужно для того, что бы можно было оперативно сделать мастера из другого слэйва.


Поддержка SPDY в NginX


SPDY - бинарный протокол поверх TCP/TLS соединения. Является транспортом для HTTP. Разработан Google.

Основные фичи:
  • мультиплексирование (несколько запросов за одно соединение, как от сервера к клиенту, так и наоборот);
  • сжатие заголовков (zlib, deflate);
  • flow control (окно для tcp-соединения);
  • server push ("заливка" данных в браузер, инициированная сервером);

Из плюсов: встроенный HTTPS (за счёт TLS), хорошая работа при большом количестве картинок (за счёт мультиплексирования); Из минусов: работает с одним доменом, как следствие - не поддерживает CDN;

По исследованиям (боевым) Wordpress'a: SPDY быстрее HTTPS, но медленнее обычного HTTP.


SQL Tricks


Доклад представлял собой список интересных, но не всем знакомым фич SQL/PostgreSQL:
  • view - эффективное средство для инкапсуляции логики и/или таблиц. С первым не соглашусь, а вот второе использую (переименование таблиц);
  • postgres использует кеш ОС (поэтому предлагают выделять ему или немного, или всю);
  • pgbench - утилита для тестирования Postgres;
  • Common Table Name (CTE) / Recursive CTE;
  • оконные функции;
  • поддержка JSON (c 9.2);
  • поддержка lateral (использование вычисляемых по текущей строке данных в FROM clause, c 9.3);
  • расширение для работы с текстом и триграмами: pg_trgm;
  • расширения для хранения пар ключ-значение: hstore;
  • подключение таблиц из других БД через dblink;
  • расширения для работы с гео-данными: PostGIS и EarthDistance;
  • prepared statements - позволяют избежать накладных расходов на разбор запроса, проверку существования и прав, построение плана (иногда может занимать больше времени, чем выполнение);
  • блокировки можно устанавливать явно через конструкцию select ... for share;
  • в PgSQL Prepared Statements доступны через execute;
  • блоки кода do $code$ .. $code$ (c 9.1);
  • upsert лучше реализовывать через insert -> fk constraint -> update;
  • вернуть несколько значений из функции можно вернув курсов (в рамках транзакции) или сгенерировав JSON (row_to_json, array_to_json);

Докладчик, кстати, реально опасен: написал с помощью Recursive CTE и Regexp'a парсер JSON'а в Postgres массив одним запросом! :)


Крадущийся сервер, затаившейся диод


"Здравствуйте, меня зовут Андрей, я Воронежское быдло". На этом описание доклада можно окончить :) В общем Аксёнов во всей своей красе.

Основные тезисы:
  • при бенчмарках - главное помнить о целях: мерить надо нужное, а не load average;
  • средние значения при метриках ничего не значат: средняя температура по больнице - это холодные трупы и лихорадочные коматозники;
  • масштабируемость нелинейна (закон Амдала - даже если не параллелится 5%, то 64 * CPU = 14,5 X)
         C(n) = n /(1 + a*(n-1) + b*n*(n-1)), где
         a - степень contention (затраты на нераспараллеленный код),
         b - степень coherency (затраты на когерентность, коммуникацию, синхронизацию);
  • можно выделить sweet spot - количество ресурсов, при которых производительность будет оптимальной;
  • после sweet spot производительность наоборот начинает падать - с ростом может быть хуже;
  • не тестировать на дефолтных настройках - у большинства ПО они мягко говоря странные (fsync после каждого Insert'a и innodb_buffer_pool в 32Мб в MySQl);
  • прогнать один и тот же запрос 1000 раз - протестировать кеш;

Мировые константы - важно понимать, какое действие сколько стоит.
  • CPU L1 - 1 000 000 000 op/sec (1e9)
  • CPU L2, misbranch - 100 000 000 op/sec (1e8)
  • RAM Access - 10 000 000 op/sec (1e7)
  • SSD megaraid - 100 000 op/sec (1e5)
  • SSD - 10 000 op/sec (1e4)
  • LAN, 1MB RAM - 1 000 op/sec (1e3)
  • HDD seek, 1MB LAN - 100 op/sec (1e2)
  • WAN roundtrip - 10 op/sec (1e1)
  •  
  • Memcached access - 10 000 op/sec (1e4)
  • RDB simple select - 100 op/sec (1e2)



Go Language


Getting started и Hello, World на языке GO.




День 2


Как устроен поиск


Утренний опохмел от Андрея Аксёнова :)
В работе Любой поисковой системы можно выделить 4 вехи: получение данных (робот-паук), индексация, поиск, масштабирование.

Индексация включает в себя:
  • получение текста (html, pdf->текст),
  • токенизация,
  • морфологическая обработка (стемминг, лемотизация),
  • создание инвертированного индекса (ключевое слово -> номера страниц в книге и позиции слова в них);
Данные в индексе необходимо сжимать. Сжатие может быть битовым, байтовым, блочным. Чем меньше данных - тем меньше нужно обрабатывать при запросе.

Поиск состоит из двух ортогональных этапов: быстро matching (найти) и качественно raking (отранжироать).
Критерии matching'a могут отличаться в зависимости от области его использования (web, data mining). Что касается ранжирования - оно в принципе до конца не может быть релевантным, ибо релевантность персональная для каждого пользователя. Поэтому для ранжирования используются хитрые алгоритмы типа BM25 (TF, IDF, DocLength), результаты которых по возможности персонализируются.

Что касается масштабирования - поиск требует ресурсов. Поэтому у Гугла миллионы серверов поиска, у Яндекса - десятки тысяч.


Поиск в Одноклассниках


Ребята умудрялись использовать fullscan поиск (на MsSQl) при 30М пользователях. На кластере их 16-ти баз один поисковый запрос работал в среднем 15-30 секунд. Поняв, что так жить нельзя - решили искать решение.

По скольку проект на Java, начали смотреть в сторону Lucene. За 3 года работы с Lucene внесли в него следующие изменения:
  • добавили репликацию;
  • хранение индексов в памяти (пробовали на RAM drive, маппинг файлов в Heap, но в итоге просто затянули файлы в ByteArray - в OldGeneration);
  • переписали поиск по индексам (дефолтный создавал слишком много объектов, что вело к проблемам с GC);

Сейчас в инфраструктуре выделен отдельный сервер-индексер, который создаёт поисковый индекс. Индекс реплицируется на query-сервера, которые хранят индекс как на диске, так и у себя в памяти (для обработки запросов используется индекс из памяти). Индексер получает данные через очередь, что позволяет ему быть недоступным время от времени.

Большой недоработкой было отсутствие логики прямого обновления индекса из БД, минуя очередь. Так как некоторые сообщения из очереди иногда пропадали. Эту же проблему я могу констатировать и у себя в компании. Вывод: sanity check при работе с очередями должен быть всегда.

Постоянно находятся в кеше только 5% запросов (самые часто запрашиваемые). Попадание в кеш 60%. Для персональных запросов создаются временные кеши (по запросу), которые живут несколько минут.

За каждым пользователем на портале закреплён отдельный app-сервер (вычисляется на основе userId). В случае проблемы с сервером пользователь перекидывается на резерв.

Поиск онлайн-пользователей сначала делали по общему индексу, фильтруя по флагу "онлайн" вне индекса. Потом создали отдельный индекс для этой цели.


Storing data in Evernote


Обзорный доклад про устройство и цифры Evernote.

Software: Java 6, MySQl 5.1, Debian (Stable), DRBD (распределённая система хранения данных), Xen. HardWare: SuperMicro 1U, 2x L5630 COU, 96 GB RAM, 6x 300GB Intel SSD, LSI RAID 5 (+ spare) ~ $8000.

DataBase: MySQL, 10TB (peak riops 350, peak wiops 50) Search engine: Lucene (peak riops 800, peak wiops 50)

Сервера расположены в США и Китае (400 Linux серверов).

Доступ к файлам контролируется через Apache/WebDAV. Данные всегда хранятся на одном хосте и не переносятся. По сравнению с NFS WebDav имеет небольшой overhead, но в разы проще и дешевле в развёртывании и поддержке.

Балансировка нагрузки используется железный балансер A10 with SSL (во внешку смотрит HTTPS, во внутрь проксируется HTTP).

С учётом особенностей сервиса (хранение множества мелких файлов) проблемы и их критичность можно описать следующей таблицей:
/ size normal load peak load
bandwith - medium medium
latence - low low
cpu - low medium
file size high low medium
meta data low medium low

Автор не рекомендует использовать облачные платформы, если ваше приложение требовательно к ресурсам (bandwidth, storage, cpu) или использует их в переменном количестве. Если возникают сомнения - посчитайте, во сколько обойдётся покупка и поддержка своих серверов под нужды приложения, и сколько это будет стоить у Amazon. В случае с Evernote разница в 1-4 порядка.


Механика DDOS


Этот доклад я пропустил почти полностью, так как был на обеде :) Из финальной части мне удалось вычленить только пару тезисов.

Самая простая защита от HTTP атак - limit зоны в Nginx. Так же можно обратить внимание на модуль NGINX "testcookie".

Тем не менее важно понимать, что Nginx - не средство от DDOS атак.


DDOS атаки в России 2012


Всего атак за 2012 год было >2600 атак (в прошлом году было где-то >1700).

Ботнета в 3000 машин достаточно, что бы завалить среднестатистический сайт. Самый крупный ботнет состоял из 150К машин. Больше всего бонетов живёт в Германии, США, Украине, Казахстан (по убыванию).

Активность DDOS совпадает с активностью e-commerce (ну и немного политики). Политические DDOS'ы используют ботнеты из Пакистана, Индии (там, куда не добраться правоохранительным органам).

Большинство атак генерирует трафик меньше 1GB (обычная пропускная способность сайта не больше).

При атаке первым делом нужно проанализировать логи (access.log) и сделать слепок трафика (tcpdump -s0 -c1000000 -w attack.dump). Далее нейтрализация атаки: вывести из-под мусорного трафика, заблокировать ip-адреса, с которых происходит атака, сменить IP.

Всегда стоит иметь как минимум 2х-кратный запас производительности сайта.

Особенности российского DDOS - Full Browser Stack (использование реальных браузеров, которые могут пройти все анти-ddos тесты).

Ну и да - если ожидаете проблем, обращайтесь в Qrator :)


Scaling in 2012


Скорее всего доклад был про оптимизацию нагрузок или чём-то ещё. Увы, всё его начало я провёл в туалете :) Упомянуть его я решил только ввиду довольно интересной дискуссии, развернувшейся во время вопросов.

Докладчик упомянул об отсутсnвии какого-либо резервирования и масштабирования на его проекте. Это повлекло сперва довольно неожиданный вопрос: какова бизнес модель вашего сайта? Как оказалось, на проекте докладчика люди платят за доступ к фичам сайта с помощью подписок (на 6, 12, 24 месяца). С учётом того, что факапы, при которых сайт ложится случаются всего пару раз в год, и того, что все пользователи сайта уже оплатили за его использование, - высокая отказоустойчивость есть достаточно дорогая, сложная, а самое главное - не так уж сильно нужная вещь :) Другое дело, если бы монетизация проекта зависела от каждого запроса к проекту! :)


Proactive Web Perfomance Optimization


Предполагалось, что доклад будет читать сотрудник Twitter, поэтому лично я ждал доклад с большим нетерпением, предвкушая что-то интересное. Однако, сразу после начала доклада оказалось, что в Twitter он работает недавно и до этого большую часть времени занимался web-оптимизацией. А что бы окончательно добить толпу, расскажет нам про замечательное средство/утилиту/профайлер/плагин для web-оптимизации - YSlow :(


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


По большому счёту доклад повествует о том, как в Parallels сымплементили свою версию GoogleFS с chunk'ами, серверами метаданных и остальными атрибутами. Отличительной (для меня) чертой является то, ребята предполагают использование пока ещё дорогих, но быстрых SSD-дисков. В Google, вроде бы, политика сводится к покупке дешевого железа, которое не жалко выкинуть и заменить.

Основное предназначение виртуализации - разделение ресурсов одного хоста, эффективный бекап и деплоймент.

Лучшее решение для объединение дисков в массив и их последующего разделения между виртуальными машинами SAN storage. Но это дорого, поэтому все используют обычные диски.

В случае журналируемых ФС данные сначала попадают в журнал, а лишь потом на диск. Это нужно для того что бы при внезапном выключении диска мы имели возможность воспроизвести журнал и добавить недостающие данные на диск.

Из доклада запомнилось упоминание о PAXOS алгоритме. Рассматривается греческий остров PAXOS, на котором есть парламент. В парламенте заседают депутаты, которые по совместительству являются и бизнесменами. В виду последнего они очень часто находятся в отъезде так, что в парламенте всегда находится не более половины парламентариев. Связаться с отсутсnвующими можно только с помощью гонцов. При этом парламент должен всегда работать и принимать законы. Кроме того все парламентарии всегда должны быть в курсе последних законов. На сколько я понял, ребята используют этот алгоритм для синхронизации chunk-серверов.

Отключение электропитания можно эмулировать с помощью посылки SIGSTOP процессу. В этом случае приложение на другом конце TCP соединения будет в той же ситуации, что и при отключении питания. Это быстрее, чем реальное отключение питания.


Сервис рекомендаций на виртуальном Hadoop кластере


Ребята сделали map/reduce задачу "сервис рекомендаций на сайте" с помощью Hadoop. В пример приводятся их частные пhоблемы и решения, так что написать тут, пожалуй, нечего :(


MariaDB: The new MySQL


Обзорный доклад про Maria DB. Форк MySQL полностью переписанный с нуля основателем MySQL, после того, как MySQL перешёл от Sun к Oracle.
В качестве движка по-умолчанию использует XtraDB от Percona. Поддерживает InnoDB.

По сути доклад сводится к Сhangelog'у MariaDB версии 5.5.


Personal story of how MySQL grew and the challenges I've met on the journey


Доклад от Oracle. В основном о том, что будет в новых версиях. Своего рода RoadMap MySQl.

В докладе прозвучал ответ на довольно интересный вопрос: почему Oracle поддерживает MySQL? Компания хочет быть представлена на всех рынках, а MySQL покрывает Web, Mobile и Embedded. Кроме того не хочется терять таких клиентов как Facebook и Twitter. Про огромное comunity можно не упоминать :)

Отдельно хочется отметить, что В MySQL Installer for Windows включена утилита миграции с таких БД как MsSQL, Sybase и т.д. К сожалению, она не умеет за одно переписывать весь сопутствующий код проекта. В виду чего её смысл для меня остаётся потерянным :)


How to choose right index


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

Наибольшую ценность на мой взгляд представляют следующие тезисы:
  • не надо делать слишком много индексов, так как они уменьшают скорость вставки и вообще влекут накладные расходы - делайте индексы только там, где они действительно нужны;
  • выбирайте только те данные, что вам нужны: меньше данных передаётся по сети, меньше данных обрабатывает процессор;
  • сортировка - достаточно дорогая операция;
  • distinct - очень медленная операция, так как работает на результате выборки;
  • index(a,b) better than index(a) only on equals operation;
  • clustering index contains all row data (видимо подразумевалось, что при построении кластерного индекса данные в таблице сортируются согласно индексу);
  • если столбца нет в индексе, но он используется в выборке - придётся делать fetch из таблицы;



Презентации


Все презентации доступны на SlideShare.

Read more...

Sunday, September 30, 2012

Техника быстрого чтения

Прочитав намедни очередную статью с Хабра о деэффективности, проактивности и прочем трэше, внезапно наткнулся на упоминание о технике быстрого чтения - методике, с которой давно хотелось познакомится поближе. Недолгий поиск в гугле показал, что статей по этой теме не так уж и много. Тем не менее, мне удалось найти архиинтереснейшую советскую книгу с оригинальным названием "Техника быстрого чтения". К сожалению, на 95% книга состоит из воды и выдержек протокола заседания XXVI съезда КПСС. Однако, несколько интересных и, возможно, полезных моментов мне всё же удалось найти.


Цель


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

Кроме того, за скорость надо платить. Цена в данном случае - качество понимания текста. Хорошей считается техника скорочтения, при которой усваивается хотя бы 75% материала.


Ошибки


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


Способы чтения


Читать текст можно разными способами: по буквам, по слогам, словами, предложениями или логическими блоками. Способы, как несложно догадаться, расположены в порядке возрастания эффективности. Последний возможен при развитом периферическом зрении, позволяющем мозгу схватывать весь абзац целиком. Подобно тому, как взрослый человек не читает всё слово целиком, а лишь ограничивается несколькими буквами и их позицией, при достижении некоторого уровня дзена можно научится читать текст не словами, а абзацами. Теоретически. Говорят, что Ленин, Маркс и какой-то рабочий с Ульяновского завода могли :)


Вот пример, показывающий неважность порядка букв в слове:
По рзелульаттам илссеовадний одонго анлигйсокго унвиертисета, не иеемт занчнеия, в кокам пряокде рсапожолена бкувы в солве. Галвоне, чотбы преавя и пслоендяя бквуы блыи на мсете. Осатьлыне бкувы мгоут селдовтаь в плоонм бсепордяке, все-рвано ткест чтаитсея без побрелм. Пичрионй эгото ялвятеся то, что мы не чиатем кдаужю бкуву по отдльенотси, а все солво цликеом.


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


Алгоритмы чтения


Что же касается методик: то тут можно выделить два алгоритма техники быстрого чтения: интегральный и дифференциальный.

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

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


Память


Прочитав материал, важно его не забыть. Большая часть материала забывается в первые часы после его прочтения. Поэтому лучшей тренировкой памяти является повторение/пересказ прочитанного вскоре после первого прочтения. Так же полезно выделять в прочитанном смысловые блоки или тезисы. Ну и самым эффективным на мой взгляд инструментом является ассоциативная память.


Используемая литература


1. Кузнецов О. А., Хромов Л.Н. Техника быстрого чтения. М., 1983.

Read more...

Saturday, September 8, 2012

Ошибки при выступлениях и подготовке презентаций

Я не строю иллюзий по части своего ораторского мастерства и прекрасно понимаю, что докладчик из меня средний: есть хуже, есть лучше... Ну и слава богу - есть куда расти и, если что, есть куда падать :) В этой заметке я хочу кратко резюмировать опыт двух моих выступлений (CodeFest 2011, DevDay 09/07/2012), что бы в случае чего не наступить ещё раз на те же грабли.

Начнём с классики - "Смерть через PowerPoint". Шок! Сенсация! - в общем смотреть/читать всем и до конца :)



К первому своему докладу я готовился довольно тщательно и был уверен в его успехе: интересная техническая тема (АОП), не сильно перегруженная презентация с упором на устное повествование и даже подготовка к выступлению перед публикой [*]. В общем ничего не предвещало беды :)

Однако, когда пришло время выступать я жутко перенервничал и выпалил весь доклад буквально за 20 минут, в то время как в спокойной обстановке перед коллегами рассказывал его минут за 40 :) В результате я упустил из рассказа где-то четверть информации. Ту же информацию, что я всё же рассказал, воспринять было довольно сложно, ибо говорил я быстрее, чем бабушки, которые продают "маааааароженноеэскимовшоколаде" в пригородных электричках :)

"Не беда" - подумал я. Всё же - первый раз, в следующий раз точно всё получится. И начал готовить коварный план мести. Много смотрел, как выступают другие, и с каждой увиденным докладом всё больше и больше убеждался в том, что слайды в презентации должны быть как можно проще, понятнее и веселее. Они должны развлекать слушателя (изредка иллюстрировать что-то), тем временем как суть презентации будет доносится словами докладчика.

Именно в этой концепции я и решил построить свою следующую презентацию: максимум смешных картинок и никакого текста на слайдах - всё будет рассказано устно!

Делалась в этот раз презентация дольше: искать весёлые картинки в гугле и обрабатывать их потом в gimp'e оказалось не так занимательно, как я предполагал :) Но чёрт с ним: презентация готова, рассказана нескольким группам людей, получен фидбек, внесены правки. Всё, в бой!

А нет! :) Мандраж никуда не девается. Да, он намного меньше, чем в первый раз, но он есть. Но самое интересное обнаруживается во время доклада:

1. Самая большая ошибка, которую я совершил в этот раз - это рассказ, который не опирается на слайды. В моём случае слайды являлись лишь иллюстрациями, которые могли появится по середине предложения. Я не мог опираться на слайды. Пока я рассказывал доклад в своей зоне комфорта (знакомым, коллегам), это не имело значения. Но как только мандраж немного выбил меня из седла... я бесконечно убедился в том, что рассказ должен опираться на слайды, а не наоборот!

2. Дальше ещё веселее. Видимо лавры Пушкина не дают мне покоя. В текст я вставил немало художественных оборотов и в целом выстроил его и его предложения так, что потеряв какую-то часть, довольно сложно восстановить мысль. Текст доклада должен быть простым, а каждая важная мысль должна опираться на отдельный слайд.

3. Ну и последнее. Нельзя, нельзя полагаться на распечатки текстов. Их не должно быть у вас с собой! Они и не нужны, если выполнены два предыдущих пункта! Если у вас случится ступор по середине доклада (что, естественно, со мной и произошло) вы не сможете сколь-либо оперативно найти в своих распечатках нужное место. Слайды - ваши подсказки и распечатки!


Read more...

Особенности разработки enterprise-приложений

Буквально вчера я выступал с докладом на замечательном мероприятии DevDay, проводимым ребятами из 2GIS. Доклад был обзорным и посвящался разработке корпоративного ПО. Под катом прилагаю слайды и текст доклада.
Добрый день! Меня зовут Крестьянинов Михаил. Работаю я в компании XXX, где занимаюсь системой биллинга и внутренней автоматизацией.



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



Кому-нибудь эта картинка что-нибудь напоминает? :) Нет? А я вот каждый день вижу :).

И так, все мы знаем (ну или по крайней мере догадываемся), что представляют собой такие направления разработки как webdev, gamedev... популярный в последнее время mobiledev. Однако, далеко не всем известно, что же представляет собой разработка enterprise (или в переводе на великий и могучий — корпоративных) приложений?

Как видно с этой картинки, занятие это довольно увлекательное, насыщенное разными технологиями, проблемами и их решениями :)

Но что бы ответить на этот вопрос серьёзно, давайте представим себе, что у нас есть некая относительно крупная компания... например, XXX. Жизнь в этой компании бурлит, цветёт и пахнет: подключаются абоненты, оплачиваются услуги, предоставляется интернет, списывается абонентская плата... ну и всё по новой :) Однако, если бы всё это делалось вручную, с помощью специально обученных бабушек или иной биоробототехники, к успеху бы компания шла очень долго и скорее всего никогда бы не дошла.

Что бы автоматизировать все эти бизнес процессы (и списывать ещё больше денег) как раз и используются приложения, именуемые корпоративными: биллинг, система учёта клиентов и т. д. Иначе говоря, корпоративные приложения — это ПО, призванное решать задачи автоматизации бизнес процессов компании.




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



В качестве примера возьмём процесс подключения абонента в НТК. Первым делом счастливый абонент (появляется абонент) звонит по телефону (или иным образом) сообщает оператору (появляется оператор), что хочет подключится. Его контактные данные сохраняются в CRM (появляется CRM) и на их основе создаётся заявка в Issue Tracker (появляется Jira). Заявка в трекере проходит некоторые бюрократические и технические этапы — например установку оборудования монтажником (появляется монтажник). После этого абонент заводится в биллинге (появляется АСР) и конфигурируется на оборудовании (появляется оборудование).

Как вы видите, только в одном, довольно обобщённом, сценарии подключения абонента задействовано четыре системы. Четыре приложения которые нужно разработать/купить и сынтегрировать вместе.

На первый взгляд, процесс довольно прост, и не совсем понятно, так ли здесь нужно что-то автоматизировать. Однако, если посмотреть на него более детально...




Думаю, ответ становится очевиден :)



И так, мы ответили на вопрос – Зачем нам корпоративные приложения? Перейдём к вопросу – Откуда берутся корпоративные приложения?



Современный рынок корпоративного ПО предлагает огромнейшее количество решений для автоматизации практически любых задач. Тем не менее практически в каждой более менее крупной компании есть свой отдел, занимающийся разработкой корпоративного ПО.

Почему? Ответов тут два.




Во первых — это стоимость. Приложения из Oracle E-Business Suite стоят в среднем от 5 до 20 килобаксов, плюс поддержка где-то ешё на тысячу /полторы. С учётом того, что большая часть его функциональности вам не пригодится, покупка его может быть оправдана только в случае компаний неимоверных масштабов.

Конечно же есть и более пролетарские решения. В качестве примера можно взять продукты компании Naumen из ЕКБ. Однако, в данном случае мы наступаем на другую сторону медали — …




… кастомизируемость, адаптируемость продукта под нужды компании.

В случае с НТК система биллинга дорабатывается под нужды маркетинга практически непрерывно: каждую неделю внедряется какая-нибудь новая фича, порожденная богатым воображением наших внутренних заказчиков.

Понятно, что ни одна сторонняя система не сможет обеспечить абсолютной гибкости настроек, а держать основное ПО компании на аутсорсе мягко говоря рискованно.




И так, мы решили писать своё enterprise-приложение. Какой подход выбрать? Вариантов тут на мой взгляд три.
Первый подход я назвал «Банковским», потому что его реализацию можно встретить практически в любом банке. В основе него лежит святая святых — БД Oracle за несколько сотен килобаксов. Большая часть логики при этом реализована в виде хранимых процедур на PL/SQL. Говорить о недостатках этого подхода смысла нет, так как споры об эффективности процедурной разработки в свете наличия ООП вроде бы давно утихли и остались в прошлом. Понятно, что это наследие прошлого, которое необходимо поддерживать и развивать. Которое приносит деньги.



Далее идут сервера приложений. Довольно интересный подход, который тем не менее редко можно встретить на рынке НСК. Суть его заключается в использовании специального ПО — сервера приложений (типа Jboss, WebSphere), который берёт на себя все аспекты работы с БД, контроля транзакций, авторизации, кластеризации. Разработчику при это остаётся только самое главное — описывать бизнес-логику.

Причина непопулярности данного подхода у нас скорее всего кроется в их цене (до $5К) и относительно невысокой производительности (обусловленной не всегда востребованными накладными расходами). Поэтому зачастую их можно встретить только в крупных компаниях, которые покупали брендовые сервера «под ключ»: с заранее установленной брендовой ОС и сервером приложений. Например, IBM System I c AIX и WebSphere на борту. В качестве более-менее удачного примера использования можно рассмотреть АльфаКлик от АльфаБанка (судя по их вакансиям работает на WebSphere под AS/400).

Ну а что же делать, если не хочется писать хранимые процедуры и нет веры в EE-сервера? Правильно, писать своё — с нуля. На самом деле — шучу. Почти с нуля.




Для разработки корпоративных приложений прекрасно подходят языки со строгой типизацией и мощным фреймворком/комьюнити. Примерами таких языков являются Java с замечательным Spring FrameWork и C# с не менее замечательным .NET. У нас в НТК мы используем как раз Java + Spring, чему очень рады.



Но бог с ней, с теорией — давайте перейдём к практике и попробуем спроектировать своё enterprise-приложение. С блэкджеком и прочими фичами. Как следует из заголовка доклада - это будет биллинг. Заодно я покажу, как он устроен у нас в НТК.

Первым делом давайте определимся с тем, что же должен уметь биллинг. Как минимум хранить информацию об абонентах и предоставляемых им услугам (появляется сервис Абоненты/Услуги).Что бы предоставлять услуги, например, доступ в интернет, придётся научиться конфигурировать оборудование (появляется сервис Оборудование). Раз у нас появились абоненты, которым мы предоставляем услуги, — пора начинать списывать с них деньги! (появляется сервис Тарификация). Что бы абоненты могли пополнять свой баланс и приносить компании ещё больше денег, дадим им возможность пополнять баланс (появляется сервис Приём Платежей). Так же мы должны уметь оповещать абонентов (появляется сервис Нотификации). И предоставить web-интерфейсы для абонентов, операторов и администраторов (появляется сервисы Интерфейсов).

И так мы декомпозировали наш биллниг на несколько относительно независимых служб, реализующих свой модуль бизнес логики. Каждая из них достаточно самостоятельна, что бы быть представлена отдельным приложением с 2х/3х-звенной архитектурой и, потенциально, со своей БД (появляются базы данных).

Такой подход называется сервисно-ориентированным или SOA. Его преимущества достаточно очевидны: кластеризация бизнес-логики, упрощение доработок и рефакторинга, потенциальное масштабирование, и главная ценность для больших систем — порядок!




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

Связать службы можно несколькими способами:
1. Напрямую (появляются прямые связи). Самый простой и самый эффективный способ. По крайней мере при небольшом количестве служб. Спектр возможных протоколов тут крайне широк, но зачастую речь идёт об REST или SOAP. В нашем случае используется крайне специфичный бинарный протокол Hessian, но его наличие обусловлено чисто историческими причинами :)




2. Второй способ - Очереди Сообщений (появляется схема с MQ). Тут существует несколько возможных протоколов: Java Message Service, Advanced Message Queuing Protocol, ну и конечно же Microsoft Message Queuing – лозунг “Not invent here” никто не отменял :) У каждого протокола есть свои реализации (наиболее популярные приведены на слайде), но суть у них одна - асинхронный обмен сообщениями без явного необходимости указания адресата и адресанта.

Например, в нашем биллинге такая схема (на основе ActiveMQ) используется для отработки события подключения абонента. Как только служба работы с оборудованием зафиксирует факт подключения абонента — она отправит сообщение об этом в соответствующий топик. Все другие службы и системы, которые хотят быть в курсе этого события (Учёт Абонентов, Нотификация, JIRA) получат это сообщение и сделают соответствующие выводы. Относительно предыдущего способа у данного есть 3 явных преимущества:
- всегда можно подписать или отписать ещё одну службу на некоторое событие,
- время работы вызывающей службы не зависит от времени работы вызываемых служб,
- работа системы в целом не зависит от доступности вызываемых служб, в виду гарантии доставки сообщения.




3. И последний способ — через сервисную шину предприятия, Enterprise Service Bus (появляется схема с ESB). ESB, как и вариации Message Queuing является стандартом, но уже не обмена сообщениями, а интеграции корпоративных систем. Что бы понять его предназначение, давайте представим себе компанию в которой одна служба имеет интерфейс SOAP, другая — SMTP, а третья — вообще работает только по собственному XML протоколу поверх TCP. Что бы свести всё это к единой схеме, единой шине нам как раз и пригодится ESB приложение (например, eMule), на основе которого мы напишем коннекторы (появляется JIRA и 1С с коннекторами) ко всем службам по всем нужным протоколам, не изменяя при этом ни строчки кода этих служб.

Какой же способ выбрать? Всё зависит от ваших задач. Мы в своей работе используем все три способа. Прямые связи, так как это дёшево и эффективно (тут правда стоит отметить, что большинство наших служб и сервисов самописаны и поддерживают единый протокол Hessian). JMS — в тех случаях, когда бизнес процесс явно подразумевает асинхронную модель поведения. ESB — в качестве моста между Hessian-службами и чужеродными нам Jira/1C.




Вот мы, пожалуй и добрались до самого главного — БД. Данные — это пожалуй одна из самых главных ценностей любой IT компании, а способ из хранения — ценнейшая тайна :) На самом деле нет :)

Но давайте к сути. Какую БД выбрать для вашего приложения?




Обычно всё уже давно выбрано за нас, причём давно :) Однако, если попытаться ответить на этот вопрос теоритически...

Понятно, что модный пару лет назад NoSQL стоит оставить Хипстерам. Ограничения целостности и строгая структурированность данных — крайне важные вещи, при работе с серьёзными данными…




… Что же касается реляционных БД... то тут почти у каждой есть своя Success Story в крупных проектах: MySQL — YouTube, Postgres — Skype, Sybase — SUP, MsSQL — все партнёры Microsoft, Oracle — так вообще корпоративный стандарт.

В общем холиварить тут можно долго. Точно можно сказать, что количество success story и размер comunity у Oracle просто огромны. Однако, он стоит денег — 47 килобаксов за процессор (и это без поддержки!). Что, согласитесь, не мало.

Из бесплатных БД лично нам наиболее импонирует Postgres...




Мы умеем с находить с ним общий язык. Он хорошо зарекомендовал себя в плане работой под нагрузкой в проекте CN.ru. Он умеет партицирование и репликацию, которые так же успешно опробованы как у нас, так и в других российских компаниях, в том же Яндексе. В общем – мы любим и верим в Postgres.

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




Однако, как я уже говорил выбирать зачастую не приходится — скорее всего всё уже выбрано за вас! :) Помните, пару слайдов назад я показывал вам, как выглядит структура сервисов нашего биллинга? Так вот - я соврал :) Мы хотим, что бы она так выглядела :)

На самом деле все выглядит так (Спецэффект).

В нашем случае в качестве основной БД мы имеем купленный много лет назад вместе в первым биллингом Sybase.




Недавно у него было день рождение. Ему исполнилось 12 лет. Я в его возрасте в первый раз попробовал пиво :) Нет, это очень хорошая СУБД... для своего времени :) Количество параметров конфигурации и объёмы документации превышают пожалуй размеры любой современной open source БД. Там даже есть партицирование БД (правда только по первичному ключу).

Но! В нём нём крайне скудны возможности SQL (минимум агрегатных функций, ни какой рекурсии или оконных функций), работы с триггерами и т. д. Но это не основная проблема — всегда можно найти какой-то workaround. Основная беда кроется в том, что архитектура БД устарела — нельзя заставить СУБД 12 летней давности эффективно использовать ресурсы современных серверов.

Так как в качестве решения проблемы Sybase предлагает купить последнюю версию их БД по цене не сильно отличающейся от стоимости Oracle, мы решили медленно но верно переезжать на Postgres.

Кстати о переезде. Более менее безболезненный переезд стал возможен как раз благодаря сервисно-ориентированной архитектуре биллинга. Поскольку логика работы с каким-то определённым аспектом инкапсулирована в одной службе, нам относительно безболезненно удалось взять часть таблиц, относящихся к финансам и тарификации и унести их из Sybase в Postgres — к производительности и партицированию, так что остальные службы даже ничего не заметили :)




И так, мы определились с архитектурой и БД. Давайте теперь подумаем, как же тестировать наше приложение?



Когда приложение состоит из одного модуля — всё просто: установили, протестировали. Но что делать, если приложение, сервис зависит от других сервисов? Ответ прост, как и всё гениальное — для каждого тестировщика создавать собственное окружение с блекджеком и полным набором сервисов.

Тоже самое будет касаться и различных БД для сервисов. Правда в нашем случае есть БД, чей объём превышает 100ГБ, что делает её актуализацию несколько затратной. В данном случае можно идти по пути обновления не всей базы, а отдельных таблиц или даже дельт этих таблиц.




Отдельно хотел бы упомянуть модульные тесты... :) Мы все знаем, что TDD - это круто... но давайте смотреть правде в глаза :) Кто из вас положа руку на грудь, скажет что ведёт разработку полностью в рамках этой религии? Писать моки для БД и множества соседних служб, конечно очень увлекательно, но имхо крайне неэффективно. Тем более, если учесть существование тестов интеграционных. В нашей разработке модульные тесты используются только для математики/алгоритмов и некоторых утилит. Всю остальную логику в случае сервисно-ориентированной архитектуры лучше возложить на интеграционные тесты – тут вам и проверка логики и работы с БД, плюс полная имитация всех внешних взаимодействий по всем протоколам, плюс проверка интерфейсов с помощью Selenium.



Для того, что бы автоматизировать процесс тестирования до конца удобно использовать системы непрерывной интеграции, например Hudson. Однако его настройка, это тема для отдельного доклада. Скажу только, что самое сложное при работе с ним — это не забить на него и его репорты. Это требует действительно большой ответственности и силы воли :)



Фух! Потихоньку подбираемся к концу :)



Вкратце затрону процесс выкладки служб на боевые сервера.

Если бы у нас был сервер приложений — то вопрос выкладки и хостинга сервисов отпал бы автоматически. Но у нас OpenSource и Spring :)

Поэтому каждую нашу службу мы оформляем виде самостоятельного приложения и пакуем в deb-пакет. Тем самым используя виртуалки с Linux'ом в качестве контейнеров для служб нашего биллинга. Подход немного нестандартен, но при наличии некоторых утилит для мониторинга весьма эффективен.




Я думаю, это печальная тема для многих из нас :) Как я уже говорил выше главная проблема в нашем случае это моральна устаревшая БД. Ну и чего уж греха таить, порой не всегда оптимальный код. Но что в обоих случаях мы идём к успеху: в первом случае к Postgres’у, во втором — к просветлению :)

Если говорить о цифрах, то это примерно 150К абонентов, >300К финансовых проводок в сутки и 150ГБ данных.

Кстати про данные. Мало кто знает, но одной из причин появление в 2008 году безлимитных тарифов на интернет в НСК стал тот факт, что с ростом числа абонентов обрабатывать и хранить данные по потреблению трафика стало довольно неоправданно напряжно :)




Проблемы есть у всех. В случае enterprice-разработки они мало чем отличаются от общих по отрасли :)

Самая главная проблема на мой взгляд — это внутренний заказчик. С одной стороны это хорошо: всегда можно в полной мере обсудить задачу и уточнить неясные моменты. С другой — это ад, потому что требования будут меняться каждый день, если не час: ведь продумать всё сразу необязательно — всегда можно подойти и сказать: «я тут подумал...» :)

В любой компании есть быдлокод оставшейся с времён, когда компания только начинала развиваться и думать о качестве кода не приходилось. История НТК, например, начиналась с купленного биллинга средней руки на JSP и хранимых процедурах БД и bash скриптах. Сейчас от того биллинга уже ничего не осталось :)

В мире корпоративной разработки есть очень много интересных технологий. Однако, далеко не все нужно использовать. А хочется, ибо круто :) Такую болезнь иногда называют Resume Driven Development. В своей компании видеть такого мне не приходилось, но вот в других порой встречается :)




Ну и конце своего доклада хотелось бы ответить на вопрос, который наверное интересует всех — как сделать так, что бы всё работало и никогда не ломалось? Да никак! Чудеса бывают только в сказках и платных мастер-классах.

Помните пару месяцев назад свалился процессинг одного крупного российского банкак? Даже один крупный российский банк с его многомиллионными бюджетами, почти полной редакцией Oracle 11g, наикрутешим аккаунтом в саппорте Oracle словил вполне тривиальную ошибку. Не срабатывает процесс создания резервной копии (check point) БД, переполняется лог транзакций, встаёт запись в базу. Точка.

Полностью защититься от беды нельзя, но можно значительно снизить риски. И рецепты тут давно известны — мониторинг с помощью того же Zabbix/Monit и резервирование!
На этом у меня всё. Вопросы?

Read more...

Tuesday, July 24, 2012

Потоковое видео в Android

В этой заметке я хочу рассказать о некоторых подводных камнях, с которыми можно столкнуться при работе с потоковым видео в Android приложениях. Конкретно, речь пойдёт о конвертации видео и протоколах доставки/воспроизведения видео. Сразу оговорюсь, что экспертом я в данной области не являюсь, а лишь хочу поделится недавно полученным опытом.


Представим, что перед вами стоит задача реализовать Android приложение, способное проигрывать множество файлов, заливаемых пользователями на ваш сервер. Написать свой youtube, с блекджеком и кодеками. Для этого вам придётся решить как минимум две задачи: конвертации видео к поддерживаемому на Android формате, воспроизведение видео с удалённого источника. Рассмотрим обе эти задачи более подробней.

Конвертация видео

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

Наиболее распространённым сейчас (на мой взгляд) способом хранения видео является контейнер MP4 с запокавкой кодеком H.264 AVC. Их мы, собственно, и рассмотрим.

Первым делом обратите внимание, что Android поддерживает не все возможности кодека H.264, а только определённый набор - профиль, именуемый Baseline Profile(BP). Так, например, в BP не входят такие полезные фичи H.264 как CABAC или B-Frames.

Для нас это значит, что если мы будем использовать эти фичи при кодировании видео, то Android проигрывать это видео будет не обязан. Хотя и может, если ваш телефон достаточно мощный и вендор позаботился об установке и поддержке дополнительных кодеков. Так, например, видео в Main Profile без проблем проигрывается на Samsung Galaxy SII. На телефонах же обычного класса (например, Samsung Galaxy Ace) мы получим сообщение о невозможности воспроизведения видео и ошибку с кодом неверного кодека в logcat'е.

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

ffmpeg -i in.3gp -f mp4 -vcodec libx264 -vprofile baseline -b:v 1500K -acodec libfaac -b:a 128k -ar 44100 -ac 2 -y out.mp4
Рассмотрим подробнее каждый из параметров:
  • -i src входной (перекодируемый) файл;
  • -f mp4 используемый видеоконтейнер;
  • -vcodec libx264 используемый видеокодек;
  • -vprofile baseline используемый профиль;
  • -b:v 1500K bitrate;
  • -acodec libfaac используемый аудиокодек;
  • -b:a 128k аудио bitrate;
  • -ar 44100 частота звука;
  • -ac 2 количество аудиопотоков;
  • -y флаг перезаписи выходного файла;
Так же стоит отметить, что можно обойтись и без указания профиля, а явно включить/отключить нужные опции кодека H.264 через параметр -x264opts, так что бы они удовлетворяли условиям BP. Но это же занятие для любителей.



Раздача видео

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

Как же быть? Платформа Android предлагает нам нативную поддержку следующих технологий/протоколов:

  • HTTP/HTTPS progressive streaming;
  • HTTP/HTTPS live streaming;
  • RTSP (RTP, SDP);
Рассмотрим их по порядку.



Progressive streaming

Наиболее простой способ раздачи видео с помощью обычного web-сервера, сводящийся по сути к скачиванию заранее подготовленного файла по HTTP(S) протоколу. Вся соль в данном случае заключается в том, что воспроизведение файла начинается не по окончанию загрузки, а как только будет скачано достаточно данных (наполнен некоторый буфер).

Тут стоит уточнить, что при использовании контейнера MP4, необходимо сформировать файл так, что бы метаданные о видео потоке (moov atoms) располагались в начале файла (после атома ftyp), перед видеоданными (mdat atoms). Сделать это можно с помощью обработки файла утилитой qt-faststart:

qt-faststart output.mp4 result.mp4
Основной проблемой progressive streaming'а является невозможность перемотки видео к нескачанному моменту, наличие достаточного количества свободного места на устройстве и необходимость поддержки большого числа "толстых" клиентов, скачивающих видео, на web-сервере.

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



Pseudo streaming

Данная технология является логическим расширением progressive streaming'a и позволяет решить одну из его главных проблем - перемотки к ещё не скачанному фрагменту. Применима для контейнеров MP4/FLV с кодеком H.264/AAC.

Единственным отличием от progressive streaming'a в данным случае является, тот факт, что вам потребуется специальный web-сервер, который с учётом временной метки в GET-запросе будет отдавать нужный вам фрагмент видео файла. Примером такого web-сервера естественно может служить православный NGINX с его ngx_http_mp4_module.

Мне не удалось найти какой-либо официальной информации относительно поддержки данного стандарта в Android. Однако, эмперическим путём было установлено, что она присутствует как минимум на устройствах HTC Desire и Samsung Galaxy SII. Однако, хочу обратить внимание, что да же в случае отсутствия нативной поддержки на вашем устройстве всегда можно воспользоваться сторонними плеерами типа MX Player, которые самостоятельно реализуют логику скачки и воспроизведения фрагментов видео с нужной временной меткой, что позволяет организовать перемотку.



Live streaming

Довольно нестандартный протокол передачи данных от компании Apple. Суть его сводится к тому, что раздаваемый файл "пилится" на множество небольших частей, объединяемых спецтальным файлом-playlist'ом формата M3U8. Передача данных происходит по протоколу HTTP(S).

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

Однако, появляются и проблемы. Для "распила" файла и создания playlist'а потребуется ресурсы процессора, время и место на сервере. Для вещания файла в сеть, как и в предыдущих примерах, потребуется HTTP сервер (без каких-либо дополнительных модулей). "Распилить" видео файл можно использовать VLC:

vlc -I dummy /path/to/pornofilm.mpg vlc://quit --sout '#transcode{width=320,height=240,fps=25,vcodec=h264,vb=256,venc=x264{aud,profile=baseline,level=30,keyint=30,ref=1},acodec=mp3,ab=96}:std{access=livehttp{seglen=10,delsegs=false,numsegs=0,index=/path/to/web/server/root/pornofilm.m3u8,index-url=http://localhost/pornofilm/stream-########.ts},mux=ts{use-key-frames},dst=/path/to/web/server/root/pornofilm/stream-########.ts}'
Воспроизвести такой файл можно по URL http://localhost/pornofilm.m3u8.

Поддержка HTTP Live Streaming на нативном уровне в Android присутствует начиная с версии 3.0. С помощью сторонних плееров (DicePlayer, MX Player), судя по wiki, можно добиться поддержки с версии 2.2.



Real Time Streaming Protocol (RTSP)

Протокол прикладного уровня с поддержкой состояния, разработанный специально для передачи видео. Формат команд очень напоминает HTTP. Сами же команды напоминают кнопки на обычном кассетном магнитофоне: PLAY, PAUSE, RECORD и т.д.

В отличие от HTTP Live Streaming RTSP не требует разбиения фалов на мелкие части и составления playlist'ов. Нужные части файла будут генерироваться и отдаваться клиенту налету. В качестве RTSP сервера можно использовать VLC.

Стоит заметить, что сам протокол RTSP не определяет способ передачи данных, а делегирует это другим протоколам. Например, RTP. Для вещания файла по протоколу RTP нужно будет запустить VLC со следующими параметрами:

vlc -vvv /path/to/pornofilm.mp4 --sout '#rtp{dst=localhost,port=1234,sdp=rtsp://localhost:8080/pornofilm.sdp}'
Однако, поднимать для каждого файла свой процесс с отдельным портом вне зависимости от наличия пользователей, желающих его просмотреть, было бы глупо.

Поэтому вернёмся к протоколу RTSP и воспроизведению видео по требованию (Vidoe On Demand). Для того, что бы использовать VLC в качестве RTSP сервера для проигрывания VOD необходимо прежде всего запустить VLC, указав атрибуты RTSP сервера и Telnet интерфейса:
vlc -vvv -I telnet --telnet-password 123 --rtsp-host 127.0.0.1 --rtsp-port 5554
После этого как сервер запущен, необходимо произвести его настройку. Делать это удобнее всего с помощью telnet'a, так как такой подход даёт возможность настройки налету:
new porno vod enabled
setup porno input /path/to/pornofilm.mpg
Для воспроизведения видео (в том числе и на платформе Android) необходимо запросить его по URL rtsp://localhost:5554/pornofilm.

Из недостатков можно отметить тот факт, что HTTP открыт зачастую на всех firewall'ах и проксях... с RTSP в случае политики Deny,Allow всё иначе.
Кроме того, при использовании RTSP-сервера для добавления/удаления файлов на сервере придётся обновлять его конфигурацию (список vod'ов). Да, для этого есть telnet, но это всё равно сложнее, чем просто заливать или удалять файлы из каталогов web-сервера.

Воспроизведение с помощью данной технологии поддерживается платформой Android нативно. Например, с помощью всё того же стандартного класса MediaPlayer.



Multicast

Многие считают, что multicast не работает в Android. Это не совсем так.

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

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

Однако, как показывает практика, проигрывать multicast видео на Android всё можно. В моём случае с этой задачей удачно справился недавно вышедший VLC Beta для Android.

Кроме того с помощью VLC-сервера всегда можно свести воспроизведение multicast'a к HLS:

vlc -I dummy udp://@192.168.20.1:1234 vlc://quit --sout '#transcode{width=320,height=240,fps=25,vcodec=h264,vb=256,venc=x264{aud,profile=baseline,level=30,keyint=30,ref=1},acodec=mp3,ab=96}:std{access=livehttp{seglen=10,delsegs=false,numsegs=0,index=/path/to/web/server/root/multicast-porno.m3u8,index-url=http://localhost/multicast-porno/stream-########.ts},mux=ts{use-key-frames},dst=/path/to/web/server/root/multicast-porno/stream-########.ts}'
или RTSP:
new multicast-porno vod enabled
setup multicast-porno input udp://@192.168.20.1:1234


Попытать удачу с проигрыванием multicast'a на вашем устройстве вы можете, передав плееру URL вида udp://@192.168.20.1:1234.



Что выбрать

Если с форматом видео всё ясно (H.264 BP / MP4), то со спобом дистрибуции вопрос открыт. У каждого их них есть свои достоинства и недостатки.

Первым делом из рассмотрения я бы убрал обычный progressive streaming. Да он работает всегда и везде, но отсутствие перемотки и загрузка всего файла целиком - это уже слишком.

Следующим кандидатом на вылет является live streaming. Главным его недостатком является нативная поддержка в Android начиная с версии 3.0. А игнорирование более 80% пользователей c версией 2.x - не вариант. Хотя тут можно посмотреть на сторонний плеер, или заняться собственной реализацией (свободных наработок для поддержки HLS я, увы, не нашёл).

И последним я бы вычеркнул RTSP. Да, это протокол, разработанный специально для видео. Да, его использование идейно верно. Но есть два момента. Во первых - необходимо постоянно обновлять конфигурацию сервера. Во вторых, HTTP открыт всегда и везде, чего нельзя сказать о RTSP/RTP.

Лично я бы остановился на pseudo streaming. Он позволяет осуществлять перемотку и при этом не скачивать весь файл полностью. От нас требуется только немного донастроить web-сервер.


Read more...

Sunday, April 1, 2012

Codefest 2012

И так, это свершилось: на этих выходных проходит замечательнейшая ИТ-конференция от компании 2GIS – Codefest! На этот раз организаторы решили поднять планку и провести ещё более, как они сами говорят, улётную конференцию! Но, обо всём по порядку.




Здоровенный язЪ!


Конференция проходит в недавно открывшемся ЭкспоЦентре. Друзья, ЭкспоЦентр здоровенный. Очень :–)

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

Отдельно хочу отметить организцию трансфера. Автобусы реально доставили. 4 раза. Я в экстазе :–)


Profit!!!


Самым полезным для меня оказался докладчик из Мегафона. Удалось узнать, что Мегафон внедряет новые фичи 3 раза в год (при этом багфиксы внедряются регулярно). Структурно представляет собой группу региональных компаний с разным биллингом и web–интерфейсом, объединённых под одним брендом. Разработка биллинга ведётся внешней компанией с довольно внушительным штатом сотрудников.

Так же было интересно послушать про интранет Яндекса. Крупной компании без интранета - никак. Джентельменским набором для компании в 500 – 5000 человек будет issue tracker Jira и самая обычная WIKI. Для организации поиска по интранету хороших решений нет, но можно попробовать интегрировать поисковый сервер Яндекса. И конечно же почта – слишком много на неё возложено, нужно искать альтернативы для отдельных вариантов её использования.

Далее был доклад про карты Янднкса. Хранятся карты частями (тайлами) в древовидной структуре, в качестве хранилища может выступать как ФС, так и БД. Загрузкой занимается JS менеджер. Для обмена данными используется JSON.

Следующим пунктом были пробоки от 2GIS. Данные о пробках берутся от спец. компаний, загимающихся мониторингом трафика, и телефонов с установленным 2GIS. Первичные данные помещаются в MongoDB (большой объём данных, быстрая вставка), отфильтрованные и обработанные данные сохраняются в Postgres (с использованием расширения PostGIS), отдача сформированных для клиента данных из Redis и Nginx (скорость).

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

Кроме того запомнился доклад про CAP теорему и шардинг MongoDB для отправки 3М sms в сутки. Либо я не правильно понял цели докладчика, либо был свидетелем Resume Driven Development. Так как стоящую перед парнем задачу можно было выполнить в разы проще. А простота (обоснованная), на мой взгляд, главный залог надёжности.

Ну и под конец дня Битрикс потроллил Windows Azure – очень много подводных камней и недоработок.

На второй день больше всего запомнилось выступление Орлова и Панкратова - очень интересно, простым языком о простых вещах. Пересказывать смысла нет - это надо слушать! :)

Выступление товарища из ScrumTrek очень напомнило мессу пастыря в баптистской церкви :) Жаль, что ни на одного из слушателей не снизошла благодать... разве что в виде карт для planning pocker'a :) А если серьёзно, то на мой взгляд agile/lean/devops в нашей стране - это способ заработка одних менеджеров на других менеджерах. Эти методологии, безусловно, содержат очень правильные мысли, которые нужно обдуманно брать и применять... но почему-то в российских компаниях попытки их применения зачастую напоминают Культ Карго.

Последний доклад, который я посетил, был от института Марс и повествовал о теории поколений в целом и поколении Y в частности. В конце доклада в ответ на мой вопрос "как быть с тем, что большинство представителей моего поколения считает, что если к 30 годам ты не стал директором или, на худой конец, менеджером, то жизнь не удалась", мне был дан очень интересный ответ - "нужно сделать так, что бы ЗП обычного специалиста и управленца были соизмеримы". Нет, на свою жизнь я в общем не жалуюсь... но вборс для IT отрасли имхо вышел годный :)


Кровь, говно и PHP


Порадовали треш–доклады для разрядки мозга от автора Sphinx Андрея Аксёнова. Благодаря нему участники конференции узнали, как пахнут кровь, говно и PHP. А так же, что такое релевантеость поиска в контексте субъективности восприятия, машинное обучение под контролем индусов и линейную регрессию от первого web–программиста Гаусса :)


Размер имеет значение


Этот Codefest собрал примерно 1300 человек. Как мне удалось нагуглить, осенью 2011 года на HL++ было 600 мест, на РИТе 2012 ожидается 1500 человек. Так что, если я не ошибся в цифрах, Сodefest в праве считать себя одной из крупнейших конференций на постсоветском пространстве.

Кстати, каким то чудом в 2010 году мне удалось побывать на HL++. Воспользуюсь случаем и проведу небольшое сравнение. ЭкспоЦентр в НСК намного удачней подходит для конференций, чем ИнфоПространство в МСК. Организация обоих конференций на одинаково хорошем уровне. Доклады на HL++ мне понравились больше: интересная для меня специфика и очень профессиональные и/или иностранные докладчики. На Codefest, конечно же, тоже было много интересных докладов, и я верю, что на следующей конференции их будет ещё больше!


The cake is a lie


В конце первого дня ребята из 2GIS угостили всех няшненьким тортом

вишенкой которого стал уже вошедший в традицию (к сожалению, очень короткий) виски–пати



Read more...

Tuesday, January 31, 2012

Oracle (Sun) Certified Java Programmer

Последние два месяца моей жизни ушли на подготовку и сдачу некогда Sun'овского, а ныне Oracle'ового экзамена по Java, более известного как "SCJP Exam". Экзамен сдан и хочется поделиться некоторыми впечатлениями о нём :)

Прежде всего - что это за экзамен и зачем он нужен? Экзамен показывает степень владения экзаменуемым технологии Java SE. Примечательно, что в качестве экзаменатора выступает компания-владелец технологии, т.е. Oracle. Нужен экзамен в первую очередь для того, что бы смотивировать себя на доскональное изучение всех тонкостей Java SE (ведь экзамен стоит денег, потерять которые не хочется). Ну а во вторых, да - успешная сдача экзамена значительно увеличивает МПХ ЧСВ экзаменуемого :)

Для подготовки к экзамену у Oracle, конечно же, есть специальные курсы, где за пару тысяч евро вас обучат всему, что надо :) Однако, я бы рекомендовал замечательную книгу SCJP Sun Certified Programmer for Java 6 Exam, которая в случае досконального изучения позволит вам успешно сдать экзамен.

Экзамен состоит из 60 вопросов на 150 минут по различным темам от объявления переменных до многопоточности. Для сдачи экзамена необходимо ответить на 61% вопросов. На момент сдачи мою экзамена на сайте Oracle он стоил $300, однако в центре тестирования с меня взяли всего $175 - видимо, цена зависит от места сдачи.

Сдавал экзамен я в Новосибирске, в СибИнфоЦентре. Процесс оказался очень забавным :) Мне пришлось оставить все свои вещи в одной комнате, после чего меня отвели в специальную коморку, оборудованную видеокамерой, где закрыли на 2,5 часа. Кроме видеокамеры в коморке были только стол, компьютер и подносом с чаем/печеньками. На компьютере было запущено спец. ПО для сдачи экзамена, полностью блокирующее доступ к ОС (Windows XP) и остальным программам. Листками бумаги пользоваться было нельзя - только специальные ламинированные черновики и маркеры (видимо что бы не унесли с собой вопросы и не выложили их в интернетах). На экзамене по ZCE, который я сдавал пару лет назад, ко всему вышеописанному прилагался англо-русский словарик - но видимо с тех пор что-то изменилось, и в этот раз я его не обнаружил.

И самое печальное - перед начало экзамена приходится прочесть целое лицензионное сочинение, о том, что вопросы с экзамена под страхом смертной казни буржуйского законодательства нельзя каким-либо образом публиковать :( Тем не менее, могу порекомендовать всем, кто интересуется Java, прочитать указанную мной выше книгу по подготовке к экзамену - восполнить пробелы :)
Read more...