Compartilhar via


Grãos de trabalho sem estado

Por padrão, o Orleans runtime cria não mais do que uma ativação de um grão dentro do cluster. Essa é a expressão mais intuitiva do modelo de Ator Virtual, em que cada grão corresponde a uma entidade com um tipo/identidade exclusivo. No entanto, às vezes, um aplicativo precisa executar operações funcionais sem estado não vinculadas a uma entidade específica no sistema. Por exemplo, se um cliente envia solicitações com cargas compactadas que precisam de descompactação antes de rotear para o grão de destino para processamento, essa lógica de descompactação/roteamento não está vinculada a uma entidade específica e pode ser facilmente expandida.

Quando você aplica a StatelessWorkerAttribute uma classe de grãos, indica ao runtime que os Orleans grãos dessa classe devem ser tratados como grãos de trabalho sem estado. Os grãos de trabalho sem estado têm as seguintes propriedades que tornam sua execução muito diferente das classes normais de grãos:

  1. O Orleans runtime pode e cria várias ativações de um grão de trabalho sem estado em diferentes silos no cluster.
  2. Os grãos de trabalho sem estado executam solicitações localmente, desde que o silo seja compatível, assim, não incorrendo em custos de rede ou de serialização. Se o silo local não for compatível, as solicitações serão encaminhadas para um silo compatível.
  3. O Orleans Runtime cria automaticamente ativações adicionais de um grain de trabalho sem estado se os existentes estiverem ocupados. O número máximo de ativações por silo é limitado por padrão pelo número de núcleos de CPU no computador, a menos que você especifique-o explicitamente usando o argumento opcional maxLocalWorkers .
  4. Devido aos pontos 2 e 3, as ativações de grãos de trabalho sem estado não são individualmente endereçáveis. Duas solicitações subsequentes para um grão de trabalhador sem estado podem ser processadas por diferentes ativações.

Os grãos de trabalho sem estado fornecem uma maneira simples de criar um pool gerenciado automaticamente de ativações de grãos que aumenta e reduz automaticamente com base na carga real. O runtime sempre verifica se há ativações de grãos de trabalho sem estado disponíveis na mesma ordem. Por isso, ele sempre envia solicitações para a primeira ativação local ociosa que encontra e só prossegue para a última se todas as ativações anteriores estiverem ocupadas. Se todas as ativações estiverem ocupadas e o limite de ativação não tiver sido atingido, ele criará mais uma ativação no final da lista e enviará a solicitação para ela. Isso significa que, quando a taxa de solicitações para um worker grain sem estado aumenta e todas as ativações existentes estão ocupadas, o tempo de execução expande o pool de ativações até o limite. Por outro lado, quando a carga cai e um número menor de ativações pode lidar com ela, as ativações no final da lista não receberão solicitações. Eles ficam ociosos e, eventualmente, são desativados pelo processo padrão de coleta de ativação. Portanto, o conjunto de ativações eventualmente diminui para se ajustar à carga.

O exemplo a seguir define uma classe MyStatelessWorkerGrain de grãos de trabalho sem estado com o limite de número de ativação máximo padrão.

[StatelessWorker]
public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
{
    // ...
}

Fazer uma chamada para um grão de trabalho sem estado é o mesmo que chamar qualquer outro grão. A única diferença é que, na maioria dos casos, você usa uma única ID de grão, por exemplo, 0 ou Guid.Empty. Você pode usar múltiplos IDs de grain se for desejável ter vários pools de grain de trabalho sem estado (um por ID).

var worker = GrainFactory.GetGrain<IMyStatelessWorkerGrain>(0);
await worker.Process(args);

Este exemplo define uma classe de grãos de trabalho sem estado com no máximo uma ativação por silo.

[StatelessWorker(1)] // max 1 activation per silo
public class MyLonelyWorkerGrain : ILonelyWorkerGrain
{
    //...
}

Observe que StatelessWorkerAttribute não altera a reentrância da classe de grão-alvo. Como qualquer outro grão, os grãos de trabalho sem estado são não reentrantes por padrão. Você pode torná-los explicitamente reentrantes adicionando uma ReentrantAttribute à classe grain.

Estado

A parte "sem estado" de "trabalhador sem estado" não significa que um trabalhador sem estado não possa ter estado ou esteja limitado apenas à execução de operações funcionais. Como qualquer outro grão, um grão de trabalho sem estado pode carregar e manter na memória qualquer estado de que precise. No entanto, como várias ativações de um grão de trabalho sem estado podem ser criadas nos mesmos e diferentes silos no cluster, não há mecanismo fácil para coordenar o estado mantido por ativações diferentes.

Vários padrões úteis envolvem trabalhadores sem estado mantendo o estado.

Itens de cache quente escalonados

Para itens de cache frequentemente acessados e com alta frequência de solicitações, manter cada item em um grão de trabalho sem estado oferece estes benefícios:

  1. Ele se expande automaticamente dentro de um silo e em todos os silos do cluster.
  2. Ele disponibiliza os dados sempre localmente no silo que recebeu a solicitação do cliente por meio de seu gateway de cliente, permitindo que as solicitações sejam respondidas sem um salto de rede extra para outro silo.

Estilo de agregação por redução

Em alguns cenários, os aplicativos precisam calcular determinadas métricas em todos os grãos de um tipo específico no cluster e relatar as agregações periodicamente. Exemplos incluem relatar o número de jogadores por mapa de jogo ou a duração média de uma chamada VoIP. Se cada um dos milhares ou milhões de grãos relatar suas métricas a um único agregador global, o agregador ficará imediatamente sobrecarregado e não poderá processar a inundação de relatórios. A abordagem alternativa é transformar essa tarefa em uma agregação no estilo de redução em duas etapas (ou mais). A primeira camada de agregação envolve os grãos de relatório que enviam suas métricas para um grão de pré-agregação de trabalho sem estado. O Orleans runtime cria automaticamente várias ativações do grão de trabalho sem estado em cada silo. Como Orleans processa todas essas chamadas localmente sem chamadas remotas ou serialização de mensagens, o custo dessa agregação é significativamente menor do que em um caso remoto. Agora, cada ativação de grãos de trabalho sem estado de pré-agregação, independentemente ou em coordenação com outras ativações locais, pode enviar seu relatório agregado para o agregador final global (ou para outra camada de redução, se necessário) sem sobrecarregá-lo.