'

Как сделать вычислительную инфраструктуру для большого кластера

Понравилась презентация – покажи это...





Слайд 0

Как сделать вычислительную инфраструктуру для большого кластера Евгений Кирпичёв Станислав Лагун Mirantis Inc. www.mirantis.com


Слайд 1

Введение и Архитектура Доставка задач/результатов Отладка и анализ Обобщение опыта: корректность, надежность, производительность


Слайд 2

О нас Mirantis делает проекты на заказ: Высокотехнологичные, иногда долгосрочные, для «топовых» заказчиков (Cisco, Mentor Graphics, Cadence, GE, …) В основном – масштабируемые системы, клауды, research


Слайд 3

Что мы строим Очень тяжелые вычисления (но очень параллельные) Простой API – задача = поток подзадач: CreateJob, SubmitTask, OnResult Много одновременных задач разной важности Очень разнородные вычисления: От секунд (нужна интерактивность) до дней (но не мешать чужой интерактивности) Задействовать кластер целиком Устойчивость к временным падениям компонент (и к перманентным падениям вычислительных узлов)


Слайд 4

Обычно (на суперкомпьютерах) используют: Это называется «batch scheduler»


Слайд 5

Нам не подходит Они предполагают: Планировщик ничего не знает про задачу Просто выделяет ядра Задачи монолитны «Мне надо 100 ядер» Как появится 100 ядер – запустят На 99 не запустят Есть куча сложных правил и квот Акцент на фичи, а не на эффективность Без этих предположений можно сделать эффективнее.


Слайд 6

Терминология Задача = поток задачек


Слайд 7

Становятся возможными некоторые трюки для повышения утилизации. But this margin is too small…


Слайд 8

Пример неудачной архитектуры Очевидно, single bottleneck – не масштабируется +балансировка нагрузки очень математически нестабильна Клиент 1 Клиент 2 Клиент 3 брокер


Слайд 9

Более удачная архитектура Планировщик Слушает команды о запуске-останове задач Приказывает демонам обслуживать задачи Трубы (как очереди, только шире) Доставляют задачки и ответики Вычислительные демоны на узлах Слушаются планировщика Тянут из очереди задачки, считают, публикуют ответики +клиенты +статистика +логгирование +мониторинг


Слайд 10

Пример Клиент – Планировщику: Создай задачу A, важность 30% Планировщик (выбирает несколько демонов) – демонам: Ты, ты и ты – бросайте всё и подключайтесь к трубе А. Клиент бросает задачки в трубу А Демоны считают, бросают ответики Клиент собирает ответики, бросает новые задачки и т.п.


Слайд 11

Введение и Архитектура Доставка задач/результатов Отладка и анализ Обобщение опыта: корректность, надежность, производительность


Слайд 12

Трубы Как очереди Только шире, быстрее и неупорядоченные На основе RabbitMQ Лучший продукт в своем классе (надежная доставка) Но «из коробки» сам по себе не масштабируется


Слайд 13

Надежная доставка Цикл жизни демона: Получить задачку Посчитать Отослать ответик Подтвердить получение задачки Если помрет, RabbitMQ заметит и перешлет задачку другому.


Слайд 14

Масштабирование Из коробки RabbitMQ совсем не подходит Одна очередь плохо тянет 10000 клиентов Встроенная кластеризация делает не то От нее вообще лучше отказаться (одни проблемы) Очевидное решение: несколько очередей + load balancing


Слайд 15

Масштабирование Голова задачи (подбираются демонами) задачки Голова задачи ответики (отсылаются демонами) Демон выбирает случайного кролика и всю жизнь работает с ним


Слайд 16

Трудности Маленький лимит соединений у RabbitMQ под Windows (не потянет 500-1000 машин) Решено: каждая машина подключается к кому-нибудь одному Не терять данные при крахах демонов Решено: подтверждения тасков Переустанавливать соединение при случайных разрывах связи Не терять данные при крахах RabbitMQ RabbitMQ не гарантирует безопасность данных вне транзакции! Не перегружать RabbitMQ Иначе начинаются ужасы (тормоза, разрывы связи, крахи) Поддерживать асинхронные прерывания (немедленное переключение) без потери данных Самая сложная часть Переключаться на другой RabbitMQ, если в этом кончились задачки (иначе starvation)


Слайд 17

Сохранность данных при крахах RabbitMQ Client RabbitMQ Disk fsync fsync fsync 0..3 Publish confirmations Клиент буферизует сообщения, про которые еще не известно, на диске ли они. При разрыве связи повторить «возможно-утерянные» сообщения. 4..5 6..7


Слайд 18

Не перегружать RabbitMQ Если слишком яро слать сообщения, RabbitMQ захлебнется (не успевая писать на диск) Тормоза, крахи, потеря соединения Белое – «ждем задачи» доставка тормозит, или реконнектимся


Слайд 19

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


Слайд 20

Не перегружать RabbitMQ Ограничить число сообщений «в полете» На каждого кролика? Нет, тогда один медленный будет всех тормозить А как тогда? Давать очередное сообщение случайному неперегруженному.


Слайд 21

Около 5000 ядер, 4 RabbitMQ Нет перегрузок – нет проблем


Слайд 22

Поддерживать асинхронные прерывания Иногда надо всё бросить и заняться другой задачей Прервать запущенную задачку и кинуть обратно в трубу Или прервать ожидание задачки Порвать соединения с трубами предыдущей задачи Убедиться, что все ответики и отклоненные задачки точно сохранены на диск Об этом мы узнаем из другого потока Многопоточность – это всегда ад К счастью, это почти единственное использование многопоточности Но все равно ад.


Слайд 23

Переключаться между кроликами Задаче досталось несколько демонов. 3 подключены к rmq1, 1 к rmq2 Дисбаланс Голодание Нет задачек в нашем – переключимся на другой А если он отвалился? А если в нем тоже нет? А если нигде нет? (избегать бури реконнектов) Нельзя надолго создавать дисбаланс нагрузки на кроликов Нужно найти того, где есть, как можно быстрее Решение есть, немножко хитрое, нет времени рассказать ?


Слайд 24

Как это закодировать Можно сделать лапшу, делающую все сразу Реконнекты, подтверждения доставки, переключение, балансировка, асинхронные прерывания…


Слайд 25

Как не сойти с ума Разумеется, слои*. *Паттерны Adapter, Composite etc, они же Combinator Library


Слайд 26

Слои API проще некуда: Отсыльщик: Отослать Получить/сбросить список неподтвержденных Уничтожиться (возможно, асинхронно) Слушатель: Достать сейчас (blocking + timeout) Достать потом (callback) Уничтожиться (возможно, асинхронно)


Слайд 27

Слои «При ошибке переоткрыться» «При ошибке попробовать еще раз» «При ошибке сделать то-то и то-то» «Преобразовать тип сообщения» «Слушать сразу несколько» «Балансировать отправку между несколькими» «Игнорировать неподтвержденные при закрытии»


Слайд 28

Например По числу кроликов задачки ответики


Слайд 29

Введение и Архитектура Доставка задач/результатов Отладка и анализ Обобщение опыта: корректность, надежность, производительность


Слайд 30

Отладка и анализ Дебаггер – не вариант (только для локальных тестов) Где и когда произойдет ошибка – заранее неизвестно Post mortem отладка по логам And you have to be pretty damn good at it Это не логи вебсервера, где все реквесты независимы Несколько взаимодействующих, иногда многопоточных подсистем Проблемы с корректностью – недетерминированы Проблемы с производительностью – не локальны Логов, по нашим меркам, дофига (тысячи важных сообщений в сек.)


Слайд 31

Пара фокусов в рукаве Мощный логгер Глобальная ось времени (точнее, чем NTP) Тянет сотни тысяч сообщений в секунду от тысяч клиентов http://code.google.com/p/greg – опенсорс-версия Ставим 1шт. на кластер, получаем точную глобальную картину (без мучений со специальным сбором-слиянием логов) GNU textutils + awk (пока хватает, MapReduce не юзаем) timeplotters – две специальных рисовалки http://jkff.info/software/timeplotters/


Слайд 32

Мы рисуем http://jkff.info/software/timeplotters/


Слайд 33

http://jkff.info/software/timeplotters/


Слайд 34

Что для этого нужно? Очень подробные логи. Еще об этом – позже.


Слайд 35

Введение и Архитектура Доставка задач/результатов Отладка и анализ Обобщение опыта: корректность, надежность, производительность


Слайд 36

Корректность: Главный принцип Как писать правильный код?


Слайд 37

Корректность: Главный принцип Код точно неправильный. Как быть?


Слайд 38

Как быть? Быть скромнее Дать себе шанс найти ошибку Минимизировать «ядро корректности» Минимизировать распространение ошибки Избегать опасных приемов


Слайд 39

Быть скромнее Не думать «ничего, отладим» Это будет стоить вам увеличения времени разработки в разы Не лепить все фичи сразу: Каждый раз приходится разломать и отлаживать по отдельности Безжалостно уничтожать некритичные фичи Единственный их эффект – усложнение отладки


Слайд 40

Цитаты в тему «Write the simplest thing that could possibly work» Ward Cunningham «Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it» Brian Kernighan


Слайд 41

Дать себе шанс найти ошибку Максимально подробные логи Не бывает «слишком много логов» Не бывает «от логгирования код некрасивый»


Слайд 42

Минимизировать «ядро корректности» Часть, от корректности которой зависит работоспособность системы. Веб-сервер: Неправильное вычисление в процессе обработки запроса ? неправильный ответ Дедлок в пуле сокетов ? виснет весь сервер


Слайд 43

Минимизировать распространение ошибки Расставлять «барьеры» До барьера – будь что будет После барьера верны некоторые свойства Барьер должен быть очень надежен


Слайд 44

Барьеры Уничтожение процесса (выполнение действия в отдельном процессе) Защищает от утечек ресурсов внутри процесса Периодический перезапуск системы Защищает от неограниченно долгих зависаний Закрытие соединения с очередью В худшем случае (неподтвержденная)задача будет сдублирована Eventual consistency negative feedback, периодическая сверка желаемого и действительного


Слайд 45

Избегать опасных приемов Изменяемое состояние Многопоточность Блокирование, синхронизация Обратная связь Редко выполняющийся код


Слайд 46

Введение и Архитектура Доставка задач/результатов Отладка и анализ Обобщение опыта: корректность, надежность, производительность


Слайд 47

Надежность Всё перезапускаемо и готово к перезапуску остальных Asynchronous one-way messaging (противоположность RPC) Явно формулировать переход ответственности за целостность данных Все компоненты готовы к дублям и потерям данных Eventual consistency


Слайд 48

Перезапускаемость Если она есть: Можно перезапустить оборзевший процесс Можно навсегда забыть о редких крахах Можно перезапускать процесс периодически и забыть навсегда об утечках и зависаниях Если ее нет: Надо вылизывать код, пока не исчезнут самые маловероятные крахи и утечки Если крах не по вашей вине (ОС, библиотека...) – это все равно ваши проблемы.


Слайд 49

Asynchronous, one-way messaging Противоположность RPC, прямое следствие из перезапускаемости. Лучше возложить ответственность за доставку сообщений на софт, который хорошо умеет это делать. Или использовать ненадежный транспорт (UDP).


Слайд 50

Eventual consistency Стремление к согласованности


Слайд 51

Eventual consistency Client RabbitMQ Disk fsync fsync fsync 0..3 Publish confirmations 4..5 6..7 Клиент и кролик постепенно согласуют знание о том, какие данные надежно сохранены


Слайд 52

Eventual consistency Master Slave Хозяин и раб постепенно согласуют представление о том, чем рабу надо заниматься «Займись B» «Занимаюсь A» «Займись B» «Занимаюсь B»


Слайд 53

Введение и Архитектура Доставка задач/результатов Отладка и анализ Обобщение опыта: корректность, надежность, производительность


Слайд 54

Производительность Несколько аспектов: Стабильность под нагрузкой Пропускная способность Задержка


Слайд 55

Главное Ресурсы конечны


Слайд 56

Какие ресурсы конечны Вот что кончалось у нас: Соединения с RabbitMQ Erlang-процессы в RabbitMQ Cинхронные AMQP-операции / сек. (e.g. queue.declare) с RabbitMQ Установленные соединения / сек. с RabbitMQ Установленные соединения / сек. с логгером Внутренние буферы сообщений в логгере Место в пуле потоков (медленно разгребался) Одновременные RPC-вызовы Место на диске CPU и диск одной машины, куда погрузили два сервиса сразу Успешно проходящие UDP-пакеты по нагруженному каналу Транзакции RabbitMQ в секунду (чего уж там – в минуту) Терпение при анализе больших логов Память у инструментов рисования логов ...


Слайд 57

Мораль Планируйте потребление ресурсов Особенно таких, потребление которых растет с масштабом Особенно централизованных Центральные одноэкземплярные сервисы Сеть Учитывайте паттерн загрузки! Его бывает трудно предсказать Наивные бенчмарки нерепрезентативны


Слайд 58

Пропускная способность Избегайте обратной связи Из-за нее задержка начинает уменьшать пропускную способность Задержку оптимизировать гораздо труднее


Слайд 59

Задержка Прогнозируйте и измеряйте Уменьшайте длину цепи задержки Избегайте компонентов с непредсказуемой задержкой Избегайте централизованных компонентов на пути запроса Не делите ресурсы между throughput-sensitive и latency-sensitive компонентами Плохая идея использовать один и тот же RabbitMQ и для команд, и для задач Рано или поздно придется управлять приоритетами запросов/действий вручную Понадобятся не просто очереди, а приоритетные очереди


×

HTML:





Ссылка: