Posicionamento de granularidade
Orleans garante que, quando uma chamada de grão é feita, há uma instância desse grão disponível na memória em algum servidor no cluster para lidar com a solicitação. Se a granularidade não estiver ativa no cluster no momento, o Orleans escolherá um dos servidores para ativar a granularidade. Isso se chama posicionamento de granularidade. O posicionamento também é uma maneira de balancear a carga: até mesmo o posicionamento de granularidade ocupada ajuda a equilibrar a carga de trabalho em todo o cluster.
O processo de posicionamento em Orleans é totalmente configurável: os desenvolvedores podem escolher entre um conjunto de políticas de posicionamento pré-definidas, como aleatória, preferencial e baseada em carga; ou podem configurar uma lógica personalizada. Isso permite a flexibilidade total na decisão de onde os grãos são criados. Por exemplo, os grãos podem ser colocados em um servidor próximo aos recursos em que precisam operar ou perto de outros grãos com os quais se comunicam. Por padrão, Orleans escolherá um servidor compatível aleatório.
A estratégia de posicionamento que Orleans usa pode ser configurada globalmente ou por classe granular.
Posicionamento aleatório
Um servidor é selecionado aleatoriamente nos servidores compatíveis no cluster. Essa estratégia de posicionamento é configurada adicionando o RandomPlacementAttribute a uma granularidade.
Posicionamento local
Se o servidor local for compatível, selecione o servidor local, caso contrário, selecione um servidor aleatório. Essa estratégia de posicionamento é configurada adicionando o PreferLocalPlacementAttribute a uma granularidade.
Posicionamento baseado em hash
Faça um hash da ID da granularidade para um inteiro não negativo e modifique-o com o número de servidores compatíveis. Selecione o servidor correspondente na lista de servidores compatíveis ordenados pelo endereço do servidor. Observe que não é garantido que isso permaneça estável, à medida que a associação de cluster for alterada. Especificamente, adicionar, remover ou reiniciar servidores pode alterar o servidor selecionado para um determinado ID de grão. Como os grãos colocados usando essa estratégia são registrados no diretório de grãos, essa alteração na decisão de posicionamento normalmente não tem um efeito perceptível quando há mudanças na associação.
Essa estratégia de posicionamento é configurada adicionando o HashBasedPlacementAttribute a uma granularidade.
Posicionamento baseado em contagem de ativação
Essa estratégia de posicionamento pretende colocar novas ativações de granularidade no servidor menos carregado, de acordo com o número de granularidades ocupadas recentemente. Ele inclui um mecanismo no qual todos os servidores publicam periodicamente sua contagem total de ativação para todos os outros servidores. Em seguida, o diretor de posicionamento seleciona um servidor que deve ter o menor número de ativações examinando a contagem de ativação relatada mais recentemente e prevê a contagem de ativação atual com base na contagem de ativação recente feita pelo diretor de posicionamento no servidor atual. O diretor seleciona vários servidores aleatoriamente ao fazer essa previsão, para evitar que vários servidores separados sobrecarregem o mesmo servidor. Por padrão, dois servidores são selecionados aleatoriamente, mas esse valor é configurável por meio de ActivationCountBasedPlacementOptions.
Esse algoritmo baseia-se na tese The Power of Two Choices in Randomized Load Balancing de Michael David Mitzenmachere também é usado no Nginx para balanceamento de carga distribuído, conforme descrito no artigo NGINX e o algoritmo Load-Balancing "Power of Two Choices".
Essa estratégia de posicionamento é configurada adicionando o ActivationCountBasedPlacementAttribute a uma granularidade.
Posicionamento de trabalhador sem estado
O posicionamento de trabalho sem estado é uma estratégia de posicionamento especial usada pelas granularidades de trabalho sem estado. Esse posicionamento opera de forma quase idêntica a PreferLocalPlacement exceto que cada servidor pode ter várias ativações do mesmo grão e o grão não está registrado no diretório de grãos, pois não há necessidade.
Essa estratégia de posicionamento é configurada adicionando o StatelessWorkerAttribute a uma granularidade.
Posicionamento baseado em função de silo
Uma estratégia de posicionamento determinística que coloca grãos em silos com uma função específica. Essa estratégia de posicionamento é configurada adicionando o SiloRoleBasedPlacementAttribute a uma granularidade.
Posicionamento otimizado de recursos
A estratégia de posicionamento com otimização de recursos tenta otimizar os recursos do cluster equilibrando as ativações de grãos entre silos com base na memória disponível e no uso da CPU. Ele atribui pesos a estatísticas de runtime para priorizar recursos diferentes e calcula uma pontuação normalizada para cada silo. O silo com a pontuação mais baixa é escolhido para colocar a próxima ativação. A normalização garante que cada propriedade contribua proporcionalmente para a pontuação geral. Os pesos podem ser ajustados através de ResourceOptimizedPlacementOptions com base nos requisitos e prioridades específicas do usuário para diferentes recursos.
Além disso, essa estratégia de posicionamento expõe uma opção para construir uma preferência mais forte para o silo local (aquele que recebeu a solicitação para fazer um novo posicionamento) a ser escolhido como alvo para a ativação. Isso é controlado por meio da propriedade LocalSiloPreferenceMargin
que faz parte das opções.
Além disso, um algoritmo adaptativo online fornece um efeito de suavização que evita quedas rápidas de sinal, transformando-o em um processo de decaimento semelhante a um polinômio. Isso é especialmente importante para o uso da CPU e, no geral, contribui para evitar a saturação de recursos nos silos, especialmente os recém-ingressados.
Esse algoritmo é baseado em: Posicionamento baseado em recursos com filtragem Kalman cooperativa de modo duplo
Essa estratégia de posicionamento é configurada adicionando o ResourceOptimizedPlacementAttribute a uma granularidade.
Escolher uma estratégia de posicionamento
Escolher a estratégia de posicionamento de grãos apropriada, além dos padrões que Orleans fornece, requer monitoramento e avaliação do desenvolvedor. A escolha da estratégia de posicionamento deve ser baseada no tamanho e na complexidade do aplicativo, das características da carga de trabalho e do ambiente de implantação.
O posicionamento aleatório depende da Lei de Números Grandes, portanto, geralmente é um bom padrão quando há uma carga imprevisível espalhada por um grande número de grãos (mais de 10.000).
O posicionamento baseado em contagem de ativação também tem um elemento aleatório, contando com o princípio Power of Two Choices, que é um algoritmo comumente usado para balanceamento de carga distribuído e é usado em balanceadores de carga populares. Os silos frequentemente publicam estatísticas em tempo de execução em outros silos no cluster, incluindo:
- Memória disponível, memória física total e uso de memória.
- Uso da CPU.
- Contagem total de ativações e contagem de ativação ativa recente.
- Uma janela deslizante de ativações que estavam ativas nos últimos segundos, às vezes chamada de conjunto de trabalho de ativação.
A partir dessas estatísticas, somente as contagens de ativação são usadas atualmente para determinar a carga em um determinado silo.
Em última análise, você deve experimentar estratégias diferentes e monitorar as métricas de desempenho para determinar o melhor ajuste. Selecionando a estratégia de posicionamento de grãos correta, você pode otimizar o desempenho, a escalabilidade e o custo-benefício de seus aplicativos Orleans.
Configurar a estratégia de posicionamento padrão
O Orleans usará o posicionamento aleatório, a menos que o padrão seja substituído. A estratégia de posicionamento padrão pode ser substituída registrando uma implementação de PlacementStrategy durante a configuração:
siloBuilder.ConfigureServices(services =>
services.AddSingleton<PlacementStrategy, MyPlacementStrategy>());
Configurar a estratégia de posicionamento para uma granularidade
A estratégia de posicionamento para um tipo de grão é configurada adicionando o atributo apropriado na classe de grãos. Os atributos relevantes são especificados nas seções de estratégias de posicionamento .
Exemplo de estratégia de posicionamento personalizado
Primeiro defina uma classe que implementa IPlacementDirector interface, exigindo um único método. Neste exemplo, presumimos que você tenha uma função GetSiloNumber
definida que retornará um número de silo com base no Guid do grão que está prestes a ser criado.
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]);
}
}
Em seguida, você precisa definir duas classes para permitir que as classes de grãos sejam atribuídas à estratégia:
[Serializable]
public sealed class SamplePlacementStrategy : PlacementStrategy
{
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class SamplePlacementStrategyAttribute : PlacementAttribute
{
public SamplePlacementStrategyAttribute() :
base(new SamplePlacementStrategy())
{
}
}
Em seguida, basta marcar todas as classes de grãos que você deseja usar essa estratégia com o atributo:
[SamplePlacementStrategy]
public class MyGrain : Grain, IMyGrain
{
// ...
}
Por fim, registre a estratégia ao criar o 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.AddPlacementDirector<SamplePlacementStrategy, SamplePlacementStrategyFixedSiloDirector>();
}
Para obter um segundo exemplo simples que mostre o uso adicional do contexto de posicionamento, consulte o PreferLocalPlacementDirector
no repositório de origem do Orleans.