Práticas recomendadas para aplicativos de RTB

Este guia explica as práticas recomendadas a serem consideradas ao desenvolver aplicativos de acordo com o protocolo RTB.

Gerenciar conexões

Mantenha as conexões ativas

Estabelecer uma nova conexão aumenta as latências e exige muito mais recursos das duas extremidades do que a reutilização de uma existente. Ao fechar menos conexões, é possível reduzir o número de conexões que precisam ser abertas novamente.

Primeiro, cada nova conexão exige uma chamada de ida e volta extra para a rede. Como estabelecemos conexões sob demanda, a primeira solicitação em uma conexão tem um prazo efetivo menor e é mais provável que expire do que as solicitações subsequentes. Qualquer tempo limite extra aumenta a taxa de erros, o que pode levar à limitação do proponente.

Em segundo lugar, muitos servidores da Web geram uma linha de execução de worker dedicada para cada conexão estabelecida. Isso significa que, para fechar e recriar a conexão, o servidor precisa encerrar e descartar uma linha de execução, alocar uma nova, torná-la executável e criar o estado da conexão, antes de finalmente processar a solicitação. Isso é um excesso de trabalho desnecessário.

Evite encerrar conexões

Comece ajustando o comportamento da conexão. A maioria dos padrões do servidor é personalizada para ambientes com um grande número de clientes, cada um fazendo um pequeno número de solicitações. Para o RTB, por outro lado, um pequeno conjunto de máquinas envia solicitações em nome de um grande número de navegadores, relativamente. Sob essas condições, faz sentido reutilizar as conexões quantas vezes for possível. Recomendamos que você defina o seguinte:

  • Tempo limite de inatividade para 2,5 minutos.
  • Número máximo de solicitações em uma conexão para o maior valor possível.
  • Número máximo de conexões com o valor mais alto que a RAM pode acomodar, mas com cuidado para verificar se o número de conexões não se aproxima muito desse valor.

No Apache, por exemplo, isso implicaria na configuração de KeepAliveTimeout como 150, MaxKeepAliveRequests como zero e MaxClients como um valor que depende do tipo de servidor.

Depois que o comportamento da conexão for ajustado, verifique também se o código do bidder não fecha conexões desnecessariamente. Por exemplo, se você tiver um código de front-end que retorna uma resposta padrão "sem lance" no caso de erros de back-end ou tempos limite, verifique se o código retorna a resposta sem fechar a conexão. Assim, se o bidder ficar sobrecarregado, as conexões vão começar a ser fechadas e o número de tempos limite aumentará, o que fará com que seu bidder seja limitado.

Mantenha as conexões equilibradas

Se o Authorized Buyers se conectar aos servidores do bidder por meio de um servidor proxy, as conexões poderão ficar desequilibradas ao longo do tempo. Isso acontece porque, sabendo somente o endereço IP do servidor proxy, o Authorized Buyers não consegue determinar qual servidor do bidder está recebendo cada chamada. Com o tempo, à medida que o Authorized Buyers estabelece e encerra conexões e os servidores do bidder são reiniciados, o número de conexões mapeadas para cada um deles pode ficar altamente variável.

Quando algumas conexões são muito utilizadas, outras conexões abertas podem permanecer praticamente inativas, porque não são necessárias no momento. À medida que o tráfego do Authorized Buyers muda, as conexões inativas podem ficar inativas. Isso pode causar carregamentos desiguais nos servidores do bidder se as conexões não estiverem no cluster. O Google tenta impedir isso encerrando todas as conexões após 10.000 solicitações para reequilibrar automaticamente as conexões quentes ao longo do tempo. Se o tráfego ainda estiver desequilibrado no seu ambiente, há outras etapas que você pode seguir:

  1. Selecione o back-end por solicitação em vez de uma vez por conexão se você estiver usando proxies de front-end.
  2. Especifique um número máximo de solicitações por conexão se você estiver usando proxy de conexões por meio de um balanceador de carga de hardware ou de um firewall e o mapeamento for corrigido quando as conexões forem estabelecidas. Observe que o Google já especifica um limite máximo de 10.000 solicitações por conexão. Portanto, você só precisará fornecer um valor mais restrito se ainda encontrar conexões quentes sendo agrupadas no seu ambiente. No Apache, por exemplo, defina MaxKeepAliveRequests como 5.000
  3. Configure os servidores do bidder para monitorar as taxas de solicitação e fechar algumas das próprias conexões se estiverem processando muitas solicitações de maneira consistente em comparação com os pares.

Tratar sobrecargas corretamente

O ideal é que as cotas sejam altas o suficiente para que o bidder possa receber todas as solicitações que pode processar, mas não mais do que isso. Na prática, manter as cotas em níveis ideais é uma tarefa difícil, e sobrecargas acontecem por vários motivos: um back-end fica inativo durante os horários de pico, uma mudança na mistura de tráfego para que mais processamento seja necessário para cada solicitação ou um valor de cota seja definido muito alto. Consequentemente, vale a pena considerar o comportamento do proponente com o recebimento de muito tráfego.

Para acomodar mudanças de tráfego temporárias (de até uma semana) entre regiões (especialmente entre Ásia e oeste dos EUA e Leste e Oeste dos EUA), recomendamos um amortecimento de 15% entre o pico de sete dias e o QPS por local de operação.

Em termos de comportamento sob cargas pesadas, os bidders se enquadram em três categorias amplas:

O bidder "responde tudo"

Embora seja simples de implementar, esse proponente tem o pior resultado quando sobrecarregado. Ele simplesmente tenta responder a cada solicitação de lance recebida, não importa o que aconteça, enfileirando aquelas que não podem ser atendidas imediatamente. O cenário que acontece geralmente é assim:

  • À medida que a taxa de solicitação aumenta, as latências de solicitação também aumentam, até que todas as solicitações comecem a expirar.
  • As latências aumentam drasticamente à medida que as taxas de chamadas se aproximam do pico
  • A limitação é iniciada, reduzindo o número de chamadas permitidas
  • As latências começam a se recuperar, o que reduz a limitação
  • O ciclo começará novamente.

O gráfico de latência desse bidder é semelhante a um padrão muito íngreme de serra dente. Como alternativa, as solicitações em fila fazem com que o servidor comece a paginar memória ou faça outra coisa que cause uma lentidão de longo prazo, e as latências não se recuperam até que os horários de pico terminem, levando a taxas de chamadas reduzidas durante todo o período de pico. Em ambos os casos, menos chamadas são feitas ou respondidas do que se a cota tivesse sido simplesmente definida com um valor menor.

O proponente "erro na sobrecarga"

Ele aceita chamadas até uma determinada taxa e depois começa a retornar erros para algumas delas. Isso pode ser feito por meio de tempos limite internos, desativando a fila de conexões (controlada por ListenBackLog no Apache), implementando um modo de queda probabilístico quando a utilização ou as latências ficarem muito altas ou por algum outro mecanismo. Se o Google observar uma taxa de erro acima de 15%, começaremos a limitar. Ao contrário do bidder "responder tudo", esse "corta as perdas", o que permite uma recuperação imediata quando as taxas de solicitação diminuem.

O gráfico de latência desse bidder é semelhante a um padrão de serra e dente superficial durante sobrecargas, localizado próximo à taxa máxima aceitável.

O proponente "sem lance na sobrecarga"

Esse proponente aceita chamadas até uma determinada taxa e depois começa a retornar respostas "sem lance" para qualquer sobrecarga. Semelhante ao proponente "erro na sobrecarga", isso pode ser implementado de várias maneiras. A diferença aqui é que nenhum sinal é retornado ao Google, então nunca limitamos as chamadas. A sobrecarga é absorvida pelas máquinas de front-end, que só permitem o tráfego que elas podem processar para continuar até os back-ends.

O gráfico de latência desse proponente mostra um patamar que para (artificialmente) de paralelizar a taxa de solicitação em horários de pico e uma queda correspondente na fração de respostas que contêm um lance.

Recomendamos combinar a abordagem "erro na sobrecarga" com a abordagem "sem lance na sobrecarga" da seguinte maneira:

  • Provisione em excesso os front-ends e configure-os para causar erros na sobrecarga, para ajudar a maximizar o número de conexões às quais eles podem responder de alguma forma.
  • Ao enviar um erro de sobrecarga, as máquinas de front-end podem usar uma resposta automática "sem lance" e não precisam analisar a solicitação.
  • Implemente a verificação de integridade dos back-ends, de modo que, se nenhum tiver capacidade suficiente disponível, eles retornem uma resposta "sem lance".

Isso permite que alguma sobrecarga seja absorvida e dá aos back-ends a chance de responder exatamente a quantas solicitações conseguem processar. Você pode considerar isso como "sem lance na sobrecarga", com máquinas de front-end voltando para "erro na sobrecarga" quando as contagens de solicitações são significativamente maiores do que o esperado.

Se você tiver um proponente "responde tudo", considere transformá-lo em um proponente com "erro na sobrecarga". Para isso, ajuste o comportamento da conexão de modo que, na verdade, ele se recuse a ser sobrecarregado. Isso faz com que mais erros sejam retornados, mas reduz os tempos limite e impede que o servidor entre em um estado em que não pode responder a nenhuma solicitação.

Responder a pings

Surpreendentemente, garantir que seu proponente responda a solicitações de ping, mas não o gerenciamento de conexão por si, é surpreendentemente importante para a depuração. O Google usa solicitações de ping para verificação de integridade e depuração do status do bidder, do comportamento de fechamento de conexão, latência e muito mais. As solicitações de ping têm o seguinte formato:

Google

id: "\3503cg\3023P\364\230\240\270\020\255\002\231\314\010\362\347\351\246\357("
is_test: true
is_ping: true

JSON do OpenRTB

"id": "4YB27BCXimH5g7wB39nd3t"

Protobuf do OpenRTB

id: "7xd2P2M7K32d7F7Y50p631"

Lembre-se de que, ao contrário do que você pode esperar, a solicitação de ping não contém espaços de anúncio. Além disso, conforme detalhado acima, você não deve encerrar a conexão depois de responder a uma solicitação de ping.

Considerar o peering

Outra forma de reduzir a latência ou variabilidade da rede é fazer peering com o Google. O peering ajuda a otimizar o caminho do tráfego para chegar ao seu bidder. Os endpoints de conexão permanecem os mesmos, mas os links intermediários mudam. Consulte o Guia de peering para ver mais detalhes. A razão para pensar no peering como uma prática recomendada pode ser resumida da seguinte maneira:

  • Na Internet, os links de trânsito são escolhidos principalmente por meio do "roteamento da batata quente", que encontra o link mais próximo fora da rede que pode levar um pacote ao destino e o encaminha por meio desse link. Quando o tráfego passa por uma seção do backbone de um provedor com quem temos muitas conexões de peering, o link escolhido provavelmente está próximo de onde o pacote começa. Além disso, não temos controle sobre a rota que o pacote segue até o bidder. Por isso, ele pode ser devolvido para outros sistemas autônomos (redes) ao longo do caminho.

  • Por outro lado, quando há um contrato de peering direto, os pacotes sempre são enviados por um link de peering. Não importa a origem do pacote, ele passa por links pertencentes ao Google ou faz leases até chegar ao ponto de peering compartilhado, que precisa estar próximo do local do bidder. A viagem inversa começa com um curto salto até a rede do Google e permanece na rede do Google o restante do caminho. Manter a maior parte da viagem em uma infraestrutura gerenciada pelo Google garante que o pacote use uma rota de baixa latência e evita muita variabilidade potencial.

Enviar DNS estático

Recomendamos que os compradores sempre enviem um único resultado de DNS estático e dependam do Google para lidar com o envio de tráfego.

Confira duas práticas comuns dos servidores DNS dos bidders ao tentar balancear a carga ou gerenciar a disponibilidade:

  1. O servidor DNS envia um endereço ou um subconjunto de endereços em resposta a uma consulta e, em seguida, alterna essa resposta de alguma forma.
  2. O servidor DNS sempre responde com o mesmo conjunto de endereços, mas alterna a ordem dos endereços na resposta.

A primeira técnica é ruim no balanceamento de carga, já que há muito armazenamento em cache em vários níveis da pilha, e as tentativas de ignorar o armazenamento em cache provavelmente não vão conseguir os resultados preferidos também, já que o Google cobra o tempo de resolução de DNS do proponente.

A segunda técnica não alcança nenhum balanceamento de carga porque o Google seleciona aleatoriamente um endereço IP da lista de respostas do DNS para que a ordem da resposta não importa.

Se um bidder fizer uma alteração no DNS, o Google respeitará o TTL definido nos registros DNS, mas o intervalo de atualização permanece incerto.