Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Neste artigo, você aprenderá as diferenças entre confirmações imediatas e atrasadas.
Confirmação imediata
Para muitos aplicativos, você deseja garantir que os eventos sejam confirmados imediatamente. Isso impede que a versão persistente fique atrás da versão atual na memória e evita o risco de perder o estado mais recente se a unidade falhar. Você pode garantir isso seguindo estas regras:
- Confirme todas as chamadas RaiseEvent usando ConfirmEvents antes do método grain retornar.
- Certifique-se de que as tarefas retornadas por RaiseConditionalEvent sejam concluídas antes que o método de grão retorne.
- Evite atributos ReentrantAttribute ou AlwaysInterleaveAttribute para que apenas um processo de chamada de grão ocorra por vez.
Se você seguir essas regras, isso significa que, depois que um evento é gerado, nenhum outro código de grão pode ser executado até que o evento tenha sido gravado no armazenamento. Portanto, é impossível observar inconsistências entre a versão na memória e a versão armazenada. Embora isso seja muitas vezes exatamente o que você quer, ele também tem algumas desvantagens potenciais.
Possíveis desvantagens
Se a conexão com um cluster ou armazenamento remoto for temporariamente interrompida, o grão ficará indisponível. Efetivamente, o grão não pode executar nenhum código enquanto estiver parado aguardando para confirmar eventos, o que pode levar um tempo indefinido (o protocolo de consistência de log continua tentando novamente até que a conectividade de armazenamento seja restaurada).
Ao lidar com muitas atualizações em uma única instância, confirmá-las uma de cada vez pode se tornar muito ineficiente, potencialmente causando baixa eficiência.
Confirmação atrasada
Para melhorar a disponibilidade e a taxa de transferência nas situações mencionadas acima, os grãos podem optar por fazer um ou ambos os seguintes procedimentos:
- Permitir que métodos de grãos acionem eventos sem aguardar confirmação.
- Permita a reentração, para que o grão possa continuar processando novas chamadas mesmo se as chamadas anteriores ficarem paralisadas aguardando confirmação.
Isso significa que o código granular pode ser executado enquanto alguns eventos ainda estão sendo confirmados. A JournaledGrain<TGrainState,TEventBase> API tem provisões específicas que lhe dão controle preciso sobre como lidar com eventos não confirmados atualmente em trânsito.
Você pode examinar a seguinte propriedade para descobrir quais eventos não foram confirmados no momento:
IEnumerable<EventType> UnconfirmedEvents { get; }
Além disso, como o estado retornado pela JournaledGrain<TGrainState,TEventBase>.State propriedade não inclui o efeito de eventos não confirmados, há uma propriedade alternativa:
StateType TentativeState { get; }
Essa propriedade retorna um estado "provisório", obtido de State
pela aplicação de todos os eventos não confirmados. O estado provisório é essencialmente uma "melhor estimativa" do que provavelmente se tornará o próximo estado confirmado depois que todos os eventos não confirmados forem confirmados. No entanto, não há garantia de que ele realmente se tornará o estado confirmado. Isso ocorre porque o grão pode falhar, ou os eventos podem correr contra outros eventos e perder, fazendo com que eles sejam cancelados (se condicionais) ou apareçam mais tarde na sequência do que o previsto (se incondicional).
Garantias de concorrência
Observe que Orleans o agendamento por turnos (concorrência cooperativa) sempre se mantém, mesmo ao usar reentrância ou confirmação atrasada. Isso significa que, embora vários métodos possam estar em andamento, apenas um pode estar executando ativamente; todos os outros estão presos em um await
. Portanto, nunca há corridas verdadeiras causadas por threads paralelos.
Em particular, observe que:
- As propriedades State, TentativeStatee VersionUnconfirmedEvents podem ser alteradas durante a execução de um método.
- No entanto, essas alterações só podem ocorrer enquanto estiverem presas em um
await
.
Essas garantias pressupõem que seu código permaneça dentro das práticas recomendadas relativas a tarefas e ao uso de async/await (em particular, não utiliza tarefas do pool de threads ou as utiliza apenas para código que não chama a funcionalidade de grain e que são corretamente aguardadas).