Prácticas recomendadas para las aplicaciones de RTB

En esta guía, se explican las prácticas recomendadas que se deben tener en cuenta cuando se desarrollan aplicaciones de acuerdo con el Protocolo de RTB.

Cómo administrar conexiones

Mantén vivas las conexiones

Establecer una conexión nueva aumenta las latencias y requiere muchos más recursos en ambos extremos que reutilizar una existente. Si cierras menos conexiones, puedes reducir la cantidad de conexiones que se deben volver a abrir.

Primero, cada conexión nueva requiere un recorrido de ida y vuelta adicional de la red para establecerse. Debido a que establecemos conexiones a pedido, la primera solicitud en una conexión tiene un plazo efectivo más corto y es más probable que se agote el tiempo de espera que las solicitudes posteriores. Cualquier tiempo de espera adicional aumenta la tasa de error, lo que puede restringir al ofertante.

En segundo lugar, muchos servidores web generan un subproceso de trabajo dedicado para cada conexión establecida. Esto significa que, para cerrar y volver a crear la conexión, el servidor debe cerrar y descartar un subproceso, asignar uno nuevo, hacer que sea ejecutable y crear el estado de conexión antes de procesar la solicitud. Se trata de una sobrecarga innecesaria.

Evita cerrar conexiones

Primero, ajusta el comportamiento de la conexión. La mayoría de los valores predeterminados del servidor se adaptan para entornos con grandes cantidades de clientes, cada uno de los cuales realiza una pequeña cantidad de solicitudes. En el caso de las RTB, por el contrario, un pequeño grupo de máquinas envía solicitudes en nombre de una gran cantidad de navegadores, en términos relativos. En estas condiciones, tiene sentido volver a usar las conexiones tantas veces como sea posible. Te recomendamos que establezcas lo siguiente:

  • Tiempo de espera de inactividad de 2.5 minutos.
  • Cantidad máxima de solicitudes en una conexión al valor más alto posible.
  • Cantidad máxima de conexiones con el valor más alto que puede admitir la RAM y tener cuidado de verificar que la cantidad de conexiones no se acerque demasiado a ese valor.

En Apache, por ejemplo, esto implicaría configurar KeepAliveTimeout en 150, MaxKeepAliveRequests en cero y MaxClients en un valor que depende del tipo de servidor.

Una vez que se ajuste tu comportamiento de conexión, también debes asegurarte de que el código del ofertante no cierre las conexiones innecesariamente. Por ejemplo, si tienes un código de frontend que muestra una respuesta predeterminada “sin oferta” en caso de errores de backend o tiempos de espera, asegúrate de que el código muestre su respuesta sin cerrar la conexión. De esa manera, evitas una situación en la que, si se sobrecarga tu ofertante, las conexiones comienzan a cerrarse y la cantidad de tiempos de espera aumenta, lo que provoca que se limite al ofertante.

Mantén las conexiones en equilibrio

Si Authorized Buyers se conecta a los servidores del ofertante a través de un servidor proxy, es posible que las conexiones se desequilibran con el tiempo porque, con solo conocer la dirección IP del servidor proxy, Authorized Buyers no puede determinar qué servidor del ofertante recibe cada solicitud de oferta. Con el tiempo, a medida que Authorized Buyers establece y cierra conexiones, y se reinician los servidores del ofertante, la cantidad de conexiones asignadas a cada una puede volverse muy variable.

Cuando algunas conexiones se usan mucho, otras conexiones abiertas pueden permanecer inactivas en gran medida porque no son necesarias en ese momento. A medida que cambia el tráfico de Authorized Buyers, las conexiones inactivas pueden volverse activas y las conexiones activas pueden quedar inactivas. Esto puede provocar cargas desiguales en los servidores de ofertantes si las conexiones están mal agrupadas en clústeres. Google intenta evitar esto mediante el cierre de todas las conexiones después de 10,000 solicitudes para volver a balancear automáticamente las conexiones calientes con el tiempo. Si aún observas que el tráfico se desequilibra en tu entorno, puedes seguir estos pasos:

  1. Selecciona el backend por solicitud en lugar de una vez por conexión si usas proxies de frontend.
  2. Especifica una cantidad máxima de solicitudes por conexión si haces proxy con conexiones a través de un firewall o balanceador de cargas de hardware y la asignación se fija una vez que se establecen las conexiones. Ten en cuenta que Google ya especifica un límite superior de 10,000 solicitudes por conexión, por lo que solo deberías proporcionar un valor más estricto si aún encuentras conexiones calientes que se agrupan en tu entorno. En Apache, por ejemplo, configura MaxKeepAliveRequests en 5,000.
  3. Configura los servidores del ofertante para supervisar sus porcentajes de solicitudes y cerrar algunas de sus propias conexiones si administran demasiadas solicitudes de forma constante en comparación con sus pares.

Maneja la sobrecarga de manera elegante

Idealmente, las cuotas se establecerían lo suficientemente altas para que tu ofertante pueda recibir todas las solicitudes que pueda procesar, pero no más que eso. En la práctica, mantener las cuotas en niveles óptimos es una tarea difícil, y se producen sobrecargas por diversos motivos: un backend que funciona durante las horas pico, una combinación de tráfico que cambia de manera que se requiere más procesamiento para cada solicitud o un valor de cuota demasiado alto. Por lo tanto, es útil tener en cuenta cómo se comportará tu ofertante si ingresa demasiado tráfico.

Para adaptarse a los cambios temporales de tráfico (hasta una semana) entre las regiones (especialmente entre Asia y el oeste de EE.UU., y este y oeste de EE.UU.), recomendamos una amortiguación del 15% entre el máximo de 7 días y las QPS por ubicación de operación.

En términos de comportamiento bajo cargas pesadas, los ofertantes se dividen en tres categorías amplias:

El ofertante "responder a todo"

Si bien es fácil de implementar, este ofertante tiene el peor rendimiento cuando está sobrecargado. Simplemente intenta responder a cada solicitud de oferta que llega, sin importar qué sucede, y pone en cola las que no se pueden entregar de inmediato. La situación que surge a menudo es similar a la siguiente:

  • A medida que aumenta el porcentaje de solicitudes, también lo hacen las latencias, hasta que todas las solicitudes comiencen a agotar el tiempo de espera.
  • Las latencias aumentan abruptamente a medida que los porcentajes de solicitudes de oferta se acercan al punto máximo
  • Se activa la regulación, que reduce considerablemente la cantidad de solicitudes de oferta permitidas.
  • Las latencias comienzan a recuperarse, lo que provoca que se reduzca la limitación
  • El ciclo comienza de nuevo.

El gráfico de latencia de este ofertante se asemeja a un patrón de dientes de sierra muy empinado. Como alternativa, las solicitudes en cola hacen que el servidor comience a ubicar la memoria o realice otra acción que provoque una demora a largo plazo, y las latencias no se recuperan en absoluto hasta que terminan las horas pico, lo que genera una disminución de las tasas de llamadas durante todo el período de tráfico máximo. En cualquier caso, se realizan o responden menos solicitudes de oferta que si la cuota se hubiera establecido en un valor más bajo.

El ofertante "error en la sobrecarga"

Este ofertante acepta solicitudes de oferta hasta una tasa determinada y, luego, comienza a mostrar errores para algunas solicitudes. Esto se puede hacer a través de tiempos de espera internos, deshabilitar la cola de conexiones (controlada por ListenBackLog en Apache), implementar un modo de abandono probabilístico cuando el uso o las latencias son demasiado altos, o algún otro mecanismo. Si Google observa una tasa de error superior al 15%, comenzaremos a limitarla. A diferencia del ofertante que ofrece "responder a todo", este ofertante "recorta sus pérdidas", lo que le permite recuperarla de inmediato cuando bajan las tasas de solicitudes.

El gráfico de latencia de este ofertante se asemeja a un patrón superficial de dientes de sierra durante las sobrecargas, localizado alrededor de la tasa máxima aceptable.

El ofertante "sin oferta por sobrecarga"

Este ofertante acepta solicitudes de oferta hasta una tasa determinada y, luego, comienza a mostrar respuestas "no-bid" para cualquier sobrecarga. Al igual que el ofertante de "error en la sobrecarga", esto se puede implementar de varias maneras. La diferencia aquí es que no se muestra ningún indicador a Google, por lo que nunca limitaremos la cantidad de solicitudes de oferta. Las máquinas de frontend absorben la sobrecarga, que solo permiten que el tráfico que pueden manejar continúe hacia los backends.

El gráfico de latencia de este ofertante muestra una meseta que (de forma artificial) se detiene en paralelo a la tasa de solicitudes en horas pico y una disminución correspondiente en la fracción de respuestas que contienen una oferta.

Recomendamos combinar el enfoque “error en sobrecarga” con el enfoque “sin oferta en sobrecarga” de la siguiente manera:

  • Aprovisiona en exceso los frontends y configúralos en un modo de error durante la sobrecarga para maximizar la cantidad de conexiones a las que pueden responder de alguna forma.
  • Cuando se producen errores por sobrecarga, las máquinas de frontend pueden usar una respuesta estándar “no-bid” y no necesitan analizar la solicitud en absoluto.
  • Implementar la verificación de estado de los backends para que, si ninguno tiene suficiente capacidad disponible, se muestre una respuesta “no-bid”.

Esto permite que se absorba parte de la sobrecarga y que los backends tengan la oportunidad de responder con exactitud a todas las solicitudes que puedan controlar. Puedes pensar en esto como “sin ofertas por sobrecarga”, con máquinas de frontend que recurren al “error en la sobrecarga” cuando los recuentos de solicitudes son significativamente más altos de lo esperado.

Si tienes un ofertante que "responde a todo", considera transformarlo en un ofertante de "error en sobrecarga" mediante el ajuste del comportamiento de la conexión para que, en efecto, rechace la sobrecarga. Si bien esto provoca que se muestren más errores, reduce los tiempos de espera y evita que el servidor llegue a un estado en el que no pueda responder a ninguna solicitud.

Responde a pings

Sorprendentemente es importante para la depuración asegurarte de que tu ofertante pueda responder a las solicitudes de ping, sin tener que administrar las conexiones en sí. Google usa solicitudes de ping para verificar el estado y depurar el estado del ofertante, el comportamiento de cierre de la conexión, la latencia y mucho más. Las solicitudes de ping tienen el siguiente 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 de OpenRTB

"id": "4YB27BCXimH5g7wB39nd3t"

OpenRTB Protobuf

id: "7xd2P2M7K32d7F7Y50p631"

Ten en cuenta que, a diferencia de lo que podría esperarse, la solicitud de ping no contiene espacios publicitarios. Además, como se detallado más arriba, no debes cerrar la conexión después de responder a una solicitud de ping.

Considera el intercambio de tráfico

Otra forma de reducir la latencia o la variabilidad de la red es intercambiar tráfico con Google. El intercambio de tráfico ayuda a optimizar la ruta de acceso que toma el tráfico para llegar a su ofertante. Los extremos de conexión permanecen iguales, pero los vínculos intermedios cambian. Consulta la Guía de intercambio de tráfico para obtener más detalles. La razón para considerar el intercambio de tráfico como una práctica recomendada se puede resumir de la siguiente manera:

  • En Internet, los vínculos de tránsito se eligen principalmente a través del "enrutamiento de papa caliente", que encuentra el vínculo más cercano fuera de nuestra red que puede llevar un paquete a su destino y enruta el paquete a través de ese vínculo. Cuando el tráfico desvía una sección de la red troncal que pertenece a un proveedor con el que tenemos muchas conexiones de intercambio de tráfico, es probable que el vínculo elegido esté cerca de donde comienza el paquete. Más allá de ese punto, no tenemos control de la ruta que sigue el paquete al ofertante, por lo que puede rebotar a otros sistemas autónomos (redes) durante el proceso.

  • Por el contrario, cuando se implementa un acuerdo de intercambio de tráfico directo, los paquetes siempre se envían a través de un vínculo de intercambio de tráfico. Sin importar dónde se origine el paquete, este recorre los vínculos que Google posee o alquila hasta llegar al punto de intercambio de tráfico compartido, que debe estar cerca de la ubicación del ofertante. El viaje inverso comienza con un salto a la red de Google y permanece en ella el resto del camino. Conservar la mayor parte del viaje en la infraestructura administrada por Google garantiza que el paquete tome una ruta de latencia baja y evita una gran variabilidad potencial.

Envía un DNS estático

Recomendamos que los compradores siempre envíen un único resultado de DNS estático a Google y confíen en Google para administrar la entrega del tráfico.

Estas son dos prácticas comunes de los servidores DNS de los ofertantes cuando intentan balancear las cargas o administrar la disponibilidad:

  1. El servidor DNS distribuye una dirección, o un subconjunto de direcciones, en respuesta a una consulta y, luego, rota esta respuesta de alguna manera.
  2. El servidor DNS siempre responde con el mismo conjunto de direcciones, pero cambia el orden de las direcciones en la respuesta.

La primera técnica es deficiente en el balanceo de cargas, ya que hay mucho almacenamiento en caché en varios niveles de la pila, y es probable que los intentos de omitir el almacenamiento en caché no obtengan los resultados preferidos, ya que Google cobra el tiempo de resolución de DNS al ofertante.

La segunda técnica no logra el balanceo de cargas en absoluto, ya que Google selecciona de forma aleatoria una dirección IP de la lista de respuestas de DNS, por lo que el orden de la respuesta no importa.

Si un ofertante realiza un cambio de DNS, Google respetará el TTL(tiempo de actividad) que se estableció en sus registros DNS, pero el intervalo de actualización sigue siendo incierto.