Павел Брылов, skype
DESCRIPTION
HighLoad++ 2013TRANSCRIPT
Как мы делаем Web в Skype
Павел Брылов
Обо мне
• Павел Брылов
• Родом из Казахстана, три года в Эстонии
• Переехал по приглашению Skype и не жалею
• До Skype работал начальником Отдела развития Интернет-
проектов Казахстанской фондовой биржи
Обо мне
• Работаю разработчиком в команде Wallet team (ex. Secure Web)
• Мы занимаемся платежами, интеграцией с платежными
провайдерами, предоставлением API для совершения платежей всем
остальным подразделениям Skype
• Ввиду очевидной важности платежей, много работаем над
улучшением инфраструктуры, технической и организационной части
процесса, чтобы обеспечить бесперебойную работу
О чем доклад?
• О PHP!
• О том как мы (практически) избавились от монилитного приложения,
и построили “облачную” SOA архитектуру
• О практиках и подходах, которые мы считаем обязательными для того
чтобы работать с большими нагрузками
• О том как взять инфраструктуру в свои руки, и быть уверенным что
каждый из тысяч серверов настроен так же как остальные
Но сначала немного историиЭто были лихие 2000е, мы выживали как могли
Несколько лет назад
• Монолитные приложения на каждый user-faced компонент:
• Компоненты тесно связаны между собой, изменение в каком-то общем классе
влечет к немедленным изменениям везде где он используется
• Боязнь что-то менять, изменение одной строчки может сломать что угодно где
угодно
• Очень много кода, несколько общих библиотек, которые менять еще страшнее
• Высокая стоимость внесения изменений, сложно предсказать временные
рамки
Несколько лет назад
• Монолитные приложения на каждый user-faced компонент:
• Одна большая команда которая занимается всеми компонентами. Shared
responsibility = no responsibility
• Спасает только тестирование. Всего функционала. Занимает долгое время,
даже с учетом автоматизации
• Длинные релизы, длинное тестирование, редкий деплоймент
• Масштабируются, но непредсказуемо. Баг в одном месте влияет на всю систему
в целом
Несколько лет назад
• Production сервера настраиваются практически вручную
• Настройка серверов занимает дни, а то и недели
• Даже с готовыми образами операционной системы, слишком много дополнительных
настроек
• Все настройки документированы, но поддерживать документацию в актуальном
состоянии очень трудно
• Быстро выкатить несколько новых серверов в случае пика нагрузки практически
невозможно
• Код деплоится с помощью svn export из тэга, все зависимости - вручную
facepalm.jpg
Нет, так не может продолжатьсяЛюбой стартап достигает фазы когда технический долг мешает развитию
Stratus
• Все началось с фреймворка на PHP, но вскоре переросло в
архитектурную модель с набором договоренностей
• Не зависит от языка программирования и платформы: сейчас в
той же архитектуре прекрасно сосуществуют приложения на
Python, Node.JS и .NET. Работает как на Linux так и в Windows
Azure
Stratus
• Service oriented architecture:
• Вместо большого монолитного приложения много небольших, выполняющих
определенную задачу, и установленных на свой собственный сервер
• Приложения предоставляют и используют API других приложений, таким образом
имплементация может меняться как угодно, прозрачно для остальных компонентов
• SLA и версионизирование гарантирует пользователям API что им не прийдется срочно
менять свой код, если другой компонент изменился
• Четкая изоляция сервисов позволяет лучше планировать нагрузку, и дает возможность
для graceful degradation в случае недоступности сервиса
Stratus
• REST + JSON
• Общее дерево REST ресурсов для всех приложений: позволяет
разделять одну и ту же логическую группу ресурсов между
разными приложениями
• Автоматическое нахождение сервисов (Service auto discovery)
Stratus
application 1
application 1
application 1
Registry
www gateway
api gateway
Stratus
• Приложение регистрируется в Registry, сообщая всю информацию о
себе: какие ресурсы оно предоставляет, какие html страницы может
обслуживать, на каких Gateway должно присутствовать
• Registry в свою очередь передает эту информацию на Gateway (load
balancer), что делает эти ресурсы доступными для пользователя
• Registry знает все и обо всем, и ничем кроме этого не занимается
• Gateway - точка входа и балансировщик нагрузки одновременно
Stratus
User application
UserAccount application
Avatar application
api gateway
https://api.skype.com/users/pavelbrylov
https://api.skype.com/users/pavelbrylov/avatar
Stratus
• Четыре обязательных интерфейса для каждого приложения:
• /stratus/register – Регистрирует приложение в Registry
• /stratus/manifest – Возвращает информацию о приложении, его версии,
библиотеках которые это приложение использует и т.д.
• /stratus/info – Возвращает все доступные в этом приложении ресурсы, в
купе с параметрами, их типами и комментариями об их назначении
• /stratus/health – Сообщает о состоянии приложения
Stratus PHP Framework
• Написан на PHP:
• PHP сильно эволюционировал со времен PHP4, о котором все с удовольствием
шутят. Сегодня это полноценный язык с вполне адекватной реализацией ООП
• Вырос не только язык, но и инфраструктура вокруг него: PHPUnit, CodeSniffer,
PHPMD, Composer, behat и другое
• Низкий уровень входа в язык является и плюсом и минусом: много “PHP
программистов на Wordpress”, мало тех кто пишет действительно хороший код
<?phpnamespace Skype\HighLoad\Endpoint;
class TestEndpoint extends \Skype\Stratus\AbstractService{
/*** HighLoad service** @var \Skype\Stratus\HighLoad\Greeter*/protected $HighLoadGreeter = self::SERVICE;
/** Hello Highload** @RestResource /highload/participant/:username* @RestMethod GET* @RestContentTypeOut application/json; ver=1.0* @Gateway api* @ReturnCode 50000 Generic error** @param string $username Username** @return object Greeting object*/public function greet ($username){
return $this->HighLoadGreeter->greet($username);}
}
<?phpnamespace Skype\HighLoad;
class Greeter extends \Skype\Stratus\Locator\AbstractService{
/*** Greet HighLoad.ru participant** @param string $username Username** @return object Greeting object*/public function greet ($username){
return (object)array('message' => sprintf("Hello, HighLoad.ru, and especially %s!“, $username)
);}
}
service.properties:[service]HighLoadGreeter.server = "#class:\Skype\HighLoad\Greeter"
Stratus PHP Framework
• Stratus Core - ядро фреймворка, содержит только базово необходимый
функционал:
• Request/Response negotiation
• Работа с Registry и обязательные для всех приложений REST ресурсы
• Реализация Dependency injection
• Базовые классы для конфигурации приложения, логгер
• Работа с аннотациями методов на базе Reflection API
• Core - единственная обязательная часть для Stratus приложений написанных на
PHP
А где же все остальное?
Stratus framework
• А все остальное в версионизированных библиотеках
• Зависимости управляются Maven’ом. Изменения в библиотеке больше
не сломают ваше приложение
• Stratus Maven плагин:
• Раскладывает зависимости собранные Maven’ом в определенную структуру,
для дальнейшей упаковки в .deb пакет
• Прогоняет PHPUnit тесты, CodeSniffer, PHPMD, PHPCPD, Code Coverage
• Генерирует документацию с помощью Doxygen
Stratus framework
• Самые популярные Stratus библиотеки:
• Db – библиотека для работы с БД, поддерживает «асинхронные» запросы
• HttpClient – библиотека для работы с HTTP сервисами на базе curl,
поддерживает «асинхронные» запросы
• Cache – предоставляет сервисы для работы с различными кешами, и
абстракцию над кешом на уровне логики (InstanceStash, SharedStash т.д.)
• Jobs/Consumer – библиотеки для выполнения фоновых заданий и работе с
очередями
Continuous Integration
• Билд сервер следит за изменениями в репозиториях, при наличии изменений
запускает Maven, собирает SNAPSHOT пакет и загружает в тестовый deb
репозиторий
• Полученный пакет автоматически устанавливается на тестовые машины
• В тестовом окружении постоянно бегают integration тесты. Если вы что-то сломали,
вы об этом узнаете
• Когда приложение готово к релизу, билд сервер повторяет процедуру, но собирает
релиз пакет, который при условии отсутствия в нем багов попадет в продакшн
Continuous Integration
• Integration тесты написаны на Python и запускаются тестовым фреймворком Taffy
• Тестируются как внутренние и внешние API, так и full flow тесты в браузерах с
использованием Selenium и WebDriver
• Тесты, как и все остальное относящееся к приложению находятся в одном с ним
репозитории
• Результаты тестирования аггрегируются в web-интерфейсе, таким образом все
заинтересованные, включая менеджемент, могут в любой момент посмотреть
готов ли компонент к деплою в production
В итоге
• Все компоненты логически разделены и изолированы, внесение изменений не вызывает
страха. Время и стоимость изменений легко прогнозируется
• Вместо одной большой команды, занимающейся всем на свете, несколько небольших,
сконцентрированных на своих компонентах и библиотеках. Работа над общими
компонентами ведется по логике open source: pull request’ы, ревью и т.д.
• Так как мы строим свои сервисы на базе тех же API, которые предоставляем пользователям,
мы уверены в их качестве и стабильности
• Легко горизонтально масштабировать: простым добавлением серверов с приложением, на
которое увеличилась нагрузка
Стоп, стоп. Просто добавить сервер?
Chef
• Система автоматизации инфраструктуры, гарантирует что все сервера с
определенной ролью/набором рецептов будут настроены одинаково
• Разработчик приложения - тот кто знает как оно должно быть настроено
• Мы не любим писать документацию, зато мы любим писать код
• Мы тестируем наши приложения, но мы не тестируем нашу инфраструктуру.
Это не правильно
• Ruby с простым DSL, порог вхождения минимальный
package “apache2” doaction :installversion “2.2.23”
end
service “apache2” doaction :enablesupports :restart => true, :reload => true
end
template “/etc/apache2/conf/httpd.conf” dosource “httpd.conf.erb”mode 0644variables(:server_name => “highload.ru”,:doc_root => “/usr/local/apache2/htdocs”
)notifies :restart, "service[apache2]“
end
httpd.conf.erb:ServerName <%=@server_name %>DocumentRoot "<%=@doc_root %>"
Chef
• Все измнения в cookbook’ах проходят тот же путь что и
приложения: разработка, тестирование, пакетирование и
деплоймент
• Тестирование с помощью foodcritic и test-kitchen
• Knife плагин для работы с репозиторием
Chef
• Версионизированные роли: stratus-highload-1-0
• Постепенное развезтывание (Gradual rollout)
• Обработчики ошибок (Exception и Report handlers)
• Автоматическое добавление в мониторинг
Cloud
• Chef - очень мощный инструмент, но всю свою мощь он показывает в облачной
инфраструктуре
• Собственная cloud платформа на базе XEN
• Позволяет иметь одинаковые контейнеры в тестовом окружении и в production
• Создать 10 серверов для приложения можно одной командой:
• knife cloud server create [cloud name] [application-role] -c 10
• Аналогичные плагины есть для Windows Azure, Amazon EC2, Rackspace, Linode и т.д.
А как же база данных?
Relman
• Все измнения в базе данных проходят тот же путь что и приложения:
разработка, тестирование, пакетирование и деплоймент
• Relman – программный продукт для деплоя на разные сервера БД
• UI для деплоймента позволяет в интерактивном режиме смотреть diff
функций, таблиц и других компонентов баз данных, давая возможность DBA
быстро и наглядно увидеть что конкретно они деплоят
• Даже в ручном режиме relman позволяет двум администраторам базы
данных деплоить ~150 релизов в неделю
table: highload.participantsdescription: HighLoad.ru participants
columns:- id_participant:
type: bigintnot_null: Truedescription: Participant iddefault_expr: partconf.global_id()
- name:type: textnot_null: Truedescription: HighLoad.ru participant name
primary_key:pk_participants:
columns: [id_participant]
uniques:u_name:
columns: [name]
-- database: highloaddb (highload_user)CREATE OR REPLACE FUNCTION “highload_${db.safe_version}”.list_participants(
OUT status int,OUT status_text text,OUT id_participant bigint,OUT name text
) RETURNS SETOF record AS $BODY$BEGIN
RETURN QUERY SELECT 200, 'OK'::text, p.id_participant, p.nameFROM highload.participants p;
RETURN;END;$BODY$ LANGUAGE plpgsql SECURITY DEFINER;
- !tables:- ./tables/participants.yaml
- highloaddb:- sql_file: highload/participants.data.sql
release.yaml
Версионизированные схемы
• highload_1_0
• Безопасный деплоймент – новая схема еще не используется
• Позволяют делать gradual rollout и rollback
Больше, больше автоматизации!
потому что автоматизации не бывает много :)
Air Traffic Control
• Центр управления полетами на базе тикет системы
• Следит за всем что происходит вокруг и реагирует на изменения:
• Создает деплоймент задания с полным changelog-ом и списком коммитеров
• Запускает релевантные тесты и добавляет результаты к таску
• Отмечает и следит за зависимостями
• Мониторит статус задания, и как только он достигает статуса «Deploy to production» и все
зависимости задеплоены - инициирует автоматический gradual deployment
• Skype бот, сообщающий всем заинтересованным лицам о том какие изменения
происходят с теми компонентами над которыми они работают
Будущее
• Windows Azure!
• Свое облако хорошо – но сложно, и дорого
• C#/.NET
• Абсолютная уверенность в том что эта миграция пройдет легко и
непринужденно