Compartilhar via


Lidando com a perda de conectividade

Depois que uma chamada RPC for concluída, a conexão não será fechada; está marcado como gratuito. Dessa forma, o servidor pode ficar inativo ou a conectividade de rede pode ser perdida durante ou entre chamadas, enquanto uma conexão está no pool. Por uma questão de política, o tempo de execução do RPC tentará novamente essas chamadas somente se as duas condições a seguir forem atendidas:

  • O servidor não pode executar a chamada ou a chamada é idempotente.
  • O cliente pode implementar novas tentativas de maneira eficiente em termos de desempenho.

Os parágrafos a seguir expandem e esclarecem as duas condições.

Uma chamada idempotente é uma chamada que pode ser executada mais de uma vez no servidor sem efeitos colaterais indesejáveis. Por exemplo, ter uma chamada RPC que consulta o saldo no banco para uma determinada conta é idempotente. Se essa chamada for executada duas vezes devido à perda de conectividade, nenhum dano será feito. Outro exemplo de uma chamada idempotente é alterar o endereço de um cliente em um banco de dados. Executar duas vezes é bom, pois a segunda execução simplesmente substitui o endereço já atual pelo mesmo endereço. Uma operação como "subtrair 50 dólares da conta xyz" não é idempotente. A perda de conectividade de rede não deve resultar em várias execuções dessa chamada.

Para ser seguro, o tempo de execução do RPC trata todas as chamadas como não idempotentes. O atributo [idempotente] não tem suporte para ncacn_ip_tcp e é ignorado. Dessa forma, a primeira condição na lista anterior é reduzida ao servidor que não pode executar a chamada.

Em muitos casos, o tempo de execução do RPC não consegue determinar conclusivamente que a chamada ainda não foi executada no servidor. Nesses casos, o cliente não tentará executar novamente a chamada.

Os exemplos a seguir ilustram quando o tempo de execução do RPC faz ou não uma chamada novamente:

  • Um servidor é reinicializado.

    Uma chamada RPC simples e sem segurança é feita em uma interface na qual nenhuma chamada anterior foi feita após a reinicialização. Como nenhuma chamada foi feita nessa interface, o tempo de execução do RPC primeiro tenta negociar o uso da interface. Ele envia um pacote usando uma conexão no pool. Como o servidor foi reinicializado e a conexão não é mais válida, ela retorna um erro. Como o tempo de execução RPC do lado do cliente ainda não começou a enviar os dados para a chamada real, o cliente determina que o servidor não poderia ter sido executado nesses dados. Portanto, ele fecha a conexão e procura outra conexão no pool. Se ele não conseguir encontrar uma conexão, ele abrirá uma nova conexão e tentará negociar o uso da interface novamente. Se isso for bem-sucedido, a chamada será feita (ou seja, uma repetição será feita, pois a falha foi detectada antes do início da chamada).

  • Uma chamada RPC com segurança em nível de privacidade (criptografia) é feita em uma conexão com um contexto de segurança já negociado.

    Para garantir um desempenho eficiente, o tempo de execução do RPC criptografa o pacote empacotado embutido (sobre os dados de texto não criptografados). Se a tentativa de enviar os dados falhar, o tempo de execução do RPC não poderá repetir a chamada, pois os dados de texto não criptografado foram substituídos pelos dados criptografados e não poderão criptografar novamente os dados com um novo contexto de segurança. Portanto, nenhuma repetição é feita.

  • Falha no envio de um fragmento que não é o primeiro.

    A repetição não é feita, pois o tempo de execução de RPC pode optar por descartar o conteúdo do primeiro fragmento depois de concluído e não tem como tentar enviar o primeiro fragmento novamente.

  • A solicitação RPC é enviada.

    O servidor anula a conexão. Nenhuma tentativa é tentada, pois o RPC não pode discernir se o servidor recebeu a chamada e começou a executá-la.

Se o servidor usar um ponto de extremidade dinâmico, o RPC não resolve novamente o ponto de extremidade durante as novas tentativas. Isso significa que, se um servidor for derrubado e voltar para cima, ele poderá residir em um ponto de extremidade diferente e o RPC não resolve o ponto de extremidade de forma transparente quando uma chamada for repetida. Para forçar a resolução nova do ponto de extremidade, o cliente RPC deve chamar RpcBindingReset antes de tentar novamente uma chamada.

Em muitos desses casos, se um cliente RPC puder determinar se uma chamada é idempotente ou se mantém os dados descartados pelo RPC, ele pode optar por criar um mecanismo de repetição sobre o RPC.

Observação

Se o servidor for um cluster e os diferentes nós do cluster executarem versões diferentes do software do servidor, uma nova tentativa de RPC poderá colocar a chamada em um nó diferente do cluster no caso de failover e, potencialmente, em uma versão diferente do servidor. Nesses cenários de implantação, verifique se o cliente não depende de uma versão específica do software do servidor para executar uma determinada chamada. Se isso acontecer, o cliente deverá criar um mecanismo sobre o RPC que detecta e manipula essas condições.