Русский
Русский
English
Статистика
Реклама

Iops

Гиперконвергентная система AERODISK vAIR v2. Часть 1. Система виртуализации АИСТ

14.04.2021 06:04:04 | Автор: admin


Всем привет. Этой статьей мы начинаем знакомить вас с новой версией российской гиперконвергентной системы AERODISK vAIR v2, в частности, со встроенным гипервизором АИСТ, который сейчас получил возможность работать автономно от vAIR, используя внешние СХД.


Изначально мы хотели рассказать о функциональности новой версии vAIR в одной статье, но материала получилось очень много, и мы встали перед выбором: либо сократить материал, либо разбить его на три части. Мы выбрали второй вариант и разбили материал следующим образом:


  • Управление кластером и гипервизор АИСТ
  • Файловая система ARDFS
  • Аппаратные платформы, лицензирование и поддержка

Соответственно, в первой части мы расскажем о функциях управления vAIR v2 и более подробно о подсистеме виртуализации. Но сначала хотелось бы сказать пару слов об архитектурных изменениях в версии vAIR v2.


Коротко об архитектуре. Основные отличия между первой и второй версией


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


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



На уровне большой картинки на данный момент архитектура vAIR v2 выглядит следующим образом:



Ну а теперь переходим к деталям.


Косметические изменения


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


Стандартный блок данных, которым оперирует ARDFS, изменился с 4МБ до 64 МБ. Сделано это было также с целью увеличения производительности ввода-вывода.


Ещё одним маленьким, но приятным бонусом, который получился в результате оптимизации ARDFS и ConfigDB, стало снижение минимальных системных требований по количеству нод в кластере. Первая версия vAIR требовала не менее четырех нод, во второй-же версии начинать можно с трёх нод. Мелочь, но тоже приятно.


АИСТ покинул гнездо


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


Для справки: и АИСТ, и vAIR как два отдельных продукта прошли всю необходимую экспертизу регуляторов и, соответственно, добавлены во всех необходимые гос. реестры Минцифры и Роспатента, чтобы по-честному считаться российским ПО.


Чтобы не было путаницы, поясним. По факту АИСТ и vAIR не являются разными продуктами. Гипервизор АИСТ это составная и обязательная часть гиперконвергентной системы vAIR, при этом АИСТ может использоваться в качестве самостоятельного решения, а также АИСТ может всегда быть обновлен до полноценного vAIR-а.


Данное архитектурное изменение не только позволяет импортозаместить зарубежную виртуализацию на российских предприятиях, но и открывает ряд крайне полезных сценариев использования vAIR. Разберем их:


Сценарий 1. Просто гиперконвергент


Тут все просто. АИСТ используется как составная часть vAIR и работает с хранилищем ARDFS. Это то, что было в первой версии, и остается сейчас.



Виртуальные машины, сеть и хранилище работают в рамках одной отказоустойчивой аппаратной платформы (3 ноды+).


Сценарий 2. Просто виртуализация


Классическая серверная виртуализация. На локальные диски физических серверов устанавливается АИСТ, к АИСТу пригоняются сторонние СХД по файловым или блочным протоколам, и на базе этих СХД хранятся виртуальные машины.



При этом в этой схеме всегда остается возможность добавить локальных дисков во все физические серверы, объединить их быстрым (от 10 Гбит/сек) интерконнектом и обновить лицензию АИСТа до vAIR, получив в итоге гибридный сценарий (см. ниже).


Сценарий 3. Гибридный сценарий


Самый интересный сценарий. Мы одновременно с гиперконвергентом используем в качестве хранилища виртуальных машин сторонние СХД (например ENGINE или ВОСТОК :-)). Полезным является то, что к любой виртуалке, которая хранится на ARDFS, мы можем легко прицепить дополнительные виртуальные диски с СХД. И наоборот, к любой виртуалке, которая лежит на СХД, мы можем прицепить виртуальные диски с ARDFS. Это открывает очень много возможностей, начиная с задач постепенной и бесшовной миграции инфраструктуры между разными хранилищами, заканчивая полезным использованием старых СХД и серверов хранения, которые и выкинуть жалко, и подарить некому.



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



Обзор функционала. Что нового и для чего


Функции управления


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


Предусмотрен сценарий развертывания управляющей виртуальной машины (УВМ), которая через RestfulAPI может осуществлять полноценное управление всем кластером.


Кстати RestfulAPI, как понятно выше, есть, он описан и работает (по нему будет отдельная статья). Его спокойно можно использовать для автоматизации операций и интеграции со смежными системами. К примеру, уже сейчас есть интеграция (и, кстати, есть внедрение в продуктив) с российским VDI-решением Термидеск, как раз реализованная на базе нашего API. Плюс ещё несколько продуктов вендоров-партнеров на подходе.


Для управления виртуальными машинами изнутри гостевой ОС используется на выбор два протокола: VNC (по умолчанию) или Spice. На уровне отдельных ВМ администратор может задавать разные варианты подключений.



Сам интерфейс разбит на несколько логических частей.


1) Основная область управления, в которой выполняются почти все операции



2) Основное меню, которое выдвигается наведением курсора



3) Панель действий, на которой отображаются доступные для выбранного объекта действия.



4) Панель задач, которая показывает, какие задачи выполняются или были выполнены над выбранным объектом, вызывается выбором объекта и последующим кликом по кнопке задачи.



5) Ну и, наконец, информационная панель, которая показывает количество актуальных ошибок (красные) и выполняемых в данный момент действий (синие).



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



Лирическое отступление: когда я эту функцию показал моему старому товарищу, который является тру-админом (то есть он админил системы в те славные времена, когда систем ещё не существовало) он воскликнул:
Вы нормальные там??!!! Нельзя админить серьезные системы через мобилу!!!
Хочу отметить, что во втором своём высказывании он, безусловно прав, лазить по серьезным кластерам через мобилку опасно, можно ткнуть не туда и всё как обычно упадёт, но всегда есть НО
Я напомнил ему ситуацию, в которую он попал несколько лет назад, когда потратил примерно 40 минут времени и 10 тонн мата на то, чтобы перезагрузить пару зависших виртуалок на известном гипервизоре, используя свой смартфон. Ноутбука у него с собой не было, а его заказчик с паром из ушей требовал устранить проблему здесь и сейчас.
Вспомнив об этом случае, мой товарищ тру-админ перестал сомневаться в нашей нормальности :-).

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


Гипервизор АИСТ


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


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



Если параметр HAVM активен, то в случае отказа ноды кластера, ВМ автоматически перезапуститься на другой ноде.


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



Для защиты данных на уровне ВМ, а также для большей гибкости администрирования предусмотрены мгновенные снимки и клоны (которые можно превратить в шаблоны ВМ соответственно). Важной доработкой и одновременно крайне большой радостью является то, что снэпшоты делаются на горячую (при работающей ВМ) и полностью поддерживают консистентность файловых систем гостевых ОС (Linux, Solaris, Windows, BSD) и ряда поддерживаемых СУБД (пока только PostgreSQL и MySQL). При этом с помощью RestfulAPI никто не мешает реализовать консистентные снимки для других систем внутри гостевой ОС самостоятельно.


Для внешнего хранения из коробки поддерживается NFS, то есть хранить виртуалки можно на распределенном хранилище ARDFS (доступно в vAIR) или на внешней СХД по протоколу NFS. Опционально предусмотрена поддержка блочных внешних СХД по протоколам iSCSI и FC.


Миграция виртуальных машин со сторонних гипервизоров


Миграция, причем неважно откуда и куда, всегда стоит особняком во всей ИТ-жизни. За время полутора лет эксплуатации нашими заказчиками первой версии vAIR они (и мы автоматически) регулярно сталкивались с проблемами миграции виртуальных машин со сторонних гипервизоров в АИСТ. Штатный конвертер KVM штука хорошая, но крайне капризная. Поэтому в vAIR v2 (и в АИСТе соответственно) мы предусмотрели человеческий конвертер ВМ из VMware/Hyper-V прямо в интерфейсе vAIR/АИСТ.



Для конвертации администратор выбирает шару NFS (пока только NFS), где лежат файлы виртуальных машин VMware или Hyper-V. Далее vAIR сам сканирует шару на наличие нужных ему файлов и формирует доступный список для миграции. Далее выбираем целевой пул ARDFS (или внешнюю СХД), то есть куда будем конвертировать, выбираем нужные файлы ВМ (можно несколько, они будут конвертироваться по очереди) запускаем и идём пить пиво.



Когда пиво выпито, новые, уже сконвертированные, виртуалки ждут нас уже внутри vAIR-а в выключенном состоянии.


Мониторинг и логирование


Функции мониторинга реализованы как локально, так и удаленно. Администратор может работать со счетчиками утилизации ресурсов CPU, RAM, сетевых интерфейсов и подсистемой ввода-вывода (IOPS, MB/s, latency), как на уровне отдельных нод, так и на уровне кластера в целом.



Всё то же самое доступно и для удаленной системы мониторинга на базе Grafana.



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




Кроме описанных выше возможностей гипервизор АИСТ позволяет выполнять функционал, который мы считаем must have, поэтому сильно его разрисовывать не будем, а просто перечислим:


  • Обновление ПО без остановки и миграции виртуальных машин
  • Живая миграция ВМ, а в ближайшем будущем с возможностью динамичного распределения ресурсов (а-ля DRS)
  • Распределённые виртуальные коммутаторы с поддержкой VLAN-ов
  • Расширение кластера без остановки виртуальных машин
  • Автоподдержка (автоматическое оповещение производителя и заведение тикетов в тех. поддержку, при согласии заказчика, само собой)
  • Метрокластер (отдельная большая функция, которой мы посветим позже отдельную статью)

Детально ознакомиться с особенностями функционала можно в технической документации, которая есть у нас на сайте:


https://aerodisk.ru/upload/Datasheet_AIST_final_11042021.pdf


В завершение первой части


В процессе разработки vAIR и АИСТ собственных решений в области виртуализации многие наши доверенные партнеры (которые допущены к раннему доступу), глядя на это, утверждали, что это плохая идея, потому что ВМварь и Нутаникс не догнать, они слишком крутые и великие, у них тысячи программистов по всей планете, бороды длиннее и свитера в два раза толще.


На подобные утверждения мы всегда задавали вопрос.


А эти компании сразу появились на свет с тысячей бородатых разрабов в толстых свитерах?

ИЛИ другой вариант


А вы когда родились вам сразу было 35 лет, у вас была машина, семья, дача, работа и образование? Это в комплекте вам врачи в роддоме выдавали?

В продолжении этой мысли позволим себе процитировать нашу же старую статью:


притча на эту тему.


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

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


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


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


На этом мы завершаем первую часть цикла статей про vAIR v2. В следующей статье подробно расскажем о функционале файловой системы ARDFS.


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


Голосование доступно тут, на Хабре, а также в нашем телеграм-чате https://t.me/aerodisk


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

Подробнее..

Что нам стоит Resource Governor настроить

04.10.2020 22:08:33 | Автор: admin

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

И, с одной стороны, в этом может не быть особой проблемы - да, серверу тяжело, да, это неприятно, но ведь, господи, ну сформируется ваш отчёт не за 15, а за 45 секунд - делов-то, вы же видите - вас много, а сервер один, нужно просто немножко подождать. Но что, если при всём при этом, есть какие-то бизнес-процессы, которые не могут ждать? Что если при такой нагрузке продажа товара становится настолько медленной, что покупатели отказываются от покупки?

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

И иногда их и правда можно разделить - с помощью Resource Governor.

Сразу несколько примечаний:

  1. Resource Governor доступен только в Enterprise Edition. Если у вас любая другая редакция (ну ещё Developer, но он же у вас не в проде, да?) - к сожалению, использовать его вы не сможете.

  2. Тут мы не говорим о таких важных вещах, как оптимизация запросов, структур хранения данных, разнесении нагрузки на разные реплики, секционировании, шардировании.

  3. Мы говорим только о том, что такое Resource Governor, как и для чего он может быть полезен, когда бесполезен, чем опасен, как его настроить, что можно мониторить и как его обойти и выключить (если вдруг что).

  4. В один пост я пытаюсь засунуть достаточно много информации и где-то сознательно, а где-то несознательно, будут допущены упрощения.

  5. Сдуру можно сломать всё что угодно, всё что вы делаете, вы делаете на свой страх и риск.

Прежде чем начать разговор о Resource Governor, на всякий случай скажу. что кроме CPU запросы используют диск и оперативную память - SQL Server читает данные с диска и записывает их в buffer pool (но Resource Governor никаким образом не позволяет влиять на buffer pool), откуда их уже "забирает" CPU. Память, кроме того, чтобы использоваться в качестве buffer pool, нужна ещё для сортировок, джойнов и всяких таких вещей (можно немного глянуть тут, где я писал про использование varchar(max)).

И вот, Resource Governor позволяет делать три вещи:

  1. Создавать пулы ресурсов (CPU, RAM, IOPS) - ограничивать ресурсы (или обеспечивать их необходимый минимум), доступные пользовательским сессиям.

  2. Создавать группы рабочей нагрузки (workload group), привязанные к пулам, для более эффективного управления ресурсами внутри пула.

  3. Определять к какой группе (и, соответственно, пулу) будет относиться пользовательская сессия.

Почему рисунок такой отстойный?

потому что умею (да и то не очень) только в paint и немножко в draw.io.

я старалсяя старался

Если вы посмотрите в dmv sys.dm_exec_sessions, в нём есть столбец group_id - это идентификатор группы нагрузки resource governor, именно при установке соединения (точнее, после авторизации) и до конца жизни сессии определяется к какой группе (и, соответственно, пулу) она будет относиться.

По-умолчанию, у нас есть два пула - internal и default и две группы - internal и default (не знаю почему я не дорисовал Internal group). Собственно, по названию, должно быть понятно - internal - это то, что используют процессы самого SQL Server - мы не можем менять ни группу, ни пул - и не надо. default - это то, куда, по-умолчанию, попадают все пользовательские сессии.

Тут есть одна важная вещь, про которую нужно обязательно сказать. В SQL Server есть такая штука как Dedicated Admin Connection (DAC) - крайне, крайне желательно убедиться, что вы можете его использовать, поскольку при подключении через DAC, админская сессия попадает в internal pool. Даже если что-то пошло совсем не так как ожидалось, через DAC можно будет подключиться и что-то поправить. Без DAC, если будут проблемы с подключениями из-за Resource Governor, вероятно, придётся запускать сервер в однопользовательском режиме, за что остальные пользователи, я думаю, спасибо не скажут. После того, как вы включили возможность его использовать не только локально - научитесь его использовать при подключении через SSMS.


Теперь, когда введение можно считать законченным, перейдём непосредственно к Resource Governor.

Чтобы создать пул мы используем команду CREATE RESOURCE POOL (MSDN):

CREATE RESOURCE POOL pool_name  [ WITH      (          [ MIN_CPU_PERCENT = value ]          [ [ , ] MAX_CPU_PERCENT = value ]           [ [ , ] CAP_CPU_PERCENT = value ]           [ [ , ] AFFINITY {SCHEDULER =                    AUTO                 | ( <scheduler_range_spec> )                   | NUMANODE = ( <NUMA_node_range_spec> )                } ]           [ [ , ] MIN_MEMORY_PERCENT = value ]          [ [ , ] MAX_MEMORY_PERCENT = value ]          [ [ , ] MIN_IOPS_PER_VOLUME = value ]          [ [ , ] MAX_IOPS_PER_VOLUME = value ]      )   ]  [;]    <scheduler_range_spec> ::=  { SCHED_ID | SCHED_ID TO SCHED_ID }[,...n]    <NUMA_node_range_spec> ::=  { NUMA_node_ID | NUMA_node_ID TO NUMA_node_ID }[,...n]  

И пройдёмся по параметрам:

  1. MIN_CPU_PERCENT - если процессор загружен на 100%, не меньше этого процента будет использоваться на выполнение запросов тех сессий, которые попали в этот пул. ВАЖНО: если им в этом пуле столько и не надо, "недоиспользованный" CPU, будет доступен другим пулам, если нужен им.

  2. MAX_CPU_PERCENT - если процессор загружен на 100%, запросы сессий из этого пула, суммарно, не будут использовать больше указанного процента. ВАЖНО: Это не жёсткое ограничение, если запросам из пула нужно будет больше, а запросам из других пулов будет достаточно ресурсов, запросы из этого пула БУДУТ использовать больше.

  3. CAP_CPU_PERCENT - а вот это жёсткое ограничение. Запросы сессий из этого пула не смогут использовать больше, чем указано, даже если процессор больше вообще никто не использует.

  4. AFFINITY - позволяет привязать пул ЛИБО к конкретному(-ым) шедулерам (условно, ядрам процессора), ЛИБО к конретной(-ым) NUMA-нодам

  5. MIN/MAX_MEMORY_PERCENT - задают (в процентах, понятно) сколько памяти из всей памяти может быть выделено запросам из пула. Ещё раз обращаю внимание - эта настройка никак не влияет на buffer pool, мы им не управляем. Это про memory grants.

  6. MIN/MAX_IOPS_PER_VOLUME - задаёт минимальное и максимальное КОЛИЧЕСТВО IO операций (без деления на чтение и запись, только общее), доступное запросам из пула.

Отдельно нужно добавить про MIN_CPU_PERCENT - сумма всех MIN_CPU_PERCENT по всем пулам не может превышать 100%. В идеале, я бы и до 100% не стал доводить, оставив хоть что-то internal и default пулам.

Чтобы создать группу, используем команду CREATE WORKLOAD GROUP (MSDN):

CREATE WORKLOAD GROUP group_name[ WITH    ( [ IMPORTANCE = { LOW | MEDIUM | HIGH } ]      [ [ , ] REQUEST_MAX_MEMORY_GRANT_PERCENT = value ]      [ [ , ] REQUEST_MAX_CPU_TIME_SEC = value ]      [ [ , ] REQUEST_MEMORY_GRANT_TIMEOUT_SEC = value ]      [ [ , ] MAX_DOP = value ]      [ [ , ] GROUP_MAX_REQUESTS = value ] ) ][ USING {    [ pool_name | "default" ]    [ [ , ] EXTERNAL external_pool_name | "default" ] ]    } ][ ; ]

Параметры:

  1. IMPORTANCE - задаёт "приоритет" сессии в группе. Разные группы могут относиться к одному пулу, соответственно, мы можем сказать, что сессии вот в этой группе "более важны", чем в другой. Это не значит, что "более важные" сессии будут выполняться, а "менее важные" ждать - просто больше ресурсов из пула будет доступно "более важным" сессиям.

  2. REQUEST_MAX_MEMORY_GRANT_PERCENT - по умолчанию 25%, задаёт какое количество из максимальной памяти пула сессия может получить в своё распоряжение. В общем случае, если ну никак не получается выделить столько памяти - запрос упадёт с ошибкой.

  3. REQUEST_MAX_CPU_TIME_SEC - если запросу потребовалось больше времени, чем тут указано, он не прервётся, но будет сгенерировано событие cpu_threshold_exceeded, которое можно отловить с помощью Extended Events. Начиная с определённого CU для SQL Server 2016/2017, появился trace-флаг, включение которого приведёт к тому, что запрос будет прерван, если CPU time превысит указанное значение.

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

  5. MAX_DOP - указывает допустимую степень параллелизма. Это значение "важнее", чем указанное в настройках сервера, БД, или в хинте в запросе. Если у вас везде 1, а тут 4 - запросы из этой группы могут выполняться с MAX DOP = 4.

  6. GROUP_MAX_REQUESTS - сколько запросов могут одновременно выполняться. Если хочет выполняться больше, чем указано, придётся подождать. Попробуем ещё с этим поиграться.

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

Тут, к сожалению, всё не очень просто. Ну, точнее, просто, но не всем подойдёт (привет 1С). Функция классификации - это обычная scalar UDF, созданная в БД master. К ней есть два требования - она должна быть объявлена как SCHEMABINDING и должна возвращать значение типа SYSNAME. Нужно понимать, что выполняется эта функция сразу после логина и выполняется для каждого соединения, соответственно, она должна выполняться очень-очень-ОЧЕНЬ быстро, иначе станет очень узким местом и вам придётся использовать DAC, чтобы её заменить.

Ещё немного про функцию классификации

В MSDN использован пример с lookup-таблицей и сразу дана куча оговорок, что нужно выполнять к ней обращения с NOLOCK или под SNAPSHOT IL, но вообще, вроде как, lookup-таблицы в функции классификации - это далеко не best practice и потенциально достаточно опасное мероприятие.

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

Для отключения Resource Governor необходимо выполнить команду:

ALTER RESOURCE GOVERNOR DISABLE;

Вот теперь введение точно можно считать законченным и можно создавать пулы/группы/функцию и проверять/мониторить это всё.

Начнём с CPU и создадим пулы:

CREATE RESOURCE POOL [pool1]WITH (    MIN_CPU_PERCENT = 15,    MAX_CPU_PERCENT = 15,    CAP_CPU_PERCENT = 20);CREATE RESOURCE POOL [pool2]WITH (    MIN_CPU_PERCENT = 50,    MAX_CPU_PERCENT = 90);

Первый пул, в случае "борьбы" за процессор сможет забирать не менее и не более 15 процентов, но из-за CAP_CPU_PERCENT не сможет использовать больше 20 процентов CPU, даже если никакой "борьбы" нет. Второй пул, в случае "борьбы" сможет взять не менее 50 и не более 90 процентов, при этом, если никому больше процессор не нужен будет - сможет взять все 100.

Создаю группы нагрузки:

CREATE WORKLOAD GROUP [pool1_group1]WITH (    IMPORTANCE = HIGH,    REQUEST_MAX_CPU_TIME_SEC = 5,    MAX_DOP = 2)USING [pool1];CREATE WORKLOAD GROUP [pool2_group1]WITH (    IMPORTANCE = HIGH)USING [pool2];CREATE WORKLOAD GROUP [pool2_group2]WITH (    IMPORTANCE = MEDIUM)USING [pool2];CREATE WORKLOAD GROUP [pool2_group3]WITH (    IMPORTANCE = LOW,    GROUP_MAX_REQUESTS = 1 )USING [pool2];

В первом пуле я создаю всего одну группу нагрузки, указываю, что сессии из этой группы смогут рассчитывать только на 2 ядра (на уровне сервера стоит MAXDOP = 4), и что максимальная длительность запроса составляет 5 секунд. Важность запросов из группы я объявляю как высокую, но, поскольку группа в пуле одна, эта важность не повлияет ни на что.

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

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

USE [StackOverflow2013]GOCREATE LOGIN p1g1 WITH PASSWORD = N'1', CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF;CREATE LOGIN p2g1 WITH PASSWORD = N'1', CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF;CREATE LOGIN p2g2 WITH PASSWORD = N'1', CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF;CREATE LOGIN p2g3 WITH PASSWORD = N'1', CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF;CREATE USER p1g1 FOR LOGIN p1g1;CREATE USER p2g1 FOR LOGIN p2g1;CREATE USER p2g2 FOR LOGIN p2g2;CREATE USER p2g3 FOR LOGIN p2g3; EXEC sp_addrolemember N'db_owner', N'p1g1';EXEC sp_addrolemember N'db_owner', N'p2g1';EXEC sp_addrolemember N'db_owner', N'p2g2';EXEC sp_addrolemember N'db_owner', N'p2g3';

А вот и функция классификации:

USE [master]GOCREATE FUNCTION fnClassify()RETURNS SYSNAME WITH SCHEMABINDINGASBEGIN    RETURN         CASE ORIGINAL_LOGIN()             WHEN 'p1g1' THEN 'pool1_group1'            WHEN 'p2g1' THEN 'pool2_group1'            WHEN 'p2g2' THEN 'pool2_group2'            WHEN 'p2g3' THEN 'pool2_group3'        ELSE 'default' END;END;

И сразу проверим, куда эта функция отнесёт нас:

SELECT master.dbo.fnClassify();
В моём случае - default, но

если функция вернёт неверное имя группы или NULL - это достаточно безопасно - в случае любых сомнений у Resource Governor куда отнести сессию, сессия будет отнесена в группу default.

Последнее, что нужно сделать - указать Resource Governor созданную функцию классификации и применить изменения:

ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = dbo.fnClassify);  ALTER RESOURCE GOVERNOR RECONFIGURE;  

Теперь можно логиниться с созданными учётными данными и посмотреть, что из этого вышло.

SELECT     s.session_id,     s.login_name,     wg.group_id,    wg.name AS workload_group_name,    wg.pool_id,    rp.name AS pool_nameFROM sys.dm_exec_sessions sJOIN sys.dm_resource_governor_workload_groups wg ON s.group_id = wg.group_idJOIN sys.dm_resource_governor_resource_pools rp ON wg.pool_id = rp.pool_idWHERE s.session_id >= 50
в dmv resource governor есть ещё много интересной информациив dmv resource governor есть ещё много интересной информации

Мы видим, что все новые пользователи благополучно "расползлись" по назначенным группам. Object Explorer и моё основное соединение остались в группе и пуле default.

Теперь попробуем нагрузить процессор и помониторить - работают ли указанные при настройке ограничения. В perfmon есть две группы счётчиков: SQLServer: Workload Group Stats и SQL Server: Resource Pool Stats. Обратите внимание, что доступные счётчики зависят от версии вашего SQL Server.

В сессии p1g1 запускаю запрос, который не делает ничего полезного, только грузит процессор, причём хинтом указываю, что он может использовать все 8 ядер моего лютого i5-8250u, если ему это нужно

USE StackOverflow2013;GOSELECT SUM (CAST (VoteTypeId AS decimal(12,2))) / AVG (CAST (VoteTypeId AS decimal(14,4)))FROM dbo.VotesOPTION (MAXDOP 8);GO

В то же время, в perfmon смотрим на показания SQLServer: Workload Group Stats: CPU Usage% и CPU Delayed % по группе pool1_group1:

CPU Usage% упёрся в CAP_CPU_PERCENT = 20, Resource Governor не даёт использовать больше CPU моему запросу, а сам запрос может использовать только 2 ядра, вместо положенных 8, из-за того, что при создании группы нагрузки, я ограничил запросы из группы именно этим значением. CPU Delayed %, в свою очередь показывает, что пул хотел бы получить в своё распоряжение ещё около 5% процессорного времени, но Resource Governor строго его ограничил.

Посмотрим тот же запрос и те же счётчики, но выполненный от имени p2g3, пользователя, который входит в группу с наименьшим приоритетом (IMPORTANCE = LOW) во втором пуле.

Поскольку это был единственный запрос, который выполнялся в этот момент, запросу ничего не мешало использовать все ядра и все 100% CPU. Правда CPU Delayed там где-то подпрыгивал аж до 0,483%, но это связано с какими-то внутренними процессами из Internal pool, которым тоже нужен был CPU. А что будет, если запустить, параллельно ещё что-нибудь тяжелое в том же пуле (pool2), но из другой группы нагрузки, с более высоким приоритетом?

Добавляю в запрос ещё немного вычислений и запускаю от имени p2g1 (IMPORTANCE = HIGH) и через пару секунд тот же самый запрос от имени p2g3 (IMPORTANCE = LOW):

USE StackOverflow2013;GOSELECT SUM (CAST (VoteTypeId AS decimal(12,2))) / AVG (CAST (VoteTypeId AS decimal(14,4))) * AVG (CAST (PostId AS decimal(19,4)))FROM dbo.VotesOPTION (MAXDOP 8);GO

Тут картинка становится интереснее. Пока запрос был один, запрос из группы с высоким приоритетом забирал весь доступный CPU, но как только появился запрос из группы с низким приоритетом - пришлось делиться. От щедрот, как видно на графике, было выдано 10% CPU, соответственно, пока запросы выполнялись параллельно, запрос из группы с низким приоритетом мог использовать только 10% CPU, и только когда первый запрос завершился, он смог использовать все 100%.

Теперь я параллельно запущу тот же самый запрос из всех трёх групп, привязанных к пулу 2, чтобы посмотреть как будет разруливаться такая ситуация с приоритетами. На графике оставлю только CPU Usage разных групп.

Сначала запрос был запущен от имени пользователя с низким приоритетом, потом со средним и в конце - с высоким:

Видно, что сначала группе с низким приоритетом было доступно 100%. Как только подключился запрос из группы со средним приоритетом - он забрал себе 70-75%, а низкому приоритету осталось 25-30%. Когда пришёл босс, он забрал себе около 65-70% процессорного времени, средний оставил себе ещё 22,5-25%, а низкому приоритету осталось всего 7.5-10% процессорного времени.

Как вы видите, сначала завершился процесс с высоким приоритетом, затем со средним и после них - с высоким. И это не смотря на то, что выполнять запросы они начинали в обратном порядке!

Теперь, когда мы увидели как взаимодействуют процессы из разных групп внутри одного пула, давайте посмотрим как будут взаимодействовать процессы из разных пулов. Тот же самый запрос я запущу в трёх сессиях: от имени пользователя p1g1 из пула 1 и от имени пользователей p2g1 и p2g3 из пула 2, с высоким и низким приоритетом. Во-первых, я хочу посмотреть как будет делиться CPU между пулами, а во вторых - как будет делиться CPU между группами с разными приоритетами, когда им, параллельно, приходится делить CPU с другим пулом. Ещё раз обращаю внимание, что "приоритеты" (IMPORTANCE) - не влияют на приоритет пула, они влияют на "важность" запросов только внутри того пула, к которому привязана группа.

сверху - использование CPU разными пулами; снизу - использование CPU внутри второго пуласверху - использование CPU разными пулами; снизу - использование CPU внутри второго пула

Верхний график - это использование CPU разными пулами (SQL Server: Resource Pool Stats: CPU Usage %). Сначала я запустил запрос от имени пользователя p1g1, привязанного к пулу с жёстко ограниченным CPU. Он сразу забрал свои максимально-максимально допустимые 20%, но как только подоспели запросы из второго пула, пришлось часть ресурсов отдать.

Напоминаю, что в первом пуле у нас стоит MAX_CPU_PERCENT = 15, а во втором пуле MAX_CPU_PERCENT = 90. Суммарно, получается, больше 100%, соответственно в дело вступают минимальные проценты. У первого пула минимум = 15%, у второго - 50%. Поэтому первый пул может рассчитывать на все свои 15%, а второй получает оставшиеся 85%.

Нижний график - это делёж процессора разными группами второго пула. Сначала был запущен запрос из группы с низким приоритетом и забрал все максимально доступные пулу 85%, но потом пришёл процесс с высоким приоритетом и забрал, примерно, 75% из них. Когда запрос с максимальным приоритетом завершился, запрос с минимальным приоритетом получил весь доступный пулу CPU обратно и тоже быстро завершился, после чего первый пул получил свои дополнительные 5% и дожал выполнение.

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

SELECT     s.session_id,    s.status,    r.task_address,    r.scheduler_idFROM sys.dm_exec_sessions s LEFT JOIN sys.dm_exec_requests r ON s.session_id = r.session_idWHERE s.login_name = N'p2g3';

Обе сессии в состоянии running, но запрос (request) и соответствующий таск был создан только для одной и только ей доступен шедулер (сверху). Только после того, как запрос от первой сессии выполнился, начал выполняться второй (снизу).


Теперь попробуем поиграться с IO. Для начала отключим Resource Governor, удалим пулы и группы:

USE [master];GOALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = NULL);  ALTER RESOURCE GOVERNOR DISABLE; DROP WORKLOAD GROUP [pool1_group1];DROP WORKLOAD GROUP [pool2_group1];DROP WORKLOAD GROUP [pool2_group2];DROP WORKLOAD GROUP [pool2_group3];DROP RESOURCE POOL [pool1];DROP RESOURCE POOL [pool2];

Для начала нужно прикинуть сколько IO вообще способен выдать мой жёсткий диск. Хочу отметить, что оценка пропускной способности дисковой подсистемы - это достаточно нетривиальная задача, которую я тут решать не собираюсь. Мне нужно знать только сколько IOPS на чтение сможет выдать мой диск, если я его слегка подгружу на чтение, чтобы показать как работает Resource Governor и не более.

Используем для этого старый-добрый счётчик Физический диск: Обращений к диску/с, параллельно запустив что-то, что будет его активно читать, например вот так (не делайте этого на проде):

USE [StackOverflow2013]GODBCC DROPCLEANBUFFERS;GOSELECT *FROM dbo.Posts;    --сессия 1SELECT *FROM dbo.Comments; --сессия 2SELECT *FROM dbo.Votes;    --сессия 3

В разных сессиях я читаю разные таблицы, поскольку Enterprise (и, скорее всего, Developer) Edition умеет делать "shared scan" и результат может быть несколько некорректным. На графике ниже можно оценить с какой любовью и заботой подбирал жёсткий диск производитель моего ноута.

Итак, в среднем SQL Server может рассчитывать на 75 IOPS (на самом деле побольше, потому что запросы я начал выполнять через несколько секунд, после начала измерений). Окей, создаю пулы, группу, функцию классификации и запускаю Resource Governor.

USE [master];GOCREATE RESOURCE POOL [pool1]WITH (    MIN_IOPS_PER_VOLUME = 50);CREATE RESOURCE POOL [pool2]WITH (    MIN_IOPS_PER_VOLUME = 30,    MAX_IOPS_PER_VOLUME = 50);GOCREATE WORKLOAD GROUP [pool1_group1]USING [pool1];CREATE WORKLOAD GROUP [pool2_group1]USING [pool2];ALTER FUNCTION fnClassify()RETURNS SYSNAME WITH SCHEMABINDINGASBEGIN    RETURN         CASE ORIGINAL_LOGIN()             WHEN 'p1g1' THEN 'pool1_group1'            WHEN 'p2g1' THEN 'pool2_group1'        ELSE 'default' END;END;GOALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = dbo.fnClassify);  ALTER RESOURCE GOVERNOR RECONFIGURE;  

Итак, посмотрим, как же разделится IO, если я запущу из разных сессий, относящихся к разным группам нагрузки, те же самые бессмысленные сканирования - для этого используем счётчики Disk Read IO/sec и Disk Read IO Throttled/sec из SQL Server: Resource Pool Stats. Сразу обращу ваше внимание, что в группе SQL Server: Workload Group Stats нет счётчиков, относящихся к IO, поэтому, вероятнее всего, "важность" группы никак не влияет на IO.

видит Бог, я пытался получить ровный график хоть где-товидит Бог, я пытался получить ровный график хоть где-то

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

На верхнем графике, где показаны Read IOPS, видно, что сначала выполнялись запросы сессий только из пула 2 и Resource Governor "резал" их до 50, что указано в качестве максимального количества IOPS. После того, как добавился запрос из сессии, относящейся к первому пулу, основной его задачей было постараться сделать так, чтобы у всех выполнились минимальные ограничения - 50 в первом пуле и 30 во втором. Причём, скорее всего, из-за того, что во втором пуле IO были ограничены "сверху", и Resource Governor и так приходилось резать ему пропускную способность, "тормозить" IO первого пула ему приходилось только тогда, когда жёсткий диск уже не мог обеспечить минимум для второго пула.


В заключение, добавлю, что Resource Governor появился с SQL Server 2008 и с тех пор неплохо так обновился. Всё, что написано выше, в принципе, уже должно работать в SQL Server 2014, но на всякий случай - проверьте документацию по своей версии.

Последнее, что нужно рассказать - это когда Resource Governor может помочь. Наверное, можно было с этого начать, но мне кажется, что после демонстрации проще понять о чём речь.

В случае нагрузки на CPU, Resource Governor имеет шансы помочь только в том случае, если CPU - это реально узкое место. Если процессор сервера не загружен на 100% - маловероятно, что от Governor'а будет толк. Да, вы можете использовать CAP_PERCENT, но это значит, что в моменты, когда особой нагрузки нет, он будет только вредить.

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

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

Будьте осторожны и не забывайте про DAC.

Дополнительное чтиво:

  1. MSDN про Resource Governor

  2. Roy Ernest: Resoruce Governor

  3. MSDN про функции классификации

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru