Размещение зерна

Orleans гарантирует, что при вызове зерна есть экземпляр этого зерна, доступный в памяти на каком-то сервере в кластере для обработки запроса. Если зерно в настоящее время не активно в кластере, Orleans выбирает один из серверов для активации зерна. Это называется размещением зерна. Размещение также является одним из способов балансировки нагрузки: даже размещение занятого зерна помогает даже рабочей нагрузке в кластере.

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

Стратегия размещения, которая Orleans используется, может быть настроена глобально или на каждый класс.

Случайное размещение

Сервер выбирается случайным образом из совместимых серверов в кластере. Эта стратегия размещения настраивается путем добавления RandomPlacementAttribute в зерно.

Локальное размещение

Если локальный сервер совместим, выберите локальный сервер, в противном случае выберите случайный сервер. Эта стратегия размещения настраивается путем добавления PreferLocalPlacementAttribute в зерно.

Размещение на основе хэша

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

Эта стратегия размещения настраивается путем добавления HashBasedPlacementAttribute в зерно.

Размещение на основе активации

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

Этот алгоритм основан на тезисе "Сила двух вариантов в случайной балансировке нагрузки" Майкла Дэвида Митценмахера, а также используется в Nginx для распределенной балансировки нагрузки, как описано в статье NGINX и алгоритм балансировки нагрузки "Power of Two Choices".

Эта стратегия размещения настраивается путем добавления ActivationCountBasedPlacementAttribute в зерно.

Размещение рабочей роли без отслеживания состояния

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

Эта стратегия размещения настраивается путем добавления StatelessWorkerAttribute в зерно.

Размещение на основе ролей Silo

Детерминированная стратегия размещения, которая помещает зерна на силосы с определенной ролью. Эта стратегия размещения настраивается путем добавления SiloRoleBasedPlacementAttribute в зерно.

Выбор стратегии размещения

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

Случайное размещение основывается на законе больших чисел, поэтому обычно это хорошее значение по умолчанию, когда происходит непредсказуемая нагрузка, распределенная по большому количеству зерен (10 000 плюс).

Размещение на основе активации также имеет случайный элемент, основанный на принципе Power of Two Choices, который обычно используется алгоритмом распределенной балансировки нагрузки и используется в популярных подсистемах балансировки нагрузки. Силосы часто публикуют статистику времени выполнения для других силосов в кластере, в том числе:

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

Из этой статистики для определения нагрузки на заданный силон используется только количество активаций.

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

Настройка стратегии размещения по умолчанию

Orleans будет использовать случайное размещение, если значение по умолчанию не переопределяется. Стратегия размещения по умолчанию может быть переопределена путем регистрации реализации PlacementStrategy во время настройки:

siloBuilder.ConfigureServices(services =>
    services.AddSingleton<PlacementStrategy, MyPlacementStrategy>());

Настройка стратегии размещения для зерна

Стратегия размещения для типа зерна настраивается путем добавления соответствующего атрибута в класс зерна. Соответствующие атрибуты указываются в разделах стратегий размещения.

Пример пользовательской стратегии размещения

Сначала определите класс, реализующий IPlacementDirector интерфейс, требующий одного метода. В этом примере предполагается, что у вас есть функция GetSiloNumber , которая вернет номер фрагмента с учетом Guid создаваемого зерна.

public class SamplePlacementStrategyFixedSiloDirector : IPlacementDirector
{
    public Task<SiloAddress> OnAddActivation(
        PlacementStrategy strategy,
        PlacementTarget target,
        IPlacementContext context)
    {
        var silos = context.GetCompatibleSilos(target).OrderBy(s => s).ToArray();
        int silo = GetSiloNumber(target.GrainIdentity.PrimaryKey, silos.Length);

        return Task.FromResult(silos[silo]);
    }
}

Затем необходимо определить два класса, чтобы разрешить назначать классы зерна стратегии:

[Serializable]
public sealed class SamplePlacementStrategy : PlacementStrategy
{
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class SamplePlacementStrategyAttribute : PlacementAttribute
{
    public SamplePlacementStrategyAttribute() :
        base(new SamplePlacementStrategy())
    {
    }
}

Затем просто пометьте все классы зерна, которые вы хотите использовать эту стратегию с атрибутом:

[SamplePlacementStrategy]
public class MyGrain : Grain, IMyGrain
{
    // ...
}

И, наконец, зарегистрируйте стратегию при сборке SiloHost:

private static async Task<ISiloHost> StartSilo()
{
    var builder = new HostBuilder(c =>
    {
        // normal configuration methods omitted for brevity
        c.ConfigureServices(ConfigureServices);
    });

    var host = builder.Build();
    await host.StartAsync();

    return host;
}

private static void ConfigureServices(IServiceCollection services)
{
    services.AddSingletonNamedService<
        PlacementStrategy, SamplePlacementStrategy>(
            nameof(SamplePlacementStrategy));

    services.AddSingletonKeyedService<
        Type, IPlacementDirector, SamplePlacementStrategyFixedSiloDirector>(
            typeof(SamplePlacementStrategy));
}

Второй простой пример дальнейшего использования контекста размещения см PreferLocalPlacementDirector . в исходном Orleans репозитории.