Colocação de grãos
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 o grão não estiver atualmente ativo no cluster, Orleans selecionará um dos servidores para ativá-lo. Isso é chamado colocação de grãos. O posicionamento é também uma maneira de equilibrar a carga: distribuir uniformemente os grãos ocupados ajuda a equilibrar a carga de trabalho em todo o cluster.
O processo de posicionamento no Orleans é totalmente configurável: os desenvolvedores podem escolher entre um conjunto de políticas de posicionamento prontas para uso, como aleatório, preferência local e baseado em carga, ou configurar uma lógica personalizada. Isso permite total flexibilidade na decisão de onde os grãos são criados. Por exemplo, os grãos podem ser colocados em um servidor perto de recursos que eles precisam operar ou perto de outros grãos com os quais eles se comunicam. Por padrão, Orleans escolherá um servidor compatível aleatoriamente.
A estratégia de posicionamento que Orleans usa pode ser configurada globalmente ou por classe de grão.
Colocação aleatória
Um servidor é selecionado aleatoriamente entre os servidores compatíveis no cluster. Essa estratégia de posicionamento é configurada adicionando o RandomPlacementAttribute a um grão.
Colocação 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 um grão.
Posicionamento baseado em hash
Hash o grain id para um inteiro não negativo e modulo-lo com o número de servidores compatíveis. Selecione o servidor correspondente na lista de servidores compatíveis ordenados por endereço do servidor. Observe que não é garantido que isso permaneça estável à medida que a composição do cluster muda. 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 mudança na decisão de colocação como alterações de associação normalmente não tem um efeito percetível.
Essa estratégia de posicionamento é configurada adicionando o HashBasedPlacementAttribute a um grão.
Posicionamento baseado em contagem de ativação
Esta estratégia de colocação pretende colocar novas ativações de grãos no servidor menos carregado com base no número de grãos ocupados 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 se prevê 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 sobrecarreguem o mesmo servidor. Por padrão, dois servidores são selecionados aleatoriamente, mas esse valor é configurável via ActivationCountBasedPlacementOptions.
Este algoritmo é baseado na tese The Power of Two Choices in Randomized Load Balancing de Michael David Mitzenmacher, e também é usado no Nginx para balanceamento de carga distribuída, conforme descrito no artigo NGINX and the "Power of Two Choices" Load-Balancing Algorithm.
Essa estratégia de posicionamento é configurada adicionando o ActivationCountBasedPlacementAttribute a um grão.
Colocação de trabalhadores apátridas
A colocação de trabalhadores apátridas é uma estratégia especial de colocação usada por trabalhador apátrida grãos. Este 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 ao adicionar o StatelessWorkerAttribute a um grão.
Colocação baseada em silos
Uma estratégia determinística de colocação que coloca grãos em silos com um papel específico. Esta estratégia de posicionamento é configurada ao adicionar o SiloRoleBasedPlacementAttribute a um grão.
Posicionamento otimizado de recursos
A estratégia de otimização de recursos procura otimizar os recursos do cluster ao equilibrar as ativações entre os silos com base na memória disponível e no uso da CPU. Ele atribui pesos às estatísticas de tempo de execução 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 seguinte ativação. A normalização garante que cada propriedade contribua proporcionalmente para a pontuação geral. Os pesos podem ser ajustados através do ResourceOptimizedPlacementOptions com base nos requisitos e prioridades específicos do utilizador para diferentes recursos.
Além disso, esta estratégia de posicionamento oferece uma opção para desenvolver uma preferência mais forte pelo silo local (aquele que recebeu o pedido para fazer um novo posicionamento), a ser selecionado como o alvo da ativação. Isto é controlado através da propriedade LocalSiloPreferenceMargin
que faz parte das opções.
Além disso, um on-line, algoritmo de adaptativo fornece um efeito de suavização que evita quedas rápidas de sinal, transformando-o em um processo de decaimento polinomial. Isso é especialmente importante para o uso da CPU e, no geral, contribui para evitar a saturação de recursos nos silos, especialmente nos recém-integrados.
Este algoritmo é baseado em: Colocação baseada em recursos com filtragem cooperativa de modo duplo Kalman
Essa estratégia de posicionamento é configurada adicionando o ResourceOptimizedPlacementAttribute a um grão.
Escolha uma estratégia de posicionamento
Escolher a estratégia de colocação de grãos adequada, 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, nas características da carga de trabalho e no ambiente de implantação.
A colocação aleatória depende da Lei dos Grandes Números, por isso, geralmente, é uma boa escolha padrão quando há uma carga imprevisível espalhada por um grande número de grãos (mais de 10.000).
O posicionamento baseado na contagem de ativação também tem um elemento aleatório, confiando no 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 de tempo de execução para outros silos no cluster, incluindo:
- Memória disponível, memória física total e uso de memória.
- Utilização da CPU.
- Contagem total de ativações e contagem de ativações ativas recentes.
- Uma janela deslizante de ativações que estavam ativas nos últimos segundos, às vezes referida como o conjunto de trabalho de ativação.
A partir dessas estatísticas, apenas as contagens de ativação são atualmente usadas para determinar a carga em um determinado silo.
Em última análise, você deve experimentar diferentes estratégias e monitorar métricas de desempenho para determinar o melhor ajuste. Ao selecionar a estratégia de posicionamento de grãos correta, você pode otimizar o desempenho, a escalabilidade e a relação custo-benefício de seus aplicativos Orleans.
Configurar a estratégia de posicionamento padrão
Orleans usará posicionamento aleatório, a menos que o padrão seja modificado. 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 um grão
A estratégia de posicionamento para um tipo de grão é configurada adicionando o atributo apropriado na classe de grão. Os atributos relevantes são especificados nas seções das estratégias de posicionamento.
Exemplo de estratégia de posicionamento personalizada
Primeiro, defina uma classe que implemente IPlacementDirector interface, exigindo um único método. Neste exemplo, assumimos que você tem uma função GetSiloNumber
definida que retornará um número de silo dado o Guid do grão 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 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
{
// ...
}
E, finalmente, regista a estratégia ao construir 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 um segundo exemplo simples que mostre o uso adicional do contexto de colocação, consulte o PreferLocalPlacementDirector
no repositório de código-fonte Orleans.