Масштабирование в Service Fabric

Azure Service Fabric упрощает создание масштабируемых приложений, обеспечивая управление службами, секциями и репликами на узлах кластера. Выполнение множества рабочих нагрузок на одном и том же оборудовании обеспечивает не только максимальное использование ресурсов, но и гибкость в выборе способа масштабирования рабочих нагрузок. В этом видео Channel 9 объясняется, как создавать масштабируемые приложения для микрослужб:

В Service Fabric масштабирования осуществляется несколькими способами:

  1. Масштабирование путем создания или удаления экземпляров службы без отслеживания состояния
  2. масштабирование путем создания или удаления новых именованных служб;
  3. Масштабирование путем создания или удаления новых именованных экземпляров приложений
  4. масштабирование с использованием секционированных служб;
  5. Масштабирование путем добавления и удаления узлов кластера
  6. масштабирование с помощью метрик диспетчера кластерных ресурсов.

Масштабирование путем создания или удаления экземпляров службы без отслеживания состояния

Один из самых простых способов масштабирования в Service Fabric применяется для служб без отслеживания состояния. При создании службы без отслеживания состояния вы получаете возможность определить InstanceCount. InstanceCount определяет, сколько работающих копий кода этой службы создается при ее запуске. Предположим, например, что в кластере имеется 100 узлов. Предположим также, что служба создается с параметром InstanceCount, равным 10. Во время выполнения все эти 10 работающих копий кода могут стать слишком нагруженными (или недостаточно нагруженными). Один из способов масштабирования рабочей нагрузки — изменение количества экземпляров. Например, некоторые части кода мониторинга и управления могут изменить существующее число экземпляров на 50 или 5 экземпляров в зависимости от того, следует ли свернуть или развернуть рабочую нагрузку в соответствии с нагрузкой.

C#:

StatelessServiceUpdateDescription updateDescription = new StatelessServiceUpdateDescription(); 
updateDescription.InstanceCount = 50;
await fabricClient.ServiceManager.UpdateServiceAsync(new Uri("fabric:/app/service"), updateDescription);

PowerShell.

Update-ServiceFabricService -Stateless -ServiceName $serviceName -InstanceCount 50

Использование динамического числа экземпляров

Специально для служб без отслеживания состояния Service Fabric предлагает автоматическое изменение количества экземпляров. Это обеспечивает динамическое масштабирование службы в пределах доступных узлов. Чтобы использовать такой режим, следует задать число экземпляров, равное -1. InstanceCount = -1 — это инструкция для Service Fabric, которая указывает "Запустить эту службу без отслеживания состояния на каждом узле". Если количество узлов изменится, то Service Fabric автоматически изменит число экземпляров в соответствии с этим изменением, чтобы обеспечить работу службы на всех допустимых узлах.

C#:

StatelessServiceDescription serviceDescription = new StatelessServiceDescription();
//Set other service properties necessary for creation....
serviceDescription.InstanceCount = -1;
await fc.ServiceManager.CreateServiceAsync(serviceDescription);

PowerShell.

New-ServiceFabricService -ApplicationName $applicationName -ServiceName $serviceName -ServiceTypeName $serviceTypeName -Stateless -PartitionSchemeSingleton -InstanceCount "-1"

масштабирование путем создания или удаления новых именованных служб;

Именованный экземпляр службы представляет собой экземпляр определенного типа службы (см. статью Жизненный цикл приложения Service Fabric) в каком-либо именованном экземпляре приложения в кластере.

Новые именованные экземпляры службы могут создаваться (или удаляться) при повышении (или снижении) нагрузки службы. Это позволяет распределять запросы между несколькими экземплярами службы, что, как правило, дает возможность снизить нагрузку существующих служб. При создании служб диспетчер кластерных ресурсов Service Fabric распределяет их по кластеру. Точные решения о размещении определяются метриками в кластере и другими правилами размещения. Службы могут быть созданы несколькими способами, однако чаще всего они создаются с помощью административных действий, таких как вызов New-ServiceFabricService, или кода, вызывающего CreateServiceAsync. CreateServiceAsync можно даже вызвать из других служб, выполняющихся в кластере.

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

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

Решением является создание экземпляра этой службы для каждого отдельного экземпляра рабочего процесса, который нужно отслеживать. Такой шаблон отлично работает с любой службой (с отслеживанием состояния и без отслеживания). Для работы этой схемы, как правило, используется еще одна служба, которая выступает в роли "службы диспетчера рабочих нагрузок". Задача этой службы — получать запросы и перенаправлять их к другим службам. Диспетчер может динамически создать экземпляр службы рабочей нагрузки, когда он получит сообщение, и затем передать запрос этой службе. Служба диспетчера может также получать обратные вызовы, когда заданная служба рабочего процесса завершает свое задание. Когда диспетчер получает эти обратные вызовы, он может удалить данный экземпляр службы рабочего процесса или оставить его, если ожидаются дополнительные вызовы.

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

Масштабирование путем создания или удаления новых именованных экземпляров приложений

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

В каких случаях должен создаваться новый именованный экземпляр приложения, а не новые именованные экземпляры службы в существующем приложении? Таких случаев несколько.

  • Новый экземпляр приложения для клиента, код которого должен выполняться с использованием определенного удостоверения или параметров безопасности.
    • Service Fabric дает возможность определить разные пакеты кода для запуска с помощью определенных удостоверений. Чтобы запустить один и тот же пакет кода с использованием разных удостоверений, необходимо выполнить активацию в разных экземплярах приложения. Предположим, в вашей среде развернуты рабочие нагрузки клиента. Они могут выполняться с использованием конкретного удостоверения, чтобы можно было отслеживать и контролировать их доступ к другим ресурсам, например удаленным базам данных или другим системам. В этом случае при регистрации нового клиента, вероятно, вы не захотите активировать его код в том же контексте (пространстве процесса). Вы могли бы это сделать, но это усложнило бы выполнение кода службы в контексте определенного удостоверения. Обычно требуется дополнительный код для защиты, изоляции и управления удостоверениями. Вместо того, чтобы использовать различные именованные экземпляры службы в одном экземпляре приложения и, следовательно, в одном пространстве процесса, можно использовать разные именованные экземпляры приложения Service Fabric. Это упрощает определение разных контекстов удостоверений.
  • Новый экземпляр приложения выступает также в роли средства настройки.
    • По умолчанию все именованные экземпляры конкретной службы определенного типа в экземпляре приложения будут выполняться в одном процессе на заданном узле. Это означает, что хотя каждый экземпляр службы можно настроить по-разному, сделать это сложно. Службы должны использовать какой-либо токен для поиска своей конфигурации в пакете конфигурации. Обычно это просто имя службы. Это хороший способ, но он привязывает конфигурацию к именам отдельных именованных экземпляров службы в пределах данного экземпляра приложения. Это может внести путаницу и усложнить управление, так как конфигурация обычно является артефактом времени разработки со значениями, относящимися к экземпляру приложения. Создание дополнительных служб всегда означает дополнительные обновления приложения, необходимые для изменения информации в пакетах конфигурации или развертывания новых пакетов конфигурации, в которых новые службы смогут найти относящуюся к ним информацию. Часто бывает проще создать абсолютно новый именованный экземпляр приложения. Затем можно использовать параметры приложения, чтобы задать требуемую конфигурацию для служб. Таким образом все службы, созданные в именованном экземпляре приложения, могут наследовать определенные параметры конфигурации. Например, вместо использования одного файла конфигурации с параметрами и настройками для каждого клиента (например, это могут быть секреты или ограничения ресурсов на клиента), можно создать отдельные экземпляры приложения для каждого клиента, переопределив эти параметры.
  • Новое приложение служит в качестве границы обновления.
    • В Service Fabric разные именованные экземпляры приложения служат в качестве границы для обновления. Обновление одного именованного экземпляра приложения не повлияет на код, который выполняет другой именованный экземпляр приложения. В итоге разные приложения будут выполнять разные версии одного кода на одних и тех же узлах. Это может повлиять на принятие решения о масштабировании, так как можно выбрать, должен ли новый код быть обновлен, как и другая служба. Например, предположим, в службу диспетчера, который отвечает за масштабирование рабочих нагрузок конкретного клиента путем динамического создания и удаления служб, поступает вызов. В этом случае, однако, вызов направлен к рабочей нагрузке, связанной с новым клиентом. Большинство клиентов стремится изолироваться друг от друга не только по соображениям безопасности и настройки, приведенным ранее. Это обеспечивает большую гибкость для выполнения специальных версий программного обеспечения и выбора момента для их обновления. Можно также создать новый экземпляр приложения и создать в нем службу, чтобы еще больше секционировать службы, которые затронет какое-либо обновление. Отдельные экземпляры приложения обеспечивают большую детализацию при обновлении приложений, а также позволяют использовать тестирование A/B и развертывания Blue-Green.
  • Существующий экземпляр приложения заполнен.
    • В Service Fabric емкость приложения — это понятие, которое можно использовать для управления объемом ресурсов, доступных для конкретных экземпляров приложения. Например, вы можете решить, что для данной службы требуется создать еще один экземпляр, чтобы увеличить ее масштаб. Однако этот экземпляр приложения превышает емкость для определенной метрики. Если этому клиенту или рабочей нагрузке все же требуется предоставить больше ресурсов, то можно либо увеличить емкость для данного приложения, либо создать новое приложение.

Масштабирование на уровне раздела

Service Fabric поддерживает секционирование. Секционирование позволяет разделить службы на несколько логических и физических секций, каждая из которых работает независимо друг от друга. Это удобно использовать для служб с отслеживанием состояния, так как ни один набор реплик не должен обрабатывать все вызовы и оперировать всеми состояниями одновременно. В разделе Обзор по разделам содержится информация о поддерживаемых типах схем секционирования на разделы. Реплики каждой секции распределены между узлами в кластере. Это позволяет распределить нагрузку данной службы и предотвратить появление единых точек отказа как во всей службе, так и в любой секции.

Рассмотрим службу, использующую схему секционирования по диапазонам, в которой нижний ключ равен 0, верхний ключ равен 99, а количество разделов равно 4. В кластере с тремя узлами служба может состоять из четырех реплик, совместно использующих ресурсы каждого узла, как показано ниже:

Макет секции с тремя узлами

Если вы увеличите число узлов, Service Fabric переместит на них несколько существующих реплик. Например, предположим, что количество узлов увеличивается до четырех и реплики перераспределяются. Теперь у службы три реплики, которые выполняются на каждом узле и относятся к разным секциям. Это обеспечивает более эффективное использование ресурсов, так как новый узел также нагружен. Как правило, это также повышает производительность, так как каждой службе доступно больше ресурсов.

Макет секции с четырьмя узлами

Масштабирование с помощью диспетчера кластерных ресурсов Service Fabric и метрик

Метрики выражают потребление службами ресурсов в Service Fabric. С помощью метрик диспетчер кластерных ресурсов может реорганизовывать и оптимизировать структуру кластера. Например, в кластере может быть большое количество ресурсов, но они могут быть не выделены службам, которые в настоящее время выполняют работу. С помощью метрик диспетчер кластерных ресурсов может реорганизовать кластер, чтобы предоставить службам доступные ресурсы.

Масштабирование путем добавления и удаления узлов кластера

Еще один вариант масштабирования в Service Fabric — изменение размера кластера. Изменение размера кластера означает добавление или удаление узлов одного или нескольких типов в кластере. Например, рассмотрим случай, в котором все узлы в кластере нагружены. Это означает, что ресурсы кластера почти полностью использованы. В этом случае лучшим способом масштабирования является добавление узлов в кластер. После присоединения новых узлов к кластеру диспетчер кластерных ресурсов Service Fabric переместит на них службы, что снизит общую нагрузку на существующие узлы. Для служб без отслеживания состояния с числом экземпляров, равным -1, дополнительные экземпляры службы создаются автоматически. Это позволяет перенести некоторые вызовы с существующих узлов на новые узлы.

Дополнительные сведения см. в статье о масштабировании кластера.

Выбор платформы

Так как реализации в разных операционных системах отличаются, выбор платформы Windows или Linux для Service Fabric может быть важным решением в ходе масштабирования приложения. Одной из возможных преград может стать способ промежуточного ведения журнала. Service Fabric в среде Windows использует драйвер ядра для создания одного журнала на каждом компьютере, который используется всеми репликами службы с отслеживанием состояния. Размер этого журнала может достигать 8 ГБ. С другой стороны, в среде Linux для каждой реплики создается отдельный промежуточный журнал размером 256 MB. Это не очень оптимально для приложений, в которых требуется использовать максимальное число небольших реплик службы, выполняющихся на одном узле. Эти отличия в требованиях к временному хранилищу могут стать решающими при выборе целевой платформы для развертывания кластера Service Fabric.

Сборка

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

Перед вами стоит ряд вопросов, связанных с масштабированием: сколько пользователей будет у этой службы? Сколько контактов будет хранить каждый пользователь? Непросто ответить на все эти вопросы при первом развертывании службы. Предположим, вы собирались создать отдельную статическую службу с определенным количеством секций. Неправильный выбор числа разделов может позже привести к серьезным проблемам с масштабированием. Аналогичным образом, даже если вы выберете правильное количество, этой информации может быть недостаточно. Например, необходимо также заранее выбрать размер кластера, то есть количество узлов и их размеры. Обычно сложно спрогнозировать, сколько ресурсов служба будет использовать в течение своего времени существования. Кроме того, может быть трудно узнать заранее схему трафика, обрабатываемого службой. Например, пользователи могут с самого утра первым делом добавлять и удалять контакты или эти действия могут быть распределены равномерно на протяжении дня. Ввиду этого может потребоваться динамическое масштабирование. Возможно, вы научитесь прогнозировать необходимость в развертывании и свертывании ресурсов, но вам наверняка понадобится реагировать на изменение потребления ресурсов службой. Это может быть изменение размера кластера для предоставления ей дополнительных ресурсов, когда реорганизации использования существующих ресурсов недостаточно.

Но нужно ли нам выбирать для всех пользователей единую схему секционирования? Зачем ограничиваться одной службой и одним статическим кластером? Как правило, реальная ситуация более динамична.

При проектировании масштабирования рассмотрите приведенную ниже динамическую схему. Возможно, ее нужно будет адаптировать к вашей ситуации.

  1. Не пытайтесь сразу выбрать единственно верную и универсальную схему секционирования, а создайте службу диспетчера.
  2. Эта служба будет изучать информацию о каждом клиенте, который регистрируется в вашей основной службе. На основе этой информации служба диспетчера создает экземпляр реальной службы хранилища контактов только для этого клиента. Если клиенту требуется особая конфигурация, изоляция или обновления, для него можно также запустить экземпляр приложения.

Эта схема динамического создания имеет множество преимуществ.

  • Вам не нужно точно предугадывать правильное число разделов для всех пользователей или создавать отдельную службу, которая является бесконечно масштабируемой.
  • Разные пользователи могут использовать отличающиеся количества секций и реплик, ограничения размещения, метрики, нагрузки по умолчанию, имена служб, параметры DNS или какие-либо другие свойства, указанное на уровне службы или приложения.
  • Это обеспечивает дополнительную сегментацию данных. Каждый клиент использует свою собственную копию службы.
    • Каждую службу клиента можно настроить по-разному и предоставить ей больше или меньше ресурсов, например, выделив большее или меньшее число секций или реплик с учетом прогнозируемого масштаба.
      • Например, предположим, что клиент оплатил уровень Gold. Он может получить большее число реплик или секций и, в перспективе, ресурсов, выделяемых службам на основе метрик и емкостей приложения.
      • Если же данные, предоставленные клиентом, предполагают относительно небольшое число контактов, то для него можно использовать малое число секций или даже поместить его службу в общий пул служб, совместно используемый другими клиентами.
  • Вам не нужно поддерживать множество экземпляров или реплик службы, пока не появились клиенты.
  • Если клиент откажется от ваших услуг, то для удаления его информации из вашей службы достаточно, чтобы служба диспетчера удалила созданную для этого клиента службу или приложение.

Дальнейшие действия

Дополнительные сведения о понятиях Service Fabric см. в следующих статьях: