Быстрое масштабирование систем

1,133 views

Published on

0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,133
On SlideShare
0
From Embeds
0
Number of Embeds
162
Actions
Shares
0
Downloads
0
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Быстрое масштабирование систем

  1. 1. Быстрое масштабирование систем Константин Андрюнин
  2. 2. Быстрое масштабирование систем. Аудитория и нтернет -сайта растёт не по дням, а по часам. Актуальным становится вопрос об масштабировании системы. Как это сделать? Какие сложности могут возникнуть?
  3. 3. Когда становится очевидным, что железо не справляется?
  4. 4. Когда становится очевидным, что железо не справляется? <ul><li>когда оно странно пахнет… </li></ul><ul><li>и дымится. </li></ul>
  5. 5. Когда становится очевидным, что железо не справляется? <ul><li>время отклика </li></ul><ul><li>отказы запросов </li></ul><ul><li>отсутствие реакции на запрос </li></ul><ul><li>непонятные ошибки, которых ранее месяцами не было </li></ul>
  6. 6. Когда становится очевидным, что железо не справляется? <ul><li>когда падают сервера </li></ul><ul><ul><li>нехватка памяти </li></ul></ul><ul><ul><li>сбои репликации </li></ul></ul><ul><ul><li>низкая производительность терминальных приложений </li></ul></ul><ul><ul><li>ошибки открытия сокетов </li></ul></ul><ul><ul><li>ошибки выделения потока на запрос </li></ul></ul>
  7. 7. Прежде всего, плясать от пользователя!
  8. 8. Прежде всего, плясать от пользователя! <ul><li>Попытаться разыграть возможные поведения пользователя по персонам (девочка-студентка, молодой гик, технофоб и т.д.) </li></ul><ul><ul><li>разделить виды запросов пользователя к системе (вызов френдленты, комментирование) </li></ul></ul><ul><ul><li>взять наиболее часто встречающиеся виды запросов и нарисовать их, стрелочками показывая «а вот теперь он идёт туда» в сиквенс-диаграмме </li></ul></ul>
  9. 9. Нарисовать sequence диаграмму
  10. 10. Н айти и оценить проблемные блоки <ul><li>идти от внутреннего пути пользователя </li></ul><ul><li>где больше всего теряется времени </li></ul><ul><ul><li>может сказаться на количестве свободных ниток </li></ul></ul><ul><li>где больше всего тратится процессорного времени </li></ul><ul><ul><li>может не хватить другим на обработку </li></ul></ul>
  11. 11. Н айти и оценить проблемные блоки <ul><li>неразделяемые ресурсы, в очередях на обращение к которым стоят модули программ </li></ul><ul><ul><li>прежде всего - обращения к диску </li></ul></ul><ul><ul><li>общая память приложений </li></ul></ul><ul><ul><li>хранение сессий в частности </li></ul></ul><ul><ul><li>и, вообще, хранение данных </li></ul></ul><ul><ul><li>гэтвей на приём и отправку запросов </li></ul></ul><ul><li>инфраструктура, накладывающая ограничения на траффик </li></ul>
  12. 12. При проектировании системы полезно воспользоваться следующими приёмами:
  13. 13. <ul><li>предлагать все-все идеи новой системы : как она должна функционировать, из каких блоков состоять, как в ней разрешены указанные проблемы </li></ul><ul><li>посмотреть на уже готовые примеры (хотя бы на уровне блок-схем) </li></ul><ul><li>посмотреть достоинства и недостатки каждой предложенной архитектуры и кратко рассмотреть, чем это грозит в ближней перспективе </li></ul><ul><ul><li>количество работ по переделке </li></ul></ul><ul><ul><li>время </li></ul></ul><ul><ul><li>как решены проблемы того, что переписывать не хочется </li></ul></ul>
  14. 14. Просто требуется представить, как дальше будет развиваться проект <ul><li>Какая посещаемость будет у него через год? </li></ul><ul><li>А через два года? </li></ul><ul><li>А через три? </li></ul>
  15. 15. Типичные решения проблемы производительности
  16. 16. Более мощное железо ? <ul><li>даёт быстрый рост производительности </li></ul><ul><li>не нужно переделывать систему </li></ul><ul><ul><li>запас производительности быстро исчерпывается </li></ul></ul><ul><ul><li>требует хорошей команды админов для переноса кода </li></ul></ul><ul><ul><li>энергопотребление = проблемы со стойками </li></ul></ul>
  17. 17. Эффективный код <ul><li>помогает разгрузить сервер </li></ul><ul><li>может решить какие-то замеченные проблемы со стабильностью и безопасностью </li></ul><ul><ul><li>к сожалению плохо помогает с неразделяемыми и разделяемыми ресурсами </li></ul></ul><ul><ul><li>чаще всего тормозит или нестабилен не плохой код, а используемые чужие библиотеки, сервера и БД </li></ul></ul><ul><ul><li>уже в краткосрочной перспективе при увеличении количества народа быстродействия снова не хватит </li></ul></ul>
  18. 18. Оптимизировать запросы к БД <ul><li>правильно использовать возможности БД – это необходимость </li></ul><ul><ul><ul><li>от join ’ов нужно избавляться </li></ul></ul></ul><ul><ul><ul><li>не забывать использовать выборки по индексам! </li></ul></ul></ul><ul><ul><ul><li>Вспомнить SQL (к примеру, считать количество полей count ’ом, а не выборкой) </li></ul></ul></ul><ul><li>хранимые процедуры позволяют существенно увеличить производительность </li></ul>
  19. 19. Оптимизировать запросы к БД <ul><ul><li>уже в среднесрочной перспективе эффект сойдёт на нет: </li></ul></ul><ul><ul><ul><ul><ul><li>БД ограничена по вычислительным ресурсам </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>а все возможности для оптимизации будут уже исчерпаны </li></ul></ul></ul></ul></ul>
  20. 20. Оптимизировать структуру БД <ul><li>Разделить поля по типу записи и чтения в них : </li></ul><ul><ul><li>статические (редко меняемые, например, профиль пользователя), оптимизировать для чтения </li></ul></ul><ul><ul><ul><ul><ul><li>откроет возможности для кэширования </li></ul></ul></ul></ul></ul><ul><ul><li>выделить часто обновляемые таблицы (к примеру, сообщения в чате) </li></ul></ul><ul><ul><ul><ul><ul><li>позволит более эффективно воспользоваться механизмом репликации </li></ul></ul></ul></ul></ul><ul><ul><li>выделение постоянно дополняемых таблиц </li></ul></ul><ul><ul><ul><ul><ul><li>позволит использовать механизм партишининга </li></ul></ul></ul></ul></ul>
  21. 21. Оптимизировать структуру БД <ul><li>разделение хранимой информации по схемам: </li></ul><ul><ul><ul><ul><ul><li>к примеру, вынос информации пользователей, чьё имя начинается от A до D в одну схему, E - H – в другую и т.д. </li></ul></ul></ul></ul></ul><ul><ul><li>позволит легко переносить схемы между различными серверами БД, становится легче добавлять новые машины </li></ul></ul><ul><ul><li>меньший объём информации = быстрые выборки! </li></ul></ul>
  22. 22. Оптимизировать структуру БД <ul><li>Более эффективная структура БД позволит расширять поля для хранимой информации </li></ul><ul><li>Оптимизация данных может помочь эффективному использованию индексов </li></ul><ul><ul><li>серьёзная переделка БД заставляет писать новую бизнес-логику доступа к ней </li></ul></ul><ul><ul><li>хорошо, когда эта бизнес-логика отделена от программы, а если она находится в коде талантливого индуса, куда лезть не следует? </li></ul></ul>
  23. 23. Использовать репликацию <ul><li>Теперь выборки могут производиться сразу на нескольких серверах! </li></ul><ul><ul><ul><ul><ul><li>Особенно эффективна репликация по типу: пишем в мастер, читаем со слейвов. </li></ul></ul></ul></ul></ul><ul><li>Для многих серверов есть готовые решения для балансировки нагрузки, зачастую даже интегрированные с кэшем выдачи </li></ul>
  24. 24. Использовать репликацию <ul><ul><li>в долгосрочной перспективе могут начаться отказы и ошибки репликации при определённой скорости записи </li></ul></ul><ul><ul><li>при падении сети происходит рассинхронизация БД </li></ul></ul><ul><ul><ul><ul><ul><li>особенно губительно для реплик мастер-мастер </li></ul></ul></ul></ul></ul><ul><ul><li>требует переделки логики доступа к БД </li></ul></ul><ul><ul><ul><ul><ul><li>нужно вводить балансер, который равномерно распределяет нагрузку между зеркалами </li></ul></ul></ul></ul></ul>
  25. 25. Кэшировать! <ul><li>Память всё дешевеет, а производительности на кэш не нужно (можно использовать старые машины) </li></ul><ul><ul><ul><ul><ul><li>очень правильно выделить отдельные машинки под сервера кэша – это может быть MemCached или JBoss Cache </li></ul></ul></ul></ul></ul><ul><li>для этого очень помогает выделение объектов, которые не меняются во время жизни сессии пользователя, к примеру – настройки профиля пользователя </li></ul>
  26. 26. Кэшировать! <ul><li>когда кэш является посредником к БД – эффективно писать интерфейсы доступа к данным </li></ul><ul><ul><ul><ul><ul><li>Нужно получить какой-то объект – дёргаем интерфейс. Он лезет в кэш. Если нет объекта в кэше – лезет в БД, кладёт в кэш и отдаёт реквестеру. Таким образом в кэше всегда есть актуальный объект. </li></ul></ul></ul></ul></ul>
  27. 27. Кэшировать! <ul><li>Основной минус: кэш неэффективен, когда объекты запрашиваются редко либо объектов так много, что они просто вытесняются более новыми </li></ul><ul><ul><li>нужно считать, где кэш будет эффективен </li></ul></ul><ul><ul><ul><ul><ul><li>для этого пригодится аудит системы, знание внешнего и внутреннего путей пользователя </li></ul></ul></ul></ul></ul><ul><ul><li>переделка объектов для эффективного кэша затрагивает структуру БД и бизнес-логику приложений </li></ul></ul><ul><ul><ul><ul><ul><li>см. многострадальный код индуса </li></ul></ul></ul></ul></ul>
  28. 28. Использование множества зеркал и балансировщика между ними <ul><li>Более гладко распределяется нагрузка </li></ul><ul><li>Можно за балансировщиком поставить различные машинки для разных типов запросов </li></ul><ul><ul><ul><ul><ul><li>к примеру ngnix как балансер, один сервер – для отдачи картинок и прочей статики и пару серверов с ПХП приложениями </li></ul></ul></ul></ul></ul><ul><ul><li>если за разными серверами, скрытыми балансером находится общий бэкэнд или неразделяемый ресурс (к примеру, БД), то эффективность механизма балансировка резко падает </li></ul></ul>
  29. 29. Очереди задач <ul><li>Те вещи, которые выполняются периодически (например, рассылка комментариев по почте) неплохо выносить в специальные обработчики с очередями задач к ним. </li></ul><ul><ul><ul><ul><ul><li>можно использовать готовый механизм очередей задач (например, Apache ActiveMQ – он имеет механизмы интеграции с большинством современных языков программирования) </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>можно написать свой (как обёртку над кроном или другим планировщиком) </li></ul></ul></ul></ul></ul>
  30. 30. Очереди задач <ul><li>главное достоинство – возможность отложить какую-то задачу в очередь и как только для неё будут свободные ресурсы – она выполнится </li></ul><ul><ul><ul><ul><ul><li>это серьёзно позволяет нормировать нагрузку на сервер </li></ul></ul></ul></ul></ul><ul><li>синхронизацию каких-то частей тоже эффективно производить через очереди </li></ul><ul><ul><ul><ul><ul><li>конвертация БД или перекладывание данных из одного формата в другой </li></ul></ul></ul></ul></ul>
  31. 31. Очереди задач <ul><li>в обработку через очереди замечательно выносятся те вещи, что не требуют немедленной реакции </li></ul><ul><ul><ul><ul><ul><li>например, различные рассылки внутрисистемных уведомлений, внутренняя почта, рассылка уведомлений администратора, подсчёт пользователей на сайте, различная статистика </li></ul></ul></ul></ul></ul><ul><li>полезное достоинство – связывание частей системы через общие серверы очередей </li></ul><ul><ul><ul><ul><ul><li>класть в очередь могут одни части системы на одной машине, а выполнять – другие, на другой, что позволяет гибко нормировать нагрузку </li></ul></ul></ul></ul></ul>
  32. 32. Очереди задач
  33. 33. Очереди задач <ul><ul><li>основной минус очередей – асинхронность выполнения, никто не гарантирует получения ответа в заданный промежуток времени </li></ul></ul>
  34. 34. RPC <ul><li>Использовать различные виды RPC , начиная с CORBA , Ice и RMI с JMX ’ом, заканчивая Web Service и REST архитектурами. </li></ul>
  35. 35. RPC <ul><li>Позволит вызывать процедуру на одной машине, а выполнять на другой, что сразу же делает архитектуру масштабируемой </li></ul><ul><li>В случае применения кэширования и использования интерфейсов к доступу к различным структурам данных, легко позволит ввести кластеризацию </li></ul><ul><li>Можно вынести и изолировать на машине ту самую пресловутую индусскую бизнес-логику </li></ul>
  36. 36. RPC <ul><li>К сожалению, большие накладные расходы </li></ul><ul><ul><ul><ul><ul><li>каждый запрос оборачивается каким-то специфичным контейнером, парсится как на стороне клиента запроса, так и на стороне сервера – отсюда дополнительные издержки и время </li></ul></ul></ul></ul></ul><ul><li>Сильно зависит от сетевой инфраструтуры проекта </li></ul><ul><ul><ul><ul><ul><li>если что-то не так с роутингом, если есть потери пакетов, то время существенно увеличивается </li></ul></ul></ul></ul></ul>
  37. 37. RPC <ul><li>На программном уровне возникает целый ряд эксепшинов, связанных с обработкой отказов сети и потери целостности сетевого контейнера из-за чего приходится писать дополнительный код </li></ul><ul><ul><ul><ul><ul><li>который в свою очередь требует тестирования, прогнозирования всех видов исключительных ситуаций и, вообще, поправок к архитектуре выдачи запросов </li></ul></ul></ul></ul></ul><ul><li>серьёзно усложняет отладку приложений – ошибки теперь приходится ловить не в одном месте, а в нескольких сразу </li></ul>
  38. 38. Использование серверов приложений <ul><li>Не нужно думать о кластеризации и масштабировании самому: за тебя (по идее) сделает всё платформа </li></ul><ul><ul><li>Главный минус – в том, что кластеризация в серверах приложений производится за счёт того же RPC </li></ul></ul><ul><ul><ul><ul><ul><li>из-за чего наследуются все его проблемы, да ещё добавляются специфичные обёртки самого сервера </li></ul></ul></ul></ul></ul><ul><ul><li>Так же плохо, что сервера хорошо скрывают, как он производит распараллеливание запросов </li></ul></ul>
  39. 39. Использование серверов приложений <ul><li>Изучение логики платформы, особенностей администрирования и наличие подводных камней при разработке и эксплуатации </li></ul><ul><ul><ul><li>требует подготовки кадров </li></ul></ul></ul><ul><ul><ul><li>в случае ухода квалифицированного специалиста имеем проблемы с поддержкой </li></ul></ul></ul>
  40. 40. Применяйте следующие подходы: <ul><li>Вынос, кластеризация и кэширование всех ранее неразделяемых ресурсов </li></ul><ul><ul><ul><ul><ul><li>обращения к диску? – создание сервиса и RPC к нему </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>обращение БД? Кластеризация, кэширование, общая точка входа через интерфейс. </li></ul></ul></ul></ul></ul>
  41. 41. Применяйте следующие подходы: <ul><li>Всё через интерфейсы! </li></ul><ul><ul><ul><ul><ul><li>оборачивайте старые блоки, которые не хочется изменять интерфейсами в надежде, что когда-нибудь и до них дойдут руки </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>к примеру, какая-то хитрая бизнес-логика? – оборачиваем, а потом, позже, - сервис и RPC к нему </li></ul></ul></ul></ul></ul>
  42. 42. Применяйте следующие подходы: <ul><li>В случае рефакторинга дизайна – глубокое последовательное и поэтапное разделение модели и представления </li></ul><ul><ul><ul><ul><ul><li>зачастую в PHP проектах разделение идёт не совсем по паттерну MVC </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>другой случай – модель для сборки страниц размазана по сессиям, кукам и запросам </li></ul></ul></ul></ul></ul>
  43. 43. Применяйте следующие подходы: <ul><li>Задача рефакторинга дизайна: на первом этапе вынести в интерфейсы всю бизнес-логику если не формирования модели, то, хотя бы, сохранения её в БД </li></ul><ul><li>На втором этапе - имплементировать эти интерфейсы с помощью менеджера доступа к БД или RPC </li></ul>
  44. 44. Применяйте следующие подходы: <ul><li>Главное: на страницах не должно остаться никаких SQL запросов! </li></ul><ul><ul><ul><ul><ul><li>На страницах должны дёргаться методы специальных классов, являющимися интерфейсами к бэкэнду системы. </li></ul></ul></ul></ul></ul>
  45. 45. Тестирование <ul><li>Все модули новой системы должны тестироваться! </li></ul><ul><li>оптимально тестировать на реальных пользовательских данных </li></ul><ul><ul><ul><ul><ul><li>сняв дамп текущих запросов пользователей, скажем, за день и прогнав их через тестируемый компонент </li></ul></ul></ul></ul></ul>
  46. 46. <ul><li>Вопреки каноническим правилам не рекомендую тестировать каждую итерацию </li></ul><ul><ul><li>итерации нужно группировать по общему признаку и выкатывать на тесты сериями </li></ul></ul><ul><ul><li>отлично, если совершенно другая команда разработчиков пишет тесты, но, часто, - это недостижимый идеал </li></ul></ul><ul><ul><li>поэтому нужно составлять по фиксированным требованиям каждой итерации тест-план </li></ul></ul><ul><ul><li>после чего выпустить на модули альфа-тестеров </li></ul></ul>Тестирование
  47. 47. <ul><li>Выбор времени выкатки на альфа-тесты – та ещё задача: </li></ul><ul><ul><li>с одной стороны всё должно уже хотя бы иногда работать в ограниченной функциональности, с другой – всякие «рюшечки» ещё не должны быть написаны </li></ul></ul><ul><ul><li>оптимально выкатывать код, когда делать больше нечего – т.е. во время простоев из-за синхронизации работы программистов </li></ul></ul><ul><ul><li>использовать кросс-тестирование (тестирует не тот, кто писал этот модуль) </li></ul></ul>Тестирование
  48. 48. Вопросы? <ul><li>Константин Андрюнин </li></ul><ul><li>e-mail: [email_address] </li></ul><ul><li>ICQ: #102100349 </li></ul><ul><li>Blog/jabber: ymi.ya.ru </li></ul>

×