Antipattern: equilíbrio de carga com um único servidor de destino com MaxFailures definido como um valor diferente de zero

Está a ver a documentação do Apigee e do Apigee Hybrid.
Veja a documentação do Apigee Edge.

A configuração TargetEndpoint define a forma como o Apigee se liga a um serviço ou uma API de back-end. Envia os pedidos e recebe as respostas para/do serviço de back-end. O serviço de back-end pode ser um servidor HTTP/HTTPS ou NodeJS.

O serviço de back-end no TargetEndpoint pode ser invocado de uma das seguintes formas:

  • Direcione o URL para um servidor HTTP ou HTTPS
  • Configuração do TargetServer

Da mesma forma, a política ServiceCallout pode ser usada para fazer uma chamada a qualquer serviço externo a partir do fluxo do proxy de API. Esta política suporta a definição de URLs de destino HTTP/HTTPS diretamente na própria política ou através de uma configuração TargetServer.

Configuração do TargetServer

A configuração TargetServer desassocia os URLs de pontos finais concretos das configurações TargetEndpoint ou das políticas Service Callout. Um TargetServer é referenciado por um nome em vez do URL no TargetEndpoint. A configuração TargetServer tem o nome de anfitrião do serviço de back-end, o número da porta e outros detalhes.

Segue-se um exemplo de configuração do TargetServer:

<TargetServer name="target1">
  <Host>www.mybackendservice.com</Host>
  <Port>80</Port>
  <IsEnabled>true</IsEnabled>
</TargetServer>

O TargetServer permite-lhe ter configurações diferentes para cada ambiente. Uma política TargetEndpoint/Service Callout pode ser configurada com um ou mais TargetServers com nomes usando um LoadBalancer. O suporte incorporado para o equilíbrio de carga melhora a disponibilidade das APIs e a comutação por falha entre instâncias de servidores de back-end configuradas.

Segue-se um exemplo de configuração de TargetEndpoint que usa TargetServers:

<TargetEndpoint name="default">
    <HTTPTargetConnection>>
      <LoadBalancer>
        <Server name="target1"/>
        <Server name="target2"/>
      </LoadBalancer>
    </HTTPTargetConnection>
</TargetEndpoint>

MaxFailures

A configuração MaxFailures especifica o número máximo de falhas de pedidos ao servidor de destino após o qual o servidor de destino deve ser marcado como inativo e removido da rotação para todos os pedidos subsequentes.

Um exemplo de configuração com MaxFailures especificado:

<TargetEndpoint name="default">
    <HTTPTargetConnection>
      <LoadBalancer>
        <Server name="target1"/>
        <Server name="target2"/>
        <MaxFailures>5</MaxFailures>
      </LoadBalancer>
    </HTTPTargetConnection>
</TargetEndpoint>

No exemplo acima, se cinco pedidos consecutivos falharem para "target1", "target1" é removido da rotação e todos os pedidos subsequentes são enviados apenas para target2.

Antipattern

Ter um único TargetServer numa configuração LoadBalancer da política TargetEndpoint ou Service Callout com MaxFailures definido como um valor diferente de zero não é recomendado, uma vez que pode ter implicações adversas.

Considere a seguinte configuração de exemplo que tem um único TargetServer com o nome "target1" com MaxFailures definido como 5 (valor diferente de zero):

<TargetEndpoint name="default">
  <HTTPTargetConnection>
      <LoadBalancer>
        <Algorithm>RoundRobin</Algorithm>
        <Server name="target1" />
        <MaxFailures>5</MaxFailures>
      </LoadBalancer>
  </HTTPTargetConnection>

Se os pedidos para o TargetServer "target1" falharem cinco vezes (número especificado em MaxFailures), o TargetServer é removido da rotação. Uma vez que não existem outros TargetServers para os quais a comutação por falha possa ser feita, todos os pedidos subsequentes ao proxy de API com esta configuração vão falhar com o erro 503 Service Unavailable.

Mesmo que o TargetServer "target1" volte ao seu estado normal e seja capaz de enviar respostas bem-sucedidas, os pedidos ao proxy de API continuam a devolver erros 503. Isto acontece porque o Apigee não volta a colocar automaticamente o TargetServer em rotação, mesmo depois de o destino estar novamente em funcionamento. Para resolver este problema, o proxy de API tem de ser implementado novamente para que o Apigee volte a colocar o TargetServer em rotação.

Se for usada a mesma configuração na política de texto de chamada de serviço, os pedidos da API vão receber um erro 500 depois de os pedidos ao TargetServer "target1" falharem 5 vezes.

Impacto

A utilização de um único TargetServer numa configuração LoadBalancer da política TargetEndpoint ou Service Callout com MaxFailures definido para um valor diferente de zero provoca o seguinte:

  • As solicitações de API falham continuamente com erros 503/500 (após as solicitações falharem o número de vezes definido em MaxFailures) até que o proxy da API seja reimplementado.
  • Interrupção mais longa, uma vez que é difícil e pode demorar mais tempo a diagnosticar a causa deste problema (sem conhecimento prévio sobre este antipadrão).

Prática recomendada

  1. Ter mais do que um TargetServer na configuração LoadBalancer para maior disponibilidade.
  2. Defina sempre uma Monitorização do sistema quando MaxFailures estiver definido como um valor diferente de zero. Um servidor de destino é removido da rotação quando o número de falhas atinge o número especificado em MaxFailures. A existência de um HealthMonitor garante que o TargetServer é novamente colocado em rotação assim que o servidor de destino voltar a estar disponível, o que significa que não é necessário reimplementar o proxy.

    Para garantir que a verificação de estado é realizada no mesmo número de porta que o Apigee usa para se ligar aos servidores de destino, o Apigee recomenda que omita o elemento filho <Port> em <TCPMonitor>, a menos que seja diferente da porta TargetServer. Por predefinição, <Port> é igual à porta TargetServer.

    Exemplo de configuração com o HealthMonitor:

    <TargetEndpoint name="default">
      <HTTPTargetConnection>
        <LoadBalancer>
          <Algorithm>RoundRobin</Algorithm>
          <Server name="target1" />
          <Server name="target2" />
          <MaxFailures>5</MaxFailures>
        </LoadBalancer>
        <Path>/test</Path>
        <HealthMonitor>
          <IsEnabled>true</IsEnabled>
          <IntervalInSec>5</IntervalInSec>
          <TCPMonitor>
            <ConnectTimeoutInSec>10</ConnectTimeoutInSec>
          </TCPMonitor>
        </HealthMonitor>
      </HTTPTargetConnection>
    </TargetEndpoint>
  3. Se existir alguma restrição de modo que apenas um TargetServer e se o HealthMonitor não for usado, não especifique MaxFailures na configuração LoadBalancer.

    O valor predefinido de MaxFailures é 0. Isto significa que o Apigee tenta sempre estabelecer ligação ao destino para cada pedido e nunca remove o servidor de destino da rotação.

Leitura complementar