• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Воюем за ресурсы (ZFConf2011)
 

Воюем за ресурсы (ZFConf2011)

on

  • 3,123 views

 

Statistics

Views

Total Views
3,123
Views on SlideShare
2,577
Embed Views
546

Actions

Likes
6
Downloads
25
Comments
0

4 Embeds 546

http://codemehanika.org 539
url_unknown 5
http://twitter.com 1
http://www.slideshare.net 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Воюем за ресурсы (ZFConf2011) Воюем за ресурсы (ZFConf2011) Presentation Transcript

    • Воюем за ресурсы:повышение производительности ZF приложения спомощью phpDaemon + Varnish + ESI
    • Алексей КачаевSenior/Lead PHP Developer atCogniance4+ года опыта c PHP3+ года использования ZendFrameworkАктивный участникzendframework.ru/forumZF2 contributor
    • Мои контактыEmail:kachayev@gmail.comTwitter:@kachayevFacebook:http://www.facebook.com/kachayevGithub:https://github.com/kachayev
    • О чем мы будем говорить• о ресурсах и о том, почему их не хватает• о времени и о том, куда оно девается• о пользователях, современных веб-приложениях и о проблемах, с ними связанными• ...
    • Как мы будем говорить1. 2 проблемы в использовании ресурсов на реальныхпримерах из широкой практики2. как эти пробемы можно решить быстро и практическибезболезнено (как в новом, так и в функционирующемпроекте)3. контректный zf app и все шаги имплементации того, чтоописано в п. 2 Понимание проблем и путей их решения важно
    • СХЕМЫ БОЕВЫХ ДЕЙСТВИЙ
    • Проблема 1. Запросы иинициализация Пользователь -> Запрос к серверу = nginx + apache2 + php + Zend + application
    • apache2 + mod_php + Zend
    • Проблема 1. Запросы иинициализация AJAX + Пользователь => Много запросов к серверу = (nginx + apache2 + php + Zend + application) * многоПримеры: autosuggest-поле, валидация формы, загрузкавиджетов и т.д.
    • apache2 + mod_php + Zend + AJAX
    • Проблема 1. Запросы иинициализация Rich application = AJAX * много = (nginx + apache2 + php + Zend + application) * много (в квадрате)
    • Куда уходит время- создание объекта приложения- чтение и сборка конфигурации (тут даже кеш не спасает)- загрузка и инициализация ресурсовЗатраты: до 40-60% времени выполнения.
    • Как хотелось бы? (псевдо код)Framework::initialize();while($request = Somewhere::request()) { // Тут мы что-то делаем // Отдаем ответ}Framework::shutdown();
    • Особенности PHP реализации1. Проблемы: - корявая реализация поддержки Fast-CGI на PHP2. Существующие решения: - php-fpm (FastCGI Process Manager, http://php-fpm.org/) - phpDaemon
    • phpDaemon в студииОсновные возможности- WebSocket, HTTP, FastCGI, flash- асинхронные клиенты для MySQL, Memcache, MongoDB идругих- динамическая перегрузка кода в демон при изменениифайлов- статистика по количеству запросам, памяти и т.д.- гибкая настройка workerов...- многое другое
    • Схема того, как будет работать сphpDaemon
    • Проблема 2. Кеширование HTML1. Это заманчиво!- обслуживание большого количества подключенийодновременно- возможность не инициализировать приложение вообще2. Это проблематично!- "размазывание кеша" (для авторизированныхпользователей, по cookies и т.д.)- точечная инвалидация = "микро-инфаркт" (например,блок последних комментариев на хабре)
    • "Размазывание кеша"
    • "Микро-кеш-инфаркт"
    • Проблема 2. Возьмем хитростью1. Varnish, как промежуточный кеширующий сервер(caching HTTP reverse proxy)http://www.varnish-cache.org/2. ESI, как markup language связи логических кусков HTMLhttp://en.wikipedia.org/wiki/Edge_Side_Includes<esi:include src="..." onerror="continue"/>3. Nginx, как front web serverhttp://nginx.org/
    • Проблема 2. Расплата за хитростьESI = Увеличение количества запросов к backendБольшинство из этих запросов однотипно и нетребуетмощностей всего приложения ВЕРНУЛИСЬ К ПРОБЛЕМЕ 1 Слава богу, мы уже знаем как ее решать.
    • ОБЩАЯ СХЕМА РАБОТЫ С КЕШ-СЕРВЕРОМ И ДЕМОНАМИ
    • Общая схема Прокси Статика на daemon Запросы на backend-ы Кеширование
    • ОПИСАНИЕ DEMO APPLICATION
    • Демо приложение: "Конференция"1. Список докладов из базы данных2. Добавление докладов в избранное без регистрации3. Форма поиска по докладам с "подсказыванием" тегов4. ~ Вход/выход для зарегистрированных пользователейSourceshttps://github.com/kachayev/zfconf-speech
    • Демо приложение: "Конференция"
    • Демо приложение: "Конференция"
    • ВНЕДРЕНИЕPHPDAEMON
    • phpDaemon: установка1. Официальная документацияhttps://github.com/kakserpom/phpdaemon/wiki/Installation-(common)2. Используется PECL расширения libevent, proctitle(возможно потребуется пересборка PHP из исходников)http://tokarchuk.ru/2010/09/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-phpdaemon-libevent-%D0%BD%D0%B0-ubuntu/ РУКОВОДСТВА БЫСТРО УСТАРЕВАЮТ
    • phpDaemon: установка на Ubuntu0. Нам понадобиться: php-dev, build-essential, git1. Удаляем старую libevent12. Скачиваем новую из ветки 1.4 (2я пока в альфе). Далеенаше любимое .configure && make && make install3. Устанавливаем pecl extension libevent-0.0.4, добавляемего подгрузку в /etc/php5/cli/php.ini4. Аналочиные действия с proctitle5. Устанавливаем phpDaemon... ->
    • phpDaemon: установка на Ubuntucd /usr/local/libgit clone git://github.com/kakserpom/phpdaemon.git $pathcd ./phpdaemonchmod +x ./bin/phpdaemonln /usr/bin/phpdaemon /usr/local/lib/phpdaemon/bin/phpdaemoncp init-scripts/phpd /etc/init.d/mkdir /etc/phpd/ && cp conf/phpd.conf.example /etc/phpd/phpd.conf/usr/local/lib/phpdaemon/bin/phpdaemon startВ файл конфигурации добавляем следующее:HTTP {enable 1; listen 127.0.0.1; listen-port 8020;responder "Example"}
    • phpDaemon:default application1. Принимает HTTPзапросы на порт, без рвеб-сервера2. Siege показал 370обработанных реквестовв секунду при 100одновременныхподключениях.
    • Прикручиваем к своему проекту1. Выделяем консистентные блоки (autocomplete,autosuggest, рендеринг отдельных блоков, виджеты и т.д.)Важно! Операция на демоне должна затрагивать минимумразличных частей приложения. Подходят: ajax-проверкаполей формы, inline-редактирование данных,autosuggest/complete и т.д.2. Отделяем выполнение (Ajax, SSI, ESI etc).3. Поднимаем демон, реализованный как HTTP App (прижелании можно и Fast CGI).(следующий слайд)
    • Прикручиваем к своему проекту(прд.)Начинаем с Nginx-подобного конфиг-файла./etc/phpd/phpd.conf Примечание: (Можно через AppResolver.php, но для простых случаев это overkill)
    • phpDaemon + Zend FrameworkResponder application - класс, наследник AppInstanceДолжен реализовать следующие функции:init() - инициализация фреймворка (создаем ZendApplication, бутстрапимся, получаем Front Controller)beginRequest() - вызывается, когда приложение получаетновый Request для обработки (возвращаем специальныйобъект - наследник HTTPRequest)onReady() - вызывается после отработки инициализацииonShutdown() - завершаем работу фрейморка
    • phpDaemon + ZF (окружение)/usr/local/phpdaemon/applications/ZfconfApp.php
    • phpDaemon + ZF (app instance)
    • phpDaemon -> RequestHTTPRequest содержит все нужные нам данные GET,POST, COOKIES, SESSION и т.д.В наследнике должны реализовать функцииrun() - передать в приложение новые суперглобальные,подготовить Response, должны вернуть Request::DONE(сбрасываем Request, Response объекты Front Controllerа ивыполняем run())onFinish() - возвращаем подготовленный ранее Response
    • phpDaemon -> Request
    • Nginx -> phpDaemon4. Nginx "ловит" адрес и перенаправляет его на backend(HTTP, или FastCGI)Полный разбор nginx кофигурации не делаем.Только момент "перехвата" URL.
    • Несколько замечаний (номер 1)Важно! При реализации данного подхода критическиважно, чтобы инициализация (Bootstrap, ApplicationResources) не делала ничего request-зависимого.Например.Присваивание текущего языка (current language) в Bootstrap- это очень большая ошибка. Для этого есть плагины.(вспоминаем цикл диспечирезации).
    • Несколько замечаний (номер 2)Важно! Внимательно следите, чтобы никто "не посмел"отправить клиенту хоть какие-то данные, до тех пор, покаэто явно не сделает phpDaemon.Например.В коде Actionа:$this->_helper->json($data);Приведет к:(примеров много)
    • Что получилось?Autosuggest отдается демоном.
    • Known issues1. Debian, Ubuntu - проблемы с рестартом при "зависших"подключениях (аналогично Mongo). "Спасает":2. Если работа ведется без веб-сервера, то нужно помнитьо статике. Например, попытка обработать запрос/favicon.ico с помощью Zend отправляет phpDaemon вглубокий down.Т.е. без веб-сервера фильтруем статику в ручную.
    • Что дальше?Неблокирующий MySQL драйверНеблокирующий Memcache клиентИ т.д.Как это работает? (на примере MySQL)1. Запрос (обработчик) делает request на MySQL и вешаетcallback2. Вызывается $this->sleep(30) - диспечер выбрасываетпроцесс из обработки, чтобы вернуться через 30 сек3. В callback делается $this->wakeup()
    • Что дальше?В последних версиях появилась возможность использоватьSandboxFatal error воркера не приводит к перезапуску демона.
    • Оценим полученный результат+ Плюсы1. Снижение нагрузки на сервер и потребляемых ресурсов2. Уменьшение времени ожидания ответа- Минусы1. Усложнение деплоя2. Усложнение тестирования3. Усложнение управления приложением
    • Полезные материалы по теме0. "Офф. сайт"http://phpdaemon.net/1. phpDaemon - фреймворк асинхронных приложенийhttp://habrahabr.ru/blogs/php/79377/2. Wiki документацияhttps://github.com/kakserpom/phpdaemon/wiki
    • ВНЕДРЕНИЕ VARNISH
    • Varnish: сильные стороны1. Мощный язык конфигурации VCL (Varnish ConfigurationLanguage)2. Легкость горизонтального масштабирования3. Возможность использования механизмов балансировкинагрзуки с учетом времени ответов и загруженности бекендсерверов4. Поддержка ESI разметки5. Большое количество отличных утилит дляпрофайлирования и мониторинга
    • Varnish Administration Console
    • Varhish: установка на Ubuntucd /tmpsudo bashcurl http://repo.varnish-cache.org/debian/GPG-key.txt | apt-key add -echo "deb http://repo.varnish-cache.org/ubuntu/ $(lsb_release -s -c) varnish-2.1" >> /etc/apt/source.listapt-get update && apt-get install varnish# Далее вы можете использовать init-скрипт* Usage: /etc/init.d/varnish {start|stop|restart|force-reload}Установка на других платформах:http://www.varnish-cache.org/docsУстановка web-based admin console:http://www.varnish-cache.org/trac/wiki/WebGui
    • Конфигурация демона/etc/default/varnish для Ubuntu- необходимость запуска демона START=yes- порт, который будет слушать демон (:81)
    • VCL файл/etc/varnish/varnish.vcl- описание backend
    • VCL файл/etc/varnish/varnish.vcl- описание процедур hash, fetch, deliver, hit, recv
    • VCL файл/etc/varnish/varnish.vcl- описание процедур hash, fetch, deliver, hit, recv
    • VCL файл
    • VCL файл/etc/varnish/varnish.vcl- описание процедур hash, fetch, deliver, hit, recv
    • Nginx location resolving
    • PhpDaemon workersВ указанном выше примере использовался один и тот жеZfconfApp на порту 8091.Но, часто есть смысл разграничивать обработчики:- отдельный worker на autosuggest- отдельный worker на рендеринг AJAX-видетаВ таких случаях используется AppResolver.php (можнопрописывать правила "раздачи" запросов на worker-ы).
    • Использование ESIОсновное- Формат: <esi:include src="" />- Директивы alt и onerror на данный момент неподдерживаются- для Zend-a самописный View Helper (рендер include иотправление заголовка esi-enabled)
    • Использование ESIОбратить внимание- отключаем сжатие (nginx: gzip off, apache2: no deflate)- проблемы с ETag, If-Non-Match- отслеживание поведения кеша по URL (nginx rewrite,apache2 rewrite, Zend routing, URL-mark etc)- готовьтесь к сюрпризам :)
    • А можно ли по другому?По аналогу со схемой Nginx + Varnish + ESI можноиспользовать схемуNginx + SSI + MemcacheМинусы- nginx не умеет писать контент в memcache (нужно писатьсо стороны backend-a)- слабые возможности конфигурирования кеш-ключа- сложно управлять кешированием
    • Подводные камни1. Правильность разграничения контентаНапример, если HTML различается по языку, хранящемуся в cookies, тоэто нужно учитывать.
    • Подводные камни2. Очистка выполняется через CLI или отправкой запросаHTTP PURGEНе самая простая процедура, поэтому для dev-режима нужнопредусмотреть возможность работы с TTL=0.Очистка varnish-кеша по объекто-зависимым событиям.Пример: очистить кеш списка докладов после внесенияизменений пользователем.- переопределить CacheManager- обернуть необходимые cache backend в специальныевраппер
    • Подводные камниКонкретная реализация зависит от общей схемы работыс кешем
    • Подводные камни3. Управление кешем со стороны клиента (Cache-Control,etc)В demo app есть пример работы заголовками клиента4. Документация во многом не соответствует правде.
    • Нагрузочное тестированиерезультатаНе очень информативно и предсказуемо, но по факту:ab -n 100 -c 5 http://zfconf.loc/Преимущество: response time практически неувеличивается при повышении concurrency level.
    • Ссылки на полезные материалыVarnish docs and tutorials:• http://www.varnish-cache.org/docs/2.1/index.html• http://www.ibm.com/developerworks/opensource/library/os-php- varnish/?ca=dgr-lnxw06Varnish-PHP• http://www.mediawiki.org/wiki/Manual:Varnish_cachingESI:• http://www.varnish-cache.org/trac/wiki/ESIfeatures• http://cd34.com/blog/infrastructure/no-esi-processing-first-char-not/VCL:• http://www.varnish-cache.org/docs/2.1/tutorial/vcl.html
    • Спасибо за внимание! Вопросы ???
    • Мои контактыEmail:kachayev@gmail.comTwitter:@kachayevFacebook:http://www.facebook.com/kachayevGithub:https://github.com/kachayev