Original: https://jungrok5.github.io/mmo-lag-anatomy/es/ Página de cada causa: https://jungrok5.github.io/mmo-lag-anatomy/es/c/[ID de la causa].html # Libro blanco del lag en juegos: base de conocimiento Generado automáticamente (2026-10-03, `node tools/export.cjs`). No editar a mano: para cambiar algo, modificar src/js/ y volver a exportar. 228 causas y 135 términos. Cada causa se identifica por su **ID**. Añadiendo `#c-ID` a la dirección del sitio se llega a su ficha. ## Códigos de responsable | Código | Equipo | Responsable | Alcance | |---|---|---|---| | cli | Equipo de desarrollo | Desarrollo de cliente | Código del cliente del juego: frames, GC y carga, interpolación, extrapolación y predicción, y la parte de red del cliente (incluidos el envío de heartbeats y la reconexión automática) | | srv | Equipo de desarrollo | Desarrollo de servidor | Código del servidor del juego: ticks, hilos y locks, diseño del netcode, gestión de conexiones (bucle de accept y argumentos de listen), respuesta a heartbeats y limpieza de conexiones caídas, opciones de socket, diseño de consultas y transacciones | | net | Equipo de infraestructura | Infraestructura de red | Enlaces y equipos de red del centro de datos (switches, routers, firewalls, balanceadores de carga, protección DDoS), ACL de red, enrutamiento de VPC y balanceadores de carga en la nube, ISP y peering | | sys | Equipo de infraestructura | Infraestructura de servidores | Servidores físicos e instancias en la nube (incluidos grupos de seguridad y seguimiento de conexiones), configuración del SO y del kernel, NIC, entornos de despliegue y monitoreo | | dba | Equipo de infraestructura | Infraestructura de BD | Servidores y almacenamiento de BD, configuración, replicación y copias de seguridad de la BD, servidores de caché | | ext | Externo | Externo | PC y red doméstica del jugador, tramo del ISP (fuera de nuestros contratos), proveedores de nube. Como no se puede arreglar directamente, se actúa con indicaciones, solicitudes y soluciones alternativas | En cada causa, el “responsable principal” es quien elimina la causa raíz, y “también” indica quién tiene tareas concretas. ## Síntomas - **Tirones** (`stutter`, también se dice: stuttering, se traba, va a saltos, parecen caídas de FPS): El movimiento pierde fluidez: se para un instante y sigue, una y otra vez. Si el ping se ve normal, lo más probable es un problema de frames en tu PC (cliente o SO); si el ping sube y baja, lo más probable es jitter del Wi-Fi o de la conexión. Eso sí, el ping que muestra el juego suele medirse dentro del bucle del juego, que se ejecuta una vez por frame, así que un pico de frametime también puede disparar la cifra de ping. - **Teletransporte** (`teleport`, también se dice: warp, teleport, se corta y salta a otro lugar): Un personaje pasa de golpe a una posición lejana sin recorrer el camino. Casi siempre significa que dejaron de llegar paquetes durante un rato. Hay que revisar pérdida de paquetes, cortes breves de la conexión, detenciones del servidor y fallos de extrapolación. Si todos se ven bien y solo uno salta, lo primero que hay que sospechar es la conexión de ese jugador. - **Rubber banding** (`rubber`, también se dice: me tira para atrás, efecto goma, vuelvo a la posición anterior): Tu personaje avanza y de pronto vuelve arrastrado al punto por el que acaba de pasar. Lo que muestra tu pantalla (predicción) y lo que validó el servidor no coinciden. O tu input no llegó al servidor (pérdida), o la validación de movimiento del servidor lo cortó, o el cliente y el servidor calculan el movimiento de forma distinta. - **Cámara rápida** (`burst`, también se dice: todo pasa de golpe, avance rápido, se pone al día de una vez): Cuando la pantalla detenida vuelve a moverse, los movimientos, golpes y daños acumulados pasan todos juntos a toda velocidad. En algún punto se acumularon paquetes y se liberaron de golpe. Los casos típicos son la espera por una retransmisión TCP, el servidor recuperando el retraso y el cliente atrasado en su procesamiento. - **Cámara lenta** (`slowmo`, también se dice: el mundo se ralentiza, todo va lento, slow motion): Todo se mueve despacio. El lanzamiento de habilidades y el movimiento de los monstruos parecen estirados. Según cómo esté diseñado el servidor, también puede verse a velocidad normal pero con tirones o teletransporte. El servidor no termina los ticks a tiempo. La conexión está bien, así que el ping medido fuera del juego no cambia; el ping del juego puede subir un poco si incluye la espera de procesamiento en el servidor. Hay que revisar picos de jugadores, cálculo de visibilidad, broadcast y falta de memoria. - **Input lag** (`delay`, también se dice: responde tarde, va pesado, los controles no responden bien): Pasa un tiempo desde que presionas hasta que ves el resultado. La imagen en sí puede verse fluida. El tiempo de ida y vuelta (ping) es alto, o hay una cola acumulada en algún punto. Hay que revisar la distancia, la cola del router, Nagle (la función de TCP que junta paquetes pequeños antes de enviarlos) y las colas del servidor. Si el ping es bajo y aun así todo va pesado, hay que mirar tu PC (V-Sync, FPS bajos) o un diseño que espera la confirmación del servidor en cada acción (capítulo sobre modelos de netcode). - **Congelamiento** (`freeze`, también se dice: se congela, se queda colgado, no responde, freeze): Todo lo que hay en pantalla se detiene un momento (de 0.5 s a varios segundos) y luego vuelve a moverse. Se detuvo el servidor entero (GC, deadlock, llamadas síncronas), la conexión se cortó un momento o se detuvo tu PC. - **Acción perdida / rollback** (`dropped`, también se dice: la habilidad no salió, me devolvió el objeto, el intercambio falló): Una acción que hiciste claramente se anula como si nunca hubiera pasado, o el resultado se revierte mucho después. La solicitud se perdió (pérdida de paquetes, cola desbordada), el servidor resolvió algo distinto de lo que veías (diferencia en el momento de la validación, rechazo después del feedback anticipado) o falló el guardado (bloqueo o fallo de la BD, crash del servidor). - **Desconexión** (`disconnect`, también se dice: me echa del juego, me saca del servidor, se cae la conexión, “Se perdió la conexión con el servidor”): En plena partida se corta la conexión y vuelves a la pantalla de inicio de sesión o a la ventana de reconexión. No llegó ningún paquete dentro del timeout. Hay que revisar cortes largos de la conexión, timeouts por inactividad, crashes o reinicios del servidor, y que el servidor o tu PC se hayan detenido más tiempo que el timeout (una carga larga). Si el juego se cerró sin ningún aviso, primero hay que sospechar de un cierre forzado del cliente (crash, falta de memoria) y después de la conexión. - **No conecta / carga infinita** (`noconnect`, también se dice: no me deja entrar, no puedo iniciar sesión, se queda cargando): No logras entrar al juego, o te quedas detenido en la pantalla de carga o de entrada. Lo que acepta las conexiones nuevas (la cola de conexiones pendientes del servidor, el firewall, el servidor de login, la BD) está lleno. Es especialmente frecuente justo después de un mantenimiento. - **Entidades invisibles / fantasma** (`invisible`, también se dice: no veo al NPC, personajes invisibles, monstruos muertos que siguen de pie): Un NPC, monstruo o jugador que debería estar ahí falta solo en tu pantalla, o una entidad que ya desapareció sigue solo en tu pantalla. Normalmente se perdió un paquete concreto o falló el dibujado de la entidad. La velocidad tiene poco que ver. Hay que revisar diferencias de canal o de phasing, mensajes de aparición o desaparición perdidos, mensajes descartados durante la carga y fallos al cargar assets. La pista decisiva es si la entidad aparece al salir de su rango de visión y volver. ## Los cuatro factores - **Latencia** (`lat`, Latency): Por la distancia, las colas y el tiempo de procesamiento, todos los paquetes llegan con el mismo retraso. Cómo lo afronta el juego: La predicción y el feedback anticipado muestran tus acciones al instante, y el servidor las resuelve rebobinando al momento que veías (compensación de lag). - **Jitter** (`jit`, Jitter): La media está bien, pero unos paquetes llegan antes y otros después. Lo provocan el Wi-Fi, las conexiones congestionadas y las CPU saturadas. Cómo lo afronta el juego: Se acumulan unos cuantos paquetes en el búfer de interpolación y se dibujan a ritmo constante. Si el jitter supera el búfer, ya no se puede disimular. - **Pérdida de paquetes** (`loss`, Packet loss): Las colas desbordadas, las interferencias de radio y los equipos de red defectuosos descartan paquetes. Un corte breve de la conexión también es una pérdida de muchos paquetes seguidos. Cómo lo afronta el juego: Los juegos con UDP rellenan los huecos con interpolación y extrapolación, y envían tus inputs repetidos para cubrir la pérdida de uno o dos. TCP no entrega al juego los paquetes posteriores hasta recibir de nuevo el perdido. - **Detención** (`stall`, Stall): El tick del servidor se retrasa o se detiene (GC, locks, llamadas síncronas, sobrecarga), o se detienen los frames en tu PC. Ocurre aunque la conexión esté perfecta. Cómo lo afronta el juego: El trabajo acumulado durante la detención se recupera de golpe, se salta o se deja avanzar más despacio. ## Causas ### L1 Proceso del juego en el cliente (causas: 16) #### cg-hitch · Pico de frametime · Frame hitch Calcular un frame tarda varias veces más de lo normal y la imagen se detiene un instante. - Por qué → Efecto → En pantalla: Una avalancha de efectos de habilidades, spawns masivos o una actualización completa de la UI se concentran en un solo frame → El frame no termina en 16.7 ms y tarda 50–300 ms → La imagen se detiene un instante y en el frame siguiente todo se mueve de golpe - Síntomas: Tirones, Congelamiento / Factores: Detención - A quién: Solo yo / Cuándo: Cuando se junta mucha gente, Al hacer ciertas acciones, De vez en cuando, al azar - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Repartir el trabajo pesado entre varios frames, localizar con un profiler los frames con picos, limitar el número de efectos. - Cifras de referencia: Un frame a 60 FPS dura 16.7 ms. Con un solo frame de más de 50 ms, es fácil que el jugador sienta que el juego “se trabó”. - En el gráfico: Picos aleatorios (Tiempo de frame) - Dónde mirar: Grabar con PresentMon, durante la partida, el tiempo de frame (FrameTime) y el tiempo que la CPU y la GPU dedicaron a ese frame (CPUBusy y GPUBusy). En dispositivos móviles, las métricas de sesiones lentas y renderizado lento de Android vitals - Se confirma si: Los momentos en que el tiempo de frame, normalmente cerca de 16.7 ms, se dispara por encima de 50 ms coinciden con efectos de habilidades, spawns masivos o actualizaciones completas de la UI, y en esos momentos el ping no cambia - Se descarta si: Si el tiempo de frame es estable pero solo los demás personajes dan tirones, apunta a la red, como en “Búfer de interpolación ausente o demasiado corto”. Si los picos llegan a intervalos regulares, revisar primero “Recolección de basura (GC) en el cliente” - Se verifica con: En el entorno del jugador - Fuentes: - [Slow rendering](https://developer.android.com/topic/performance/vitals/render) · Android (Google) · Para llegar a 60 FPS hay que dibujar cada frame en menos de 16 ms; si se retrasa, se saltan frames y se ven tirones (jank) - [Slow Sessions (games only)](https://developer.android.com/topic/performance/issues/slow-session) · Android (Google) · Android vitals considera lento un frame del juego que supera los 50 ms (20 FPS) o los 34 ms (30 FPS) - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · FrameTime (tiempo de CPU entre frames), CPUBusy y GPUBusy (tiempo que la CPU y la GPU dedicaron a generar ese frame) #### cg-gc · Recolección de basura (GC) en el cliente · Client GC (Unity C#, Unreal, Lua) El juego entero se detiene mientras se recupera la memoria ya usada y desechada (basura). Lo característico son tirones a intervalos regulares. - Por qué → Efecto → En pantalla: En cada frame se crean y se desechan cadenas de texto, arrays y listas temporales → Cuando se acumula basura, el GC detiene el hilo principal para liberarla → Tirones regulares cada pocos segundos o cada varias decenas de segundos - Síntomas: Tirones, Congelamiento / Factores: Detención - A quién: Solo yo / Cuándo: A intervalos regulares, Cuando se junta mucha gente - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Reducir las asignaciones (evitar concatenar cadenas, LINQ y capturas en lambdas), usar pools de objetos, mantener activado el GC incremental (opción predeterminada desde Unity 2020), forzar el GC por adelantado en momentos en que una pausa no molesta, como las pantallas de carga. - Cifras de referencia: Normalmente de varios ms a 100 ms por recolección, y más en teléfonos de gama baja o en juegos que usan mucha memoria (en la simulación, unos 150–170 ms). El GC de Unity revisa todo el heap cada vez que se ejecuta, así que cuanta más memoria usa el juego, más dura. - En el gráfico: Picos periódicos (Tiempo de frame, momentos de ejecución del GC) - Dónde mirar: En una build de desarrollo, los marcadores GC.Collect y GC.Alloc del Profiler de Unity. En Unreal, stat GC y stat Hitches (registra en el log los frames que superan el tiempo fijado en t.HitchFrameTimeThreshold) - Se confirma si: Cada frame con pico tiene un tramo de GC.Collect de duración parecida a la del pico, y los picos se repiten a intervalos regulares de unos segundos a varias decenas de segundos. Donde hay mucha gente, GC.Alloc por frame aumenta - Se descarta si: Si los frames con pico no tienen tramo de GC: “Carga síncrona y compilación de shaders en el hilo principal” o “Carga de renderizado de multitudes” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Es habitual en clientes que usan C#, como los de Unity. Los principales culpables son el código que vuelve a crear en cada frame las cadenas del log de combate, los números de daño y los textos de la UI. Si los tirones solo aparecen donde hay mucha gente, hay código que genera basura en proporción al número de jugadores. El GC incremental reparte la recolección en pequeñas porciones por frame (3 ms por defecto en Unity), pero si el juego genera basura más rápido de lo que se recolecta, al final se detiene de golpe. Unreal Engine también tiene su propio GC, que limpia los objetos del juego que ya no se usan. Depende de la versión del motor y de la configuración, pero con los valores predeterminados se ejecuta aproximadamente cada minuto y puede provocar un tirón por minuto. En los clientes cuyas reglas de juego están escritas en un lenguaje de scripting como Lua, el GC de ese lenguaje también se ejecuta por separado. - Fuentes: - [Garbage collection modes](https://docs.unity3d.com/Manual/performance-incremental-garbage-collection.html) · Unity · El GC incremental es la opción predeterminada y reparte la recolección entre varios frames; si se desactiva, el hilo principal se detiene mientras se revisa todo el heap, y la pausa puede llegar a cientos de ms - [Scripting.GarbageCollector.CollectIncremental](https://docs.unity3d.com/ScriptReference/Scripting.GarbageCollector.CollectIncremental.html) · Unity · El objetivo predeterminado del tiempo que el GC incremental usa en cada porción (time slice) es de 3 ms (incrementalTimeSliceNanoseconds) - [Garbage Collection Settings in the Unreal Engine Project Settings](https://dev.epicgames.com/documentation/en-us/unreal-engine/garbage-collection-settings-in-the-unreal-engine-project-settings) · Epic Games · Ajuste que hace que el GC de Unreal se ejecute a un intervalo fijo (Time Between Purging Pending Kill Objects, en segundos). Este documento no indica el valor predeterminado - [Profiler markers reference](https://docs.unity3d.com/Manual/profiler-markers.html) · Unity · GC.Collect: tramo en que el código del programa se detiene durante la recolección de basura (de menos de 1 ms a cientos de ms); GC.Alloc: asignación en el heap administrado - [Stat Commands in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/stat-commands-in-unreal-engine) · Epic Games · stat GC (estadísticas de recolección de basura), stat Hitches (registra en el log los frames que superan t.HitchFrameTimeThreshold) #### cg-sync-load · Carga síncrona y compilación de shaders en el hilo principal · Synchronous asset load, shader compile El juego se detiene para leer archivos y crear shaders justo antes de dibujar zonas, monstruos o efectos que aparecen por primera vez. - Por qué → Efecto → En pantalla: Entrar en una zona nueva o ver por primera vez una habilidad, un equipamiento o un monstruo → El hilo principal espera a que terminen la lectura de archivos y la compilación de shaders → Se detiene 0.1–1 s solo la primera vez; a partir de la segunda va bien - Síntomas: Congelamiento, Tirones / Factores: Detención - A quién: Solo yo / Cuándo: Al moverse o cambiar de zona, Al hacer ciertas acciones - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Carga asíncrona, precarga (prewarming), compilar los shaders por adelantado en la pantalla de carga o en la primera ejecución, aprovechar las pantallas de carga. - Cifras de referencia: Compilar un shader lleva decenas de ms, y a veces más de 100 ms. Cargar una textura lleva de decenas a cientos de ms según la velocidad del almacenamiento. - En el gráfico: Avalancha tras la apertura (Número de picos de frametime (justo después de un parche o una actualización de drivers)) - Dónde mirar: Grabar con PresentMon dos veces el mismo recorrido y comparar la primera visita con la segunda. En una build de desarrollo, en Unreal activar r.PSOPrecache.Validation y revisar stat PSOPrecache y “PSO PRECACHING MISS” en el log; en Unity, los tramos de carga y de shaders de los frames con pico en la vista Timeline del Profiler - Se confirma si: Picos de 0.1–1 s solo en sitios nuevos o con habilidades usadas por primera vez, que desaparecen la segunda vez. Los reportes se concentran justo después de un parche o de una actualización del driver gráfico y luego bajan - Se descarta si: Si hay picos en el mismo sitio cada vez, el problema no es la caché de shaders. Si se repiten en cada desplazamiento solo en PC con almacenamiento lento: “Almacenamiento lento que retrasa el streaming de assets”; si la memoria dedicada de la GPU está llena: “Falta de memoria gráfica (VRAM)” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: En PC, el driver gráfico guarda en la caché de shaders cada shader que compila y luego lo reutiliza. Por eso, justo después de actualizar el driver gráfico o de un parche del juego, esa caché se invalida y hasta quien jugaba bien vuelve a tener tirones durante un tiempo. El reporte típico es “después del parche se traba la primera vez que voy a cada sitio”. - Fuentes: - [Shader loading](https://docs.unity3d.com/Manual/shader-loading.html) · Unity · La primera vez que se usa una variante de shader, el driver gráfico la compila para la GPU y puede provocar una pausa visible; lo ya compilado queda en caché y no vuelve a provocar pausas - [Optimizing Rendering With PSO Caches in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/optimizing-rendering-with-pso-caches-in-unreal-engine) · Epic Games · Crear el estado de pipeline (PSO) en el momento en que se necesita puede tardar más de 100 ms, así que hay que crearlo por adelantado - [Direct3D 12 Return Codes](https://learn.microsoft.com/en-us/windows/win32/direct3d12/d3d12-graphics-reference-returnvalues) · Microsoft · D3D12_ERROR_DRIVER_VERSION_MISMATCH: una caché de PSO creada con otra versión del driver no se puede reutilizar (hay que recompilar tras actualizar el driver) - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Graba el tiempo de cada frame con FrameTime (tiempo de CPU entre frames) - [PSO Precaching for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/pso-precaching-for-unreal-engine) · Epic Games · Al activar r.PSOPrecache.Validation, stat PSOPrecache muestra estadísticas de los PSO que no se precargaron y el log registra “PSO PRECACHING MISS”; si crear un PSO en tiempo de ejecución supera los 20 ms (valor predeterminado), cuenta como tirón (hitch) #### cg-asset-stream · Almacenamiento lento que retrasa el streaming de assets · Slow storage stalls asset streaming En un almacenamiento lento como un HDD, la lectura de texturas y modelos de un mundo abierto no sigue el ritmo del desplazamiento, así que las entidades aparecen tarde o el juego da tirones mientras espera la lectura. - Por qué → Efecto → En pantalla: Moverse rápido en montura o teletransportarse, o entrar en un sitio con mucha gente, hace que se necesiten muchas texturas y modelos nuevos a la vez → Un almacenamiento lento como un HDD no lee a la velocidad necesaria, las solicitudes de lectura se acumulan y algunas cargas hacen esperar al hilo principal hasta que terminan → Texturas borrosas durante un rato, edificios y personajes que aparecen tarde, y tirones o congelamientos mientras se espera la lectura - Síntomas: Entidades invisibles / fantasma, Tirones, Congelamiento / Factores: Detención - A quién: Solo yo / Cuándo: Al moverse o cambiar de zona, Cuando se junta mucha gente - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Externo (Externo) - Tareas (Equipo de desarrollo): Streaming asíncrono que no haga esperar al hilo principal, precarga según la dirección y la velocidad de desplazamiento, mostrar primero una resolución baja (mipmaps) o modelos simples y sustituirlos después, limitar brevemente la velocidad de desplazamiento o usar una pantalla de carga si el streaming se retrasa durante un desplazamiento rápido, indicar en los requisitos mínimos y recomendados si hace falta un SSD. - Tareas (Externo): Indicar a los jugadores que instalen el juego en un SSD y que revisen si en el mismo disco hay descargas o análisis del antivirus en curso. - Cifras de referencia: Según Microsoft, los discos duros antiguos leen decenas de MB por segundo y los SSD NVMe, varios GB por segundo, y los juegos de la generación anterior dedicaban al streaming unos 50 MB por segundo. Si un juego pensado para la velocidad de un SSD, que lee mucho más que eso, se ejecuta en un HDD, es fácil que la lectura no siga el ritmo del desplazamiento. - En el gráfico: Alto solo en algunos (Número de picos de frametime (por tipo de almacenamiento), latencia de lectura del disco) - Dónde mirar: Registrar a la vez, durante un desplazamiento rápido, PhysicalDisk\Avg. Disk sec/Read (tiempo medio de una lectura) y Current Disk Queue Length del Monitor de rendimiento de Windows, junto con el tiempo de frame de PresentMon. En una build de desarrollo, stat Streaming y stat AsyncLoad en Unreal, y la advertencia AssetBundle.asset/allAssets del Profiler de Unity (se pide el resultado antes de que termine la carga y el hilo principal espera) - Se confirma si: Al desplazarse rápido, la latencia de lectura y la cola del disco se disparan, y en ese mismo momento hay picos de frame o texturas y entidades que aparecen tarde. Con la misma escena en un SSD, desaparece - Se descarta si: Si el disco está desocupado y las texturas se ven borrosas: “Falta de memoria gráfica (VRAM)”. Si desde la segunda visita al mismo sitio todo va bien: “Carga síncrona y compilación de shaders en el hilo principal” - Se verifica con: En el entorno del jugador - Para saber más: Si solo se detiene la primera vez y después va bien, se parece más a “Carga síncrona y compilación de shaders en el hilo principal”; si se repite en cada desplazamiento solo en PC con almacenamiento lento, es esta causa. “Falta de memoria gráfica (VRAM)”, en la que las texturas se descargan y se vuelven a subir porque falta memoria gráfica, también produce texturas borrosas, así que hay que mirar a la vez la espera de lectura del disco y el uso de memoria gráfica. El análisis en tiempo real del antivirus también puede intervenir cada vez que se abre un archivo del juego y retrasar aún más la lectura. - Fuentes: - [DirectStorage is coming to PC](https://devblogs.microsoft.com/directx/directstorage-is-coming-to-pc/) · Microsoft · Los discos duros antiguos leen decenas de MB por segundo y los SSD NVMe, varios GB por segundo; el presupuesto de streaming de assets de los juegos de la generación anterior rondaba los 50 MB por segundo; los juegos de mundo abierto leen y descartan en tiempo real el paisaje lejano mientras el jugador se desplaza - [Texture and mesh loading](https://docs.unity3d.com/Manual/LoadingTextureandMeshData.html) · Unity · La subida síncrona a la GPU lee y sube los datos en un solo frame en el hilo principal y causa una pausa visible; la subida asíncrona hace el streaming a lo largo de varios frames - [Texture Streaming Overview for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/texture-streaming-overview-for-unreal-engine) · Epic Games · El streamer sube y baja la resolución de las texturas (mips) según el punto de vista; la mayor parte del cálculo se hace en hilos de trabajo asíncronos y se cargan primero los mips visibles en pantalla - [Profiler markers reference](https://docs.unity3d.com/Manual/profiler-markers.html) · Unity · Advertencia AssetBundle.asset/allAssets: se pide el resultado antes de que termine la carga y el hilo principal se detiene a esperar - [Stat Commands in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/stat-commands-in-unreal-engine) · Epic Games · stat Streaming (memoria y número de texturas en streaming), stat AsyncLoad (estadísticas de carga asíncrona) - [Windows Performance Monitor Disk Counters Explained](https://learn.microsoft.com/en-us/archive/blogs/askcore/windows-performance-monitor-disk-counters-explained) · Microsoft · Avg. Disk sec/Read es el tiempo medio que tarda en completarse una lectura (latencia de E/S); Current Disk Queue Length es la longitud de la cola del disco en el momento de la medición - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Graba el tiempo de cada frame con FrameTime (tiempo de CPU entre frames) - [About regular quick and full scans with Microsoft Defender Antivirus](https://learn.microsoft.com/en-us/defender-endpoint/schedule-antivirus-scans) · Microsoft · La protección en tiempo real analiza los archivos cada vez que se abren y se cierran #### cg-crowd · Carga de renderizado de multitudes · Render/animation cost of crowds Cuando cientos de jugadores entran en la misma pantalla, como en un asedio o un world boss, el costo de dibujarlos se vuelve inasumible. - Por qué → Efecto → En pantalla: Cientos de jugadores y efectos se superponen en la misma pantalla → El costo de animaciones, sombras, nombres sobre los personajes y efectos crece en proporción al número de jugadores → Los FPS caen (60 → 15), todos los movimientos van a tirones y los inputs también responden tarde - Síntomas: Tirones, Input lag / Factores: Detención - A quién: Una zona o un canal, Solo yo / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Simplificar por distancia (LOD), limitar los jugadores mostrados, ofrecer una opción de efectos simplificados, reducir la frecuencia de actualización de las animaciones. - Cifras de referencia: Aunque cada personaje cueste solo 0.02–0.1 ms, con 300 son 6–30 ms. El presupuesto del frame a 60 FPS es de 16.7 ms, así que solo con eso se consume más de 1/3 y, en el peor caso, se supera. - En el gráfico: Sube con la carga (Tiempo de frame, número de personajes en pantalla) - Dónde mirar: Comparar el tiempo de frame y CPUBusy/GPUBusy de PresentMon antes y después de un asedio o un world boss. En una build de desarrollo, stat Unit de Unreal (tiempos del hilo del juego, del hilo de renderizado y de la GPU) - Se confirma si: El tiempo de frame sube a medida que aumentan los jugadores en pantalla, y mejora al instante al limitar los jugadores mostrados o activar la opción de efectos simplificados - Se descarta si: Si hay picos sin relación con el número de jugadores: “Pico de frametime” o “Recolección de basura (GC) en el cliente”. Si los FPS están bien pero solo se retrasan los movimientos de los demás: “Cuello de botella al procesar paquetes en el hilo principal” - Se verifica con: En el entorno del jugador - Fuentes: - [Introduction to level of detail](https://docs.unity3d.com/Manual/LevelOfDetail.html) · Unity · Sin LOD, incluso los objetos que se ven pequeños en pantalla se dibujan con la misma complejidad; el LOD reduce el costo de dibujado - [Animation Budget Allocator in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/animation-budget-allocator-in-unreal-engine) · Epic Games · Reduce de forma dinámica la actualización (tick) de las animaciones de las mallas esqueléticas para mantener dentro del presupuesto el tiempo dedicado a la animación - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Con FrameTime, CPUBusy y GPUBusy se distingue si es la CPU o la GPU la que retrasa el frame - [Stat Commands in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/stat-commands-in-unreal-engine) · Epic Games · stat Unit: tiempo total del frame y tiempos del hilo del juego, del hilo de renderizado y de la GPU #### cg-net-mainthread · Cuello de botella al procesar paquetes en el hilo principal · Network processing on the main thread Si el cliente solo procesa una cantidad fija de paquetes recibidos por frame, cuando llegan muchos de golpe se acumulan y se van pasando una y otra vez al frame siguiente. - Por qué → Efecto → En pantalla: Donde hay mucha gente llegan miles de actualizaciones por segundo → El hilo principal topa con su límite de procesamiento por frame y no alcanza a leerlas todas → Los movimientos de los demás se aplican cada vez más tarde y todos de golpe - Síntomas: Cámara rápida, Input lag / Factores: Detención, Latencia - A quién: Una zona o un canal, Solo yo / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: recibir y decodificar en un hilo aparte, fusionar las actualizaciones de posición antiguas de una misma entidad y aplicar solo la más reciente. Servidor: donde hay mucha gente, enviar con menos frecuencia las actualizaciones de los personajes lejanos para reducir el volumen de envío. - Cifras de referencia: Si se acumulan paquetes sin procesar, en pocos segundos ya hay un segundo entero de retraso. - En el gráfico: Sube con la carga (Paquetes recibidos sin procesar, retraso entre recepción y aplicación) - Dónde mirar: Registrar en logs cuántos paquetes deja sin procesar el cliente en cada frame y el retraso desde que llega un paquete hasta que se aplica al juego, y verlo junto al número de jugadores cercanos - Se confirma si: Donde hay mucha gente, los paquetes pendientes y el retraso de aplicación no paran de crecer, mientras que en ese mismo momento el ping y el intervalo de envío del servidor son normales - Se descarta si: Si no hay retraso de aplicación pero los paquetes ya llegan tarde, el problema está en la red. Si el tiempo de frame sube mucho: “Carga de renderizado de multitudes” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Cuando falta ancho de banda, no se replican todos los actores cada vez; se priorizan según la distancia al observador y el tiempo desde la última replicación - [Replication Graph in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/replication-graph-in-unreal-engine) · Epic Games · Los juegos con muchos jugadores conectados y muchos objetos que replicar (MMORPG, etc.) tienen que agruparlos por posición y enviar solo lo necesario para evitar un cuello de botella en la CPU del servidor #### cg-no-buffer · Búfer de interpolación ausente o demasiado corto · Missing/short interpolation buffer Si el cliente dibuja los paquetes del servidor en cuanto llegan, el jitter (variación en el tiempo de llegada de los paquetes) se ve tal cual en pantalla. - Por qué → Efecto → En pantalla: La posición recibida se dibuja al instante, o el búfer es más corto que el jitter → Se detiene lo que tarda el paquete retrasado y salta cuando llegan varios juntos → Los demás personajes se mueven a trompicones - Síntomas: Tirones / Factores: Jitter - A quién: Solo yo / Cuándo: Siempre - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: usar un búfer de interpolación y ajustar su longitud automáticamente según el estado de la conexión. Servidor: aplicar compensación de lag (validación con rebobinado) para que el registro de impactos sea correcto aunque se dispare viendo la imagen del pasado que impone el búfer. - Cifras de referencia: Lo habitual es un búfer de unas dos veces el intervalo de envío del servidor (100 ms si llegan 20 actualizaciones por segundo). - En el gráfico: Siempre alto (Intervalo de llegada de paquetes, veces que el búfer de interpolación se vació) - Dónde mirar: Registrar en el cliente la distribución del intervalo de llegada de los paquetes del servidor y el número de frames en que no había un siguiente snapshot que interpolar, de modo que el personaje se detuvo o se pasó a extrapolar - Se confirma si: La variación del intervalo de llegada supera a menudo la longitud del búfer de interpolación, y cada vez el búfer se vacía y los demás personajes dan un tirón. Al alargar el búfer, disminuye - Se descarta si: Si los tirones siguen con un búfer suficiente, verificar si el propio intervalo de envío del servidor es irregular (retraso del tick) - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Un búfer más largo da más fluidez, pero en la misma medida ves al rival en una posición pasada. Por eso se combina con la compensación de lag: para validar un ataque, el servidor rebobina hasta “el pasado que veía ese jugador”. - Fuentes: - [Interpolation and extrapolation (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/interpolation.html) · Unity · Interpolación con búfer, que retrasa a propósito el dibujado para esperar a los paquetes que llegan tarde; cuanto mayor es el búfer, más precisa es, pero más latencia añade - [Struct ClientTickRate (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/api/Unity.NetCode.ClientTickRate.html) · Unity · Valor predeterminado del búfer de interpolación: InterpolationTimeNetTicks = 2 (dos envíos del servidor) - [Physics (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/physics.html) · Unity · Compensación de lag: el servidor busca el mundo de colisiones que veía el cliente en ese tick y decide si hubo impacto #### cg-extrap · Extrapolación excesiva (dead reckoning) · Over-extrapolation / dead reckoning Mientras no llegan paquetes, el cliente sigue mostrando a los personajes en movimiento con su última velocidad y, cuando descubre que se equivocó, los devuelve a su sitio. - Por qué → Efecto → En pantalla: Se cortan los paquetes y el personaje sigue avanzando con su última dirección y velocidad → En realidad, el otro jugador se había detenido o había cambiado de dirección → El personaje del otro jugador avanza un buen trecho y salta de golpe a su posición real, o atraviesa paredes. Si los paquetes llegan a intervalos irregulares, se adelanta y vuelve atrás una y otra vez, y parece que tiembla - Síntomas: Teletransporte, Tirones / Factores: Pérdida de paquetes, Jitter - A quién: Solo yo / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Limitar el tiempo de extrapolación (p. ej., 200–250 ms), converger suavemente cuando haya error. - Cifras de referencia: A 6 m/s, un error de solo 300 ms supone 1.8 m de desfase. - En el gráfico: Picos aleatorios (Tiempo de extrapolación, distancia de corrección de posición) - Dónde mirar: Registrar cuánto tiempo se dibuja a otros personajes con extrapolación y qué distancia se corrige su posición cuando llega un paquete nuevo - Se confirma si: En cada corte de paquetes, el tiempo de extrapolación crece sin límite y luego la distancia de corrección llega a varios metros - Se descarta si: Si la extrapolación se corta pronto y aun así hay teletransporte, la pérdida de paquetes o la latencia son grandes en sí mismas: revisar la conexión y la ruta - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Interpolation and extrapolation (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/interpolation.html) · Unity · Si el siguiente snapshot no llega a tiempo, la extrapolación, que sigue moviendo la entidad con la misma dirección y velocidad, se equivoca a menudo, así que se le pone un límite (en Unity, 20 ticks por defecto, alrededor de 1/3 de segundo a 60 Hz) - [Peeking into VALORANT's Netcode](https://technology.riotgames.com/news/peeking-valorants-netcode) · Riot Games · Cuando los datos tardíos o perdidos se rellenan con suposiciones y la suposición falla, el cliente se desfasa del servidor y el personaje salta o se corrige como si se deslizara #### cg-predict · Error de predicción en el cliente · Prediction mismatch / reconciliation Tu cliente mueve a tu personaje antes de tener respuesta del servidor; si el servidor lo calcula de otra forma, tu personaje es arrastrado hacia atrás. - Por qué → Efecto → En pantalla: El cliente mueve al personaje antes de la confirmación del servidor (predicción) → El servidor calcula de otra forma las colisiones, la velocidad de movimiento o los buffs, o no recibe los comandos → Cuando llega la confirmación, tu personaje es arrastrado hacia atrás - Síntomas: Rubber banding / Factores: Pérdida de paquetes, Latencia - A quién: Solo yo / Cuándo: Al moverse o cambiar de zona, De vez en cuando, al azar - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: usar el mismo código de movimiento que el servidor, enviar los inputs por duplicado, aplicar las correcciones con suavidad. Servidor: usar el mismo código de movimiento que el cliente, filtrar por número de input los inputs duplicados y procesarlos una sola vez. - Cifras de referencia: La distancia que retrocede tu personaje es “tiempo de desfase × velocidad de movimiento”. Basta con que se pierdan unos pocos comandos para que sea de 1–3 m. - En el gráfico: Picos aleatorios (Correcciones del servidor (errores de predicción)) - Dónde mirar: Registrar cuántas correcciones de posición envía el servidor y de qué distancia. En Unreal, las correcciones ClientAdjustPosition del servidor; en Unity Netcode for Entities, contar cuántas veces se revirtió y se recalculó por error de predicción - Se confirma si: Las correcciones se concentran en los momentos de los reportes de rubber banding, y la distancia de corrección es grande una y otra vez con ciertos buffs, terrenos o habilidades de movimiento - Se descarta si: Si las correcciones solo se concentran cuando hay mucha pérdida, apunta a pérdida de los paquetes de input (la conexión). Si no hay correcciones y solo los demás personajes parecen arrastrados: “Extrapolación excesiva (dead reckoning)” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Introduction to prediction (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/intro-to-prediction.html) · Unity · El cliente y el servidor predicen con el mismo código de simulación; si el resultado difiere del estado del servidor (error de predicción), se revierte y se recalcula, y la corrección se ve - [Use the command stream to handle user inputs (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/command-stream.html) · Unity · Para cubrir la pérdida de paquetes, reenvía por duplicado los inputs de los ticks anteriores junto con el input más reciente - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · El cliente se mueve primero y el servidor reproduce el mismo movimiento; si la posición difiere, corrige con ClientAdjustPosition y vuelve a aplicar los movimientos guardados #### cg-fixed-step · Espiral de recuperación con timestep fijo · Fixed-timestep catch-up / spiral of death Tras una pausa, el juego intenta recuperar de golpe los cálculos atrasados, y esos mismos cálculos lo vuelven a retrasar. - Por qué → Efecto → En pantalla: La simulación del juego corre a un intervalo fijo y se detiene una vez → Todos los pasos atrasados se calculan en un solo frame → Se encadenan frames largos con picos, o al topar con el límite el mundo se ralentiza - Síntomas: Tirones, Cámara rápida, Cámara lenta / Factores: Detención - A quién: Solo yo / Cuándo: De vez en cuando, al azar, Cuando se junta mucha gente - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Limitar la recuperación por frame, resolver el tiempo sobrante con interpolación. - En el gráfico: Picos aleatorios (Tiempo de frame, pasos fijos por frame) - Dónde mirar: En el profiler de una build de desarrollo, ver junto con el tiempo de frame cuántas veces se ejecutó el paso fijo en un frame (en Unity, el número de marcadores de la fase FixedUpdate, como FixedBehaviourUpdate) - Se confirma si: Tras un frame largo se encadenan otros frames largos que ejecutan varios pasos, y al alcanzar el límite (Maximum Allowed Timestep en Unity) el tiempo del juego avanza más despacio que el real - Se descarta si: Si el frame largo es uno solo: “Pico de frametime” o “Recolección de basura (GC) en el cliente” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: La física de Unity (FixedUpdate) es el ejemplo típico de paso fijo (0.02 s por defecto, 50 veces por segundo). Maximum Allowed Timestep, en la configuración de Time (el tiempo máximo que se recupera en un frame, unos 0.33 s por defecto), es el límite de recuperación. Si un frame dura más que eso, el tiempo sobrante se descarta y el reloj del juego se queda atrás del real en esa misma cantidad. - Fuentes: - [Set fixed timestep to optimize physics simulation frequency](https://docs.unity3d.com/Manual/physics-optimization-cpu-frequency.html) · Unity · Valor predeterminado de Fixed Timestep: 0.02 s (50 veces por segundo); si el frame es largo, se ejecutan varios pasos de física en un mismo frame y la carga aumenta - [Handling variation in time](https://docs.unity3d.com/Manual/time-handling-variations.html) · Unity · Valor predeterminado de Maximum Allowed Timestep: 1/3 s (0.3333333); aunque el juego se detenga 1 segundo, el tiempo del juego solo avanza 0.333 s; es el límite que corta el círculo vicioso en que los pasos de recuperación vuelven a ralentizar el juego - [Profiler markers reference](https://docs.unity3d.com/Manual/profiler-markers.html) · Unity · FixedBehaviourUpdate: tramo de ejecución de MonoBehaviour.FixedUpdate; los marcadores de física se llaman en la fase FixedUpdate #### cg-clock · Error de sincronización del reloj · Clock sync error Si la hora del servidor que estima el cliente es errónea, el momento de interpolación y la validación de los cooldowns quedan desfasados. - Por qué → Efecto → En pantalla: La hora del servidor se sincroniza una sola vez al conectar y no se ajusta aunque cambie el ping → El momento de interpolación y la hora en que termina el cooldown se desfasan respecto al servidor → El otro jugador da un tirón de vez en cuando; el cooldown ya terminó y aun así la habilidad se rechaza - Síntomas: Tirones, Acción perdida / rollback / Factores: Latencia - A quién: Solo yo / Cuándo: Cuanto más tiempo lleva encendido, De vez en cuando, al azar - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Sincronizar la hora periódicamente (medir el tiempo de ida y vuelta y corregir), ajustarla poco a poco y sin saltos bruscos, medir el tiempo transcurrido con un reloj monotónico (monotonic clock), sin usar la hora del sistema. - En el gráfico: Subida gradual (Error de la hora estimada del servidor) - Dónde mirar: Registrar periódicamente la diferencia entre la hora del servidor que estima el cliente y la que el servidor envía en los paquetes (número de tick) - Se confirma si: El error crece a medida que pasa el tiempo desde la conexión, o salta de golpe cuando se ajusta el reloj del sistema, y en esos momentos aumentan los reportes de habilidades rechazadas y tirones - Se descarta si: Si el error se mantiene pequeño y aun así se rechazan habilidades, apunta a la validación del servidor o a la latencia - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Si el tiempo transcurrido se mide con la fecha y hora del sistema (reloj de pared, wall clock), la hora del juego salta en el momento en que Windows corrige el reloj con la hora de internet o el usuario lo cambia. El tiempo transcurrido hay que medirlo con un reloj monotónico, que nunca retrocede (monotonic clock, como Stopwatch). - Fuentes: - [RFC 5905: Network Time Protocol Version 4: Protocol and Algorithms Specification](https://www.rfc-editor.org/rfc/rfc5905) · IETF · Método que calcula la latencia de ida y vuelta y el desfase del reloj a partir de las cuatro marcas de tiempo de la solicitud y la respuesta - [Acquiring high-resolution time stamps](https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps) · Microsoft · QueryPerformanceCounter (el que usa Stopwatch) es un reloj para medir tiempo transcurrido que no se sincroniza con la hora externa; la hora del sistema solo se usa cuando hace falta la hora UTC - [Time synchronization (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/time-synchronization.html) · Unity · Estima la hora del servidor a partir del tiempo de ida y vuelta y la ajusta modificando poco a poco la velocidad de avance, sin cambios bruscos de hora #### cg-float-time · Pérdida de precisión del tiempo en float · Float time precision loss on long sessions Si el juego guarda su hora en un formato decimal de baja precisión (float), cuanto más tiempo lleva encendido, peor es la resolución temporal (la diferencia de tiempo más pequeña que se puede distinguir), y los movimientos y los efectos tiemblan. - Por qué → Efecto → En pantalla: El tiempo transcurrido desde que se abrió el juego se acumula en un float o se pasa tal cual a los shaders → Cuanto más tiempo lleva encendido, mayor es la diferencia mínima que puede representar el float → Solo en los clientes encendidos durante días tiemblan los personajes, las animaciones y los efectos con movimiento continuo; al reiniciar el juego todo va bien - Síntomas: Tirones / Factores: Jitter - A quién: Solo yo / Cuándo: Cuanto más tiempo lleva encendido - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Guardar el tiempo transcurrido en double (64 bits) o en un entero, reiniciar periódicamente el tiempo que se pasa a los shaders, hacer pruebas automáticas de larga duración (varios días). - Cifras de referencia: Un float de 32 bits tiene algo más de 7 dígitos significativos, así que tras un día encendido (unos 86,400 segundos) la resolución temporal es de unos 8 ms, casi la mitad de un frame a 60 FPS (16.7 ms), y tras una semana es de unos 60 ms, más que un frame entero. - En el gráfico: Subida gradual (Reportes de temblores según el tiempo encendido) - Dónde mirar: Pedir en los reportes de temblores cuánto tiempo llevaba encendido el cliente y comparar antes y después de reiniciar. En desarrollo, una prueba en la que la hora de inicio del juego se fija como si ya hubieran pasado varios días - Se confirma si: Los temblores solo aparecen en clientes encendidos durante días, desaparecen al reiniciar y empeoran cuanto más tiempo lleva encendido - Se descarta si: Si tiembla nada más arrancar: “Búfer de interpolación ausente o demasiado corto” o “Resolución del temporizador” - Se verifica con: En el entorno del jugador - Para saber más: Aparece sobre todo en MMO móviles en los que se deja activado el combate automático y no se cierra el juego durante días. Time.time de Unity también es un float, por eso Unity ofrece aparte Time.timeAsDouble, en double, y recomienda usarlo. - Fuentes: - [Time.timeAsDouble](https://docs.unity3d.com/ScriptReference/Time-timeAsDouble.html) · Unity · Versión double de Time.time; cuanto más tiempo lleva encendido, más precisa es que la versión float, y se recomienda en la mayoría de los casos - [Floating-point numeric types (C# reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types) · Microsoft · Precisión de float: unos 6–9 dígitos; de double: unos 15–17 dígitos #### cg-vsync · V-Sync y cola de renderizado · V-Sync, render queue Los frames que dibuja la GPU se acumulan en una cola de varios frames y salen al ritmo del monitor; mientras tanto, el input se retrasa. - Por qué → Efecto → En pantalla: El driver gráfico acumula por adelantado 1–3 frames en la cola → Los inputs tardan ese tiempo extra en verse en pantalla → El ping es bajo, pero el control se siente pesado y responde tarde - Síntomas: Input lag, Tirones / Factores: Latencia - A quién: Solo yo / Cuándo: Siempre - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Externo (Externo) - Tareas (Equipo de desarrollo): Ofrecer un modo de baja latencia, acortar la cola de frames, ofrecer un límite de FPS un poco por debajo de la tasa de refresco, activar el frame pacing en teléfonos. - Tareas (Externo): Indicar a los jugadores que, con un monitor de tasa de refresco variable, pongan un límite de FPS un poco por debajo de la tasa de refresco y que activen el modo de baja latencia del driver gráfico. - Cifras de referencia: A 60 Hz, cada frame son 16.7 ms. Si la CPU va más rápido que la GPU o que el refresco de la pantalla y la cola de tres frames (valor predeterminado en DirectX 11) se llena, se suman 50 ms. Con V-Sync de doble búfer, un frame que tardó 17 ms espera hasta el siguiente refresco de pantalla (33.3 ms) y, mientras tanto, el frame anterior se muestra una vez más. - En el gráfico: Siempre alto (Latencia de input a pantalla) - Dónde mirar: Comparar en PresentMon MsClickToPhotonLatency y MsAllInputToPhotonLatency (desde el input del mouse o el teclado hasta la salida a pantalla) y DisplayLatency, cambiando V-Sync, el modo de baja latencia y el límite de FPS. MsPCLatency (desde que la computadora recibe el input hasta que lo envía a la pantalla) solo se registra si el juego emite eventos PC Latency - Se confirma si: Con V-Sync activado o sin límite de FPS, esta latencia aumenta uno o dos frames (decenas de ms), y baja con el modo de baja latencia o con un límite de FPS un poco por debajo de la tasa de refresco. El ping no cambia - Se descarta si: Si la latencia dentro de tu PC es baja y aun así el control responde tarde: “Latencia de pantalla, dispositivos de entrada y generación de frames”; si el ping es alto, apunta a la red - Se verifica con: En el entorno del jugador - Para saber más: V-Sync (sincronización vertical) es el ajuste que solo envía un frame nuevo en el instante en que el monitor refresca la imagen. Elimina el tearing, pero el input se retrasa lo que dura esa espera, y si los FPS bajan de 60 oscilan entre 60 y 30 y el juego va a tirones. Un monitor de tasa de refresco variable reduce esa espera porque refresca la imagen cuando el frame está listo. En los teléfonos pasa lo mismo. Si un juego a 30 FPS no reparte sus frames de forma regular en una pantalla de 60 Hz, la media es de 30 FPS, pero cada frame se queda en pantalla un tiempo irregular, como 49 ms, 16 ms y 33 ms, y hay tirones (ejemplo de la documentación para desarrolladores de Android). Se reduce con la biblioteca de frame pacing de Android (regulariza el intervalo de salida de los frames) o con la opción equivalente del motor. - Fuentes: - [IDXGIDevice1::SetMaximumFrameLatency](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgidevice1-setmaximumframelatency) · Microsoft · Número de frames que el driver puede acumular en la cola: 3 por defecto (1–16) - [Reduce latency with DXGI 1.3 swap chains](https://learn.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains) · Microsoft · Present se bloquea hasta que la cola se vacía, y entre el dibujado y la presentación se espera casi un frame más; se reduce con una swap chain con espera (waitable swap chain) - [Frame Pacing library](https://developer.android.com/games/sdk/frame-pacing) · Android (Google) · En una pantalla de 60 Hz, si no hay frame nuevo se vuelve a mostrar el anterior; ejemplo de un juego a 30 FPS cuyos tiempos de frame quedan irregulares, como 49 ms, 16 ms y 33 ms - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · MsPCLatency (desde que la computadora recibe el input hasta que lo envía a la pantalla), MsClickToPhotonLatency (del clic del mouse a la pantalla), MsAllInputToPhotonLatency (del input de teclado o mouse a la pantalla), DisplayLatency (del envío del frame a su salida hacia el monitor) - [PresentMon Console Application (README-ConsoleApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-ConsoleApplication.md) · Intel · MsPCLatency solo se registra si la aplicación emite eventos PC Latency (--track_pc_latency); MsAllInputToPhotonLatency se basa en los inputs de teclado y mouse #### cg-leak · Fuga de memoria en el cliente · Client memory leak Cuanto más tiempo lleva encendido, más memoria usa: el juego va cada vez más lento y al final se cierra a la fuerza. - Por qué → Efecto → En pantalla: Al ir y venir entre zonas no se liberan texturas, elementos de UI ni efectos → El GC se ejecuta más a menudo, falta memoria en el SO y empieza el swap → Tras unas horas de juego, los tirones aumentan poco a poco hasta un cierre forzado (que el jugador percibe como una desconexión) - Síntomas: Tirones, Desconexión / Factores: Detención - A quién: Solo yo / Cuándo: Cuanto más tiempo lleva encendido - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Medir el uso de memoria en cada cambio de zona, localizar y corregir las texturas, la UI y los efectos que no se liberan, hacer pruebas automáticas de larga duración (soak tests). - En el gráfico: Subida gradual (Memoria del proceso del juego) - Dónde mirar: Registrar durante varias horas Process(juego)\Private Bytes con el Monitor de rendimiento. En dispositivos móviles, el motivo de cierre en ApplicationExitInfo de Android (REASON_LOW_MEMORY) y los informes de jetsam de iOS - Se confirma si: La memoria sube cada vez que se cambia de zona y no vuelve a bajar, y cuanto más tiempo lleva encendido, más tirones y cierres forzados hay - Se descarta si: Si la memoria se mantiene estable y solo hay temblores que empeoran con el tiempo encendido: “Pérdida de precisión del tiempo en float” - Se verifica con: En el entorno del jugador - Para saber más: Los teléfonos aguantan sobre todo comprimiendo la memoria. Si aun así falta, el SO cierra el juego en el acto (para el jugador, el juego se cerró solo). Cuanta menos RAM tiene el dispositivo, antes ocurre. - Fuentes: - [Memory allocation among processes](https://developer.android.com/topic/performance/memory-management) · Android (Google) · Android aguanta comprimiendo la memoria en zRAM; si no basta, el low memory killer termina procesos, y si se cierra la app en primer plano parece un crash - [Identifying high-memory use with jetsam event reports](https://developer.apple.com/documentation/xcode/identifying-high-memory-use-with-jetsam-event-reports) · Apple · iOS cierra a la fuerza las apps (jetsam) si la presión de memoria no se alivia, y toda app que supera su límite de memoria pasa a ser candidata al cierre - [Find user-mode memory leaks with Performance Monitor (PerfMon)](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/using-performance-monitor-to-find-a-user-mode-memory-leak) · Microsoft · Registrar durante mucho tiempo Process > Private Bytes (memoria privada asignada por el proceso) y Virtual Bytes; si no dejan de crecer, hay una fuga - [ApplicationExitInfo](https://developer.android.com/reference/android/app/ApplicationExitInfo) · Android (Google) · REASON_LOW_MEMORY: el low memory killer del sistema terminó el proceso de la app (los dispositivos que no lo admiten lo reportan como REASON_SIGNALED con SIGKILL) #### cg-crash · Crash del cliente · Client crash Un error no controlado cierra el juego. El jugador lo percibe como una desconexión, pero el servidor está bien. - Por qué → Efecto → En pantalla: Referencia nula, falta de memoria, error del driver gráfico → El proceso del juego se cierra a la fuerza → Reportes de “me echó del juego”, mientras los demás jugadores siguen bien en ese mismo momento - Síntomas: Desconexión / Factores: Detención - A quién: Solo yo / Cuándo: Al hacer ciertas acciones, De vez en cuando, al azar - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Externo (Externo) - Tareas (Equipo de desarrollo): Recopilar los informes de crash, sacar estadísticas por dispositivo y driver, corregir primero los errores más frecuentes. - Tareas (Externo): Si se concentran en una versión concreta del driver gráfico, indicar a los jugadores que actualicen el driver. - En el gráfico: Alto solo en algunos (Número de crashes (por dispositivo, driver gráfico y build)) - Dónde mirar: Informes de crash y tasa de crashes de Android vitals por dispositivo, driver y build. En la computadora del jugador, el evento con ID 1000 del registro de Aplicación del Visor de eventos (nombre del módulo que falló) y los registros “Display driver stopped responding and has recovered” - Se confirma si: Hay un registro de crash a la hora del reporte de desconexión y, a esa misma hora, los demás jugadores del mismo servidor están bien. Se concentran en ciertos dispositivos, versiones de driver o módulos - Se descarta si: Si solo se cortó la conexión, sin registro de crash: “Expiración del mapeo NAT” o la conexión del jugador - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Crashes](https://developer.android.com/topic/performance/vitals/crash) · Android (Google) · Un crash es el cierre inesperado de una app por una excepción no controlada o una señal (SIGSEGV, etc.); se contabiliza en Android vitals de Play Console - [WDDM Support for Timeout Detection and Recovery (TDR)](https://learn.microsoft.com/en-us/windows-hardware/drivers/display/timeout-detection-and-recovery) · Microsoft · Si la GPU no termina un trabajo en 2 segundos (valor predeterminado), Windows reinicia el driver gráfico y la GPU - [The application or service crashing behavior troubleshooting guidance](https://learn.microsoft.com/en-us/troubleshoot/windows-server/performance/troubleshoot-application-service-crashing-behavior) · Microsoft · El evento con ID 1000 del registro de Aplicación es el registro real del crash y contiene el nombre de la aplicación con errores y el del módulo con errores (Faulting module name) #### cg-anticheat · Escaneos del módulo anti-cheat · Anti-cheat scan and heartbeat El módulo de seguridad que se ejecuta junto al juego para impedir los hacks hace escaneos periódicos. Si el escaneo es pesado o si el heartbeat (señal periódica que confirma que el cliente sigue activo) que intercambia con el servidor de seguridad llega tarde, hay tirones o desconexiones. - Por qué → Efecto → En pantalla: El módulo de seguridad escanea periódicamente la memoria del juego, los programas en ejecución y los drivers → Durante el escaneo se detiene el hilo del juego, o el heartbeat no sale a tiempo → Tirones a intervalos regulares y, en casos graves, desconexión con un aviso de error de seguridad - Síntomas: Tirones, Congelamiento, Desconexión / Factores: Detención - A quién: Solo yo / Cuándo: A intervalos regulares, Al conectar o tras un mantenimiento, De vez en cuando, al azar - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: ejecutar los escaneos pesados fuera del hilo del juego y en pequeñas porciones, comparar las estadísticas de tirones y desconexiones por versión del módulo de seguridad (si se concentran justo después de una actualización, comunicarlo al proveedor del módulo). Servidor: tolerar que el heartbeat llegue tarde una o dos veces. - Cifras de referencia: Un escaneo ligero suele tardar menos de 1 ms, pero un escaneo pesado que corre en el hilo del juego puede ocupar de una vez decenas o cientos de ms, según la implementación. - En el gráfico: Picos periódicos (Tiempo de frame, expulsiones por el anti-cheat) - Dónde mirar: Medir el intervalo de los picos en el tiempo de frame de PresentMon y contabilizar, por versión del módulo de seguridad y configuración de hardware, los motivos de expulsión por anti-cheat que recibe el servidor (en EOS, AuthenticationFailed / Authentication Timed Out de ClientActionReason, etc.) - Se confirma si: Pausas breves a intervalos regulares que se repiten sin relación con lo que pasa en el juego; justo después de una actualización del módulo de seguridad aumentan, con ciertas configuraciones de hardware, los tirones y las expulsiones por timeout de autenticación - Se descarta si: Si el intervalo es el mismo en todas las configuraciones, sin relación con la versión del módulo de seguridad: “Recolección de basura (GC) en el cliente” o “Procesos en segundo plano que ocupan la CPU” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: El módulo de seguridad se instala como driver en lo más profundo del SO, así que a veces choca con antivirus, overlays o módulos de seguridad de otros juegos. Si justo después de una actualización del módulo de seguridad se concentran reportes de tirones y desconexiones solo con ciertas configuraciones de hardware, es lo primero que hay que sospechar. - Fuentes: - [Using the Anti-Cheat Interfaces](https://dev.epicgames.com/docs/epic-online-services/trust-and-safety/anti-cheat-interfaces/using-anti-cheat) · Epic Games · Si el servidor no recibe los mensajes anti-cheat del cliente dentro del tiempo fijado (RegisterTimeout), lo expulsa por timeout de autenticación (una causa habitual es un cliente detenido por una carga); si el problema viene de una actualización reciente del módulo, se vuelve al módulo anterior - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Graba el tiempo de cada frame con FrameTime (tiempo de CPU entre frames) ### L2 SO y dispositivo del cliente (causas: 15) #### co-background · Procesos en segundo plano que ocupan la CPU · Background CPU contention Cuando un análisis del antivirus, Windows Update, un software de streaming o un video en el navegador ocupan los núcleos, el hilo del juego espera sin recibir CPU. - Por qué → Efecto → En pantalla: Otros programas ocupan un núcleo de la CPU durante mucho tiempo → El hilo del juego queda en espera de CPU → Los frames llegan tarde y el procesamiento de los paquetes recibidos también se retrasa - Síntomas: Tirones, Cámara rápida / Factores: Detención - A quién: Solo yo / Cuándo: De vez en cuando, al azar, A intervalos regulares - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Ajustar la prioridad del hilo del juego, registrar el uso total de CPU del sistema en los logs que se toman cuando hay tirones, para distinguir si la culpa es de otro programa. - Tareas (Externo): Indicar a los jugadores que activen el Modo de juego de Windows y que cierren durante la partida los programas innecesarios (análisis del antivirus, Windows Update, software de streaming, videos en el navegador). - Cifras de referencia: Windows suele ceder los núcleos en porciones de varios ms a decenas de ms. Basta con quedarse sin turno una sola vez para perder un frame entero. - En el gráfico: Picos aleatorios (Uso total de CPU del sistema, tiempo de frame) - Dónde mirar: Registrar la columna CPU de la pestaña Procesos del Administrador de tareas y Processor Information(_Total)\% Processor Time del Monitor de rendimiento junto con el tiempo de frame de PresentMon. Si se sospecha del antivirus, grabar con New-MpPerformanceRecording y ver con Get-MpPerformanceReport qué archivos y procesos tienen los análisis más largos - Se confirma si: En los momentos de tirones se dispara el uso de CPU de otro programa (análisis del antivirus, actualizaciones, software de streaming), o los archivos de la carpeta del juego aparecen entre los de mayor tiempo de análisis. Al cerrar ese programa o añadir una exclusión, desaparece - Se descarta si: Si el uso de CPU es bajo y aun así toda la pantalla da un tirón y el sonido chisporrotea: “Ahorro de energía y drivers de la NIC” (latencia de DPC) - Se verifica con: En el entorno del jugador - Para saber más: Windows da algo más de prioridad al programa de la ventana en primer plano, pero si hay más trabajo que núcleos, el juego también espera. El antivirus interviene sobre todo a través de la “protección en tiempo real”; su consumo de CPU molesta con menos frecuencia. Analiza cada archivo que abre el juego, así que las pausas al leer assets se alargan. - Fuentes: - [Multitasking](https://learn.microsoft.com/en-us/windows/win32/procthread/multitasking) · Microsoft · Windows da a cada hilo una porción de tiempo (time slice) y, cuando la agota, pasa al siguiente hilo; la porción dura unos 20 ms (varía según el SO y la CPU) - [Priority Boosts](https://learn.microsoft.com/en-us/windows/win32/procthread/priority-boosts) · Microsoft · El proceso de la ventana en primer plano recibe una prioridad igual o superior a la de los procesos en segundo plano - [About regular quick and full scans with Microsoft Defender Antivirus](https://learn.microsoft.com/en-us/defender-endpoint/schedule-antivirus-scans) · Microsoft · La protección en tiempo real analiza los archivos cada vez que se abren y se cierran, y las carpetas cada vez que se abren - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · Contador Processor Information: % Processor Time - [Performance analyzer for Microsoft Defender Antivirus](https://learn.microsoft.com/en-us/defender-endpoint/tune-performance-defender-antivirus) · Microsoft · Se graba con New-MpPerformanceRecording y Get-MpPerformanceReport muestra los archivos, rutas y procesos que más influyeron en el tiempo de análisis - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Graba el tiempo de cada frame con FrameTime (tiempo de CPU entre frames) #### co-power · Ahorro de energía y thermal throttling · Power saving, thermal throttling El modo batería de una computadora portátil, el modo de ahorro de energía del teléfono o el calor del dispositivo reducen la velocidad de la CPU y la GPU. Lo característico del calor es que al principio todo va bien y la lentitud llega al cabo de un rato. - Por qué → Efecto → En pantalla: Modo batería o de ahorro de energía, o el dispositivo se calienta → La frecuencia de la CPU y la GPU baja un 30–50%, según el dispositivo → Con el ahorro de energía, nada más activarlo; con el calor, tras jugar entre unos minutos y unos 20 minutos: los FPS bajan y hay tirones - Síntomas: Tirones, Input lag / Factores: Detención - A quién: Solo yo / Cuándo: Cuanto más tiempo lleva encendido, Siempre - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Ajustar automáticamente las opciones gráficas, controlar el calor con un límite de FPS, bajar las opciones por adelantado según el nivel térmico que informa el SO (thermalState en iOS, la API de estado térmico en Android), marcar el ejecutable para que use la GPU dedicada en computadoras portátiles con dos chips gráficos (exportar NvOptimusEnablement y AmdPowerXpressRequestHighPerformance). - Tareas (Externo): Indicar a los jugadores que desactiven el modo de ahorro de energía y que conecten la computadora portátil a la corriente; ante reportes de “mi computadora portátil es buena pero los FPS son bajos”, indicarles que comprueben en qué chip gráfico corre el juego y que lo asignen a la GPU de alto rendimiento en la configuración de gráficos de Windows. - En el gráfico: Subida gradual (FPS, frecuencia de CPU y GPU) - Dónde mirar: Registrar durante 20–30 minutos CPUFrequency, GPUFrequency, CPUTemperature y GPUTemperature de PresentMon junto con el tiempo de frame, y comprobar con la columna Motor de GPU de la pestaña Procesos del Administrador de tareas en qué chip gráfico corre el juego. En dispositivos móviles, registrar junto con los FPS la API térmica de Android (getThermalHeadroom, estado térmico) y thermalState de iOS - Se confirma si: Los FPS bajan a partir del momento en que, tras subir la temperatura, cae la frecuencia, o la frecuencia solo es baja en modo batería o de ahorro de energía. O el juego está corriendo en la gráfica integrada - Se descarta si: Si la frecuencia y la temperatura no cambian y aun así los FPS bajan: “Procesos en segundo plano que ocupan la CPU” o “Fuga de memoria en el cliente” - Se verifica con: En el entorno del jugador - Para saber más: Las computadoras portátiles con dos chips gráficos a veces ejecutan el juego en la gráfica integrada, más lenta, para ahorrar energía. Ante un reporte de “mi computadora portátil es buena pero los FPS son bajos”, lo primero es comprobar en qué chip gráfico corre el juego. - Fuentes: - [Thermal API](https://developer.android.com/games/optimize/adpf/thermal) · Android (Google) · Los dispositivos solo mantienen el alto rendimiento durante un tiempo limitado y después el calor provoca throttling; se recomienda bajar la carga por adelantado según el estado térmico - [thermalState](https://developer.apple.com/documentation/foundation/processinfo/thermalstate-swift.property) · Apple · Nivel térmico actual que informa iOS; cuando sube, la app debe reducir el uso de recursos - [Selecting the Best Graphics Device to Run a 3D Intensive Application](https://gpuopen.com/learn/amdpowerxpressrequesthighperformance/) · AMD · En computadoras portátiles con dos chips gráficos, un juego de 60 FPS puede bajar a 30 FPS si corre en la gráfica integrada; exportar AmdPowerXpressRequestHighPerformance selecciona la gráfica dedicada - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Registra por frame CPUFrequency y GPUFrequency (frecuencia) y CPUTemperature y GPUTemperature (temperatura) - [GPUs in the task manager](https://devblogs.microsoft.com/directx/gpus-in-the-task-manager/) · Microsoft · El Administrador de tareas tiene columnas que muestran el uso de GPU por proceso y a qué GPU y motor corresponde ese valor #### co-timer · Resolución del temporizador · Timer resolution (Windows 15.6ms) El temporizador predeterminado de Windows funciona en pasos de 15.6 ms, así que “esperar solo 1 ms” se alarga en la práctica hasta el siguiente ciclo del temporizador, hasta 15.6 ms. - Por qué → Efecto → En pantalla: El límite de FPS y el envío de paquetes se implementan con Sleep (una espera breve) → El SO solo despierta al proceso en pasos de 15.6 ms → El intervalo entre frames y el intervalo de envío de inputs se vuelven irregulares - Síntomas: Tirones / Factores: Jitter - A quién: Solo yo / Cuándo: Siempre - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Usar temporizadores de alta resolución, regular el ritmo con eventos o con V-Sync, sin depender de esperas. - Cifras de referencia: Con pasos de 15.6 ms no se puede clavar un intervalo de 16.7 ms, así que el intervalo entre frames oscila entre 15.6 ms y 31.2 ms. - En el gráfico: Siempre alto (Distribución del intervalo entre frames) - Dónde mirar: Distribución de MsBetweenPresents (intervalo entre frames) de PresentMon y el apartado “Platform Timer Resolution” del informe de powercfg /energy (procesos que cambiaron la resolución del temporizador) - Se confirma si: Los intervalos entre frames se concentran en múltiplos de 15.6 ms, como 15.6 ms y 31.2 ms, y el juego no pide una resolución de temporizador mayor - Se descarta si: Si los intervalos se reparten de forma uniforme, es poco probable que sea el temporizador. Más probable: “Procesos en segundo plano que ocupan la CPU” o la carga del frame - Se verifica con: En el entorno del jugador - Para saber más: En versiones antiguas de Windows, si un programa cambiaba el temporizador a 1 ms, el cambio se aplicaba a todos los programas. De ahí venía la idea de que “con el navegador abierto el juego va más fluido”. Desde Windows 10, versión 2004, solo se aplica al programa que lo pide, y Windows 11 puede ignorar la solicitud de ventanas minimizadas o totalmente tapadas que no emiten sonido. - Fuentes: - [_WDF_TIMER_CONFIG (wdftimer.h)](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdftimer/ns-wdftimer-_wdf_timer_config) · Microsoft · La precisión de un temporizador normal es el intervalo del tick del reloj del sistema, 15.6 ms por defecto; la de un temporizador de alta resolución, 1 ms - [timeBeginPeriod function (timeapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod) · Microsoft · Antes de Windows 10, versión 2004, era un ajuste global; después solo se aplica al proceso que lo pide, y Windows 11 no garantiza la alta resolución a los procesos de ventanas tapadas o minimizadas - [CreateWaitableTimerExW function (synchapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createwaitabletimerexw) · Microsoft · Flag del temporizador de espera de alta resolución: CREATE_WAITABLE_TIMER_HIGH_RESOLUTION - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · MsBetweenPresents: tiempo (ms) entre esta llamada a Present() y la anterior - [Results for the Idle Energy Efficiency Assessment](https://learn.microsoft.com/en-us/windows-hardware/test/assessments/results-for-the-idle-energy-efficiency-assessment) · Microsoft · Resolución predeterminada del temporizador del sistema: 15.6 ms; el apartado “Platform Timer Resolution” del informe de energía muestra qué procesos cambiaron la resolución del temporizador - [Powercfg command-line options](https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/powercfg-command-line-options) · Microsoft · powercfg /energy: analiza el sistema y genera un informe de energía (HTML) #### co-mobile-bg · Aplicación móvil enviada a segundo plano · App suspended in background Si sales un momento de la app para ver una notificación, el SO la suspende (suspend) a los pocos segundos y, mientras tanto, el servidor te desconecta. - Por qué → Efecto → En pantalla: Se deja el juego en segundo plano para leer un mensaje o atender una llamada → El motor del juego detiene la partida y el SO pronto suspende también la app y la red → Al volver ya hay desconexión y toca reconectar - Síntomas: Desconexión / Factores: Detención, Pérdida de paquetes - A quién: Solo yo / Cuándo: Tras un rato inactivo, Al hacer ciertas acciones - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: al volver, reconectar de inmediato y de forma automática con el token de sesión, sin esperar a que la conexión caída expire (retomar la sesión sin volver a iniciar sesión), recibir el estado más reciente de una vez y sincronizarse. Servidor: si se corta el heartbeat, cerrar la conexión pero mantener la sesión del personaje durante un periodo de gracia breve (sin expulsarlo al instante) y, si reconecta dentro de ese plazo, retomarla con el token de sesión. - Cifras de referencia: El motor del juego suele detenerse en el momento en que la app pasa a segundo plano. iOS suspende la app en pocos segundos, o normalmente en unas decenas de segundos si recibe tiempo extra, y Android 14 o posterior congela (freeze) la app que sale de la pantalla a los 10 segundos aproximadamente. - En el gráfico: Desconexión masiva (Desconexiones (timeout de heartbeat), registros de suspensión de la app) - Dónde mirar: Cruzar por ID de sesión las horas de suspensión y regreso de la app en el log del cliente (en Unity, OnApplicationPause) con el motivo y la hora de la desconexión en el servidor. En Android, revisar también el motivo de cierre del proceso registrado en ApplicationExitInfo (REASON_LOW_MEMORY, etc.) - Se confirma si: Justo antes de la desconexión por timeout de heartbeat en el servidor, el cliente entró en suspensión, y reconectó nada más volver - Se descarta si: Si la desconexión ocurrió con la app en primer plano: “Expiración del mapeo NAT”, “IP compartida del ISP (CGNAT)” o “Cambio Wi-Fi ↔ LTE/5G” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Si falta memoria, el teléfono puede llegar a cerrar del todo el juego que está en segundo plano. Por eso, al volver de la cámara o de una app de pago o de autenticación, el juego arranca desde cero. Es más habitual en dispositivos de gama baja. - Fuentes: - [Extending your app’s background execution time](https://developer.apple.com/documentation/uikit/extending-your-app-s-background-execution-time) · Apple · Al pasar a segundo plano, applicationDidEnterBackground dispone de 5 segundos y luego la app se suspende; si necesita más, pide tiempo con beginBackgroundTask (el tiempo restante está en backgroundTimeRemaining) - [Cached apps freezer](https://source.android.com/docs/core/perf/cached-apps-freezer) · Android (Google) · Android 14 o posterior congela los procesos de apps en estado de caché a los 10 segundos; al congelarse, todos sus hilos se detienen - [Application.runInBackground](https://docs.unity3d.com/ScriptReference/Application-runInBackground.html) · Unity · Con el valor predeterminado false, se detiene en segundo plano; en Android se detiene en segundo plano sea cual sea el ajuste, e iOS ignora este ajuste - [MonoBehaviour.OnApplicationPause(bool)](https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnApplicationPause.html) · Unity · Cuando la app se suspende o se reanuda, envía OnApplicationPause(true/false) a todos los MonoBehaviour - [ApplicationExitInfo](https://developer.android.com/reference/android/app/ApplicationExitInfo) · Android (Google) · REASON_LOW_MEMORY: el low memory killer del sistema terminó el proceso de la app (los dispositivos que no lo admiten lo reportan como REASON_SIGNALED con SIGKILL) #### co-netswitch · Cambio Wi-Fi ↔ LTE/5G · Network switch changes IP Al salir de casa, el Wi-Fi se corta y el dispositivo pasa a LTE o 5G; tu dirección IP cambia y la conexión existente deja de valer. - Por qué → Efecto → En pantalla: La señal Wi-Fi se debilita y el dispositivo cambia a la red móvil → Tu dirección IP cambia y ya no se pueden intercambiar datos por la conexión abierta con la dirección antigua → Una pausa breve y después desconexión o reconexión - Síntomas: Congelamiento, Desconexión / Factores: Pérdida de paquetes - A quién: Solo yo / Cuándo: Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo), Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Servidor: con un token de sesión, retomar al mismo jugador aunque cambie su dirección y cerrar de inmediato la conexión de la dirección antigua, estudiar protocolos que mantienen la conexión aunque cambie la dirección (como la migración de conexión de QUIC). Cliente: al detectar un cambio de red, reconectar de inmediato con el token de sesión, sin esperar al timeout del heartbeat. - Tareas (Equipo de infraestructura): Si se usa la migración de conexión de QUIC, configurar el balanceador de carga para que elija el servidor por el ID de conexión, sin usar la dirección y el puerto (si elige por dirección y puerto, los paquetes con la dirección nueva van a otro servidor). - En el gráfico: Desconexión masiva (Desconexiones y reconexiones, IP distinta al reconectar) - Dónde mirar: Buscar en los logs de conexión del servidor reconexiones del mismo token de sesión desde otra IP y cruzarlas con la hora del callback de cambio de la red predeterminada del cliente (registerDefaultNetworkCallback) - Se confirma si: Justo después de la desconexión, la IP de reconexión pasa del rango del Wi-Fi (la conexión de casa) al rango del operador móvil, o al revés, y justo antes llega el callback de cambio de red - Se descarta si: Si la IP no cambió y aun así hubo desconexión: “Handover entre estaciones base (en movimiento)” o “Señal móvil débil y zonas sin cobertura” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Read network state](https://developer.android.com/training/basics/network-ops/reading-network-state) · Android (Google) · Cuando cambia la red predeterminada, las conexiones nuevas usan la nueva red y las de la red anterior acaban cerrándose a la fuerza; el cambio se detecta con registerDefaultNetworkCallback - [RFC 9000: QUIC: A UDP-Based Multiplexed and Secure Transport](https://www.rfc-editor.org/rfc/rfc9000) · IETF · El ID de conexión mantiene la conexión aunque cambien la dirección IP y el puerto (sección 9); un balanceador de carga que reparte solo por dirección y puerto puede enviar a otro servidor los paquetes cuya dirección cambió (sección 5.2.3) - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · Una conexión TCP se identifica por el par de sockets (dirección y puerto) de ambos extremos #### co-security · Inspección de paquetes del software de seguridad · Antivirus / firewall inspection Si el antivirus o el firewall inspeccionan cada paquete, la latencia aumenta y, si se exceden, toman el juego por un ataque y lo bloquean. - Por qué → Efecto → En pantalla: El software de seguridad inspecciona uno por uno los paquetes enviados y recibidos → Cada paquete suma latencia y, si la inspección se atrasa, se descartan paquetes → El ping da picos irregulares o la conexión queda bloqueada - Síntomas: Tirones, No conecta / carga infinita / Factores: Jitter, Pérdida de paquetes - A quién: Solo yo / Cuándo: Siempre, Al conectar o tras un mantenimiento - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Mantener una lista de compatibilidad con programas de seguridad, registrar una excepción para el juego en el Firewall de Windows durante la instalación. - Tareas (Externo): Indicar a los jugadores que añadan el juego como excepción en su software de seguridad; si el software toma el juego por un ataque, pedir a su fabricante que corrija el falso positivo. - Cifras de referencia: En condiciones normales, inspeccionar un paquete suele llevar menos de 1 ms. El problema surge cuando el módulo de inspección se atrasa o tiene un bug, o cuando toma el tráfico del juego por un ataque. - En el gráfico: Alto solo en algunos (RTT y fallos de conexión (por jugador)) - Dónde mirar: Comparar tras desactivar un momento el software de seguridad o añadir el juego como excepción. En Windows, al activar Audit Filtering Platform Connection y Audit Filtering Platform Packet Drop en la directiva de auditoría, el registro de Seguridad guarda los eventos 5157 (conexión bloqueada) y 5152 (paquete bloqueado), y WFPv4\Packets Discarded/sec del Monitor de rendimiento muestra los paquetes descartados - Se confirma si: Quedan registros de bloqueo de conexiones o paquetes hacia la dirección del servidor del juego, o los picos de ping y los fallos de conexión desaparecen al desactivar el software de seguridad - Se descarta si: Si otros dispositivos de la misma casa tienen el mismo problema, sin relación con el software de seguridad, apunta al router o a la conexión - Se verifica con: En el entorno del jugador - Fuentes: - [About Windows Filtering Platform](https://learn.microsoft.com/en-us/windows/win32/fwp/about-windows-filtering-platform) · Microsoft · Arquitectura que permite o bloquea paquetes mediante hooks y un motor de filtrado en la pila de red de Windows; los fabricantes de seguridad externos pueden insertar sus propios módulos de filtrado (callouts) - [Windows Firewall Rules](https://learn.microsoft.com/en-us/windows/security/operating-system-security/network-security/windows-firewall/rules) · Microsoft · Por defecto se bloquean las conexiones entrantes, así que las apps necesitan reglas de excepción, que suele crear el instalador de la app - [Address false positives/negatives in Microsoft Defender for Endpoint](https://learn.microsoft.com/en-us/defender-endpoint/defender-endpoint-false-positives-negatives) · Microsoft · Procedimiento para crear excepciones y enviar el archivo a Microsoft para su análisis cuando se toma un programa legítimo por una amenaza (falso positivo) - [5157(F): The Windows Filtering Platform has blocked a connection.](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-5157) · Microsoft · Evento 5157: Windows Filtering Platform bloqueó una conexión (Audit Filtering Platform Connection) - [Audit Filtering Platform Packet Drop](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/audit-filtering-platform-packet-drop) · Microsoft · Evento 5152: Windows Filtering Platform bloqueó un paquete - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · Contadores WFPv4/WFPv6: Packets Discarded/sec #### co-rcvbuf · Desbordamiento del búfer de recepción · Socket receive buffer overflow Si el juego está ocupado y saca tarde los paquetes del socket (la interfaz de red para enviar y recibir que ofrece el SO), el búfer del SO se desborda. - Por qué → Efecto → En pantalla: Los frames se atrasan y el juego lee el socket tarde → El búfer de recepción del SO se llena: en UDP se descartan paquetes, y en TCP se reduce la ventana de recepción para que el emisor deje de enviar → Teletransporte (UDP) o cámara rápida (TCP) - Síntomas: Teletransporte, Cámara rápida / Factores: Pérdida de paquetes, Detención - A quién: Solo yo / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Usar un hilo dedicado a la recepción, ajustar el tamaño del búfer (SO_RCVBUF). - Cifras de referencia: El búfer de recepción predeterminado es de decenas a cientos de KB según el SO y la configuración. Las actualizaciones en un sitio con mucha gente pueden llegar a cientos de KB por segundo. - En el gráfico: Sube con la carga (Descartes en el búfer de recepción UDP, tiempo de frame) - Dónde mirar: Registrar Microsoft Winsock BSP\Dropped Datagrams (UDP descartados por falta de espacio en el búfer de recepción del socket) y UDPv4\Datagrams Received Errors del Monitor de rendimiento de Windows junto con el tiempo de frame; en el juego, contar los huecos en los números de secuencia de los paquetes recibidos - Se confirma si: Dropped Datagrams aumenta en sitios con mucha gente o justo después de un frame largo, y en ese mismo instante aparecen huecos en la secuencia del juego. A esa hora no hay pérdida en la conexión - Se descarta si: Si Dropped Datagrams no cambia y solo faltan números de secuencia, la pérdida está en la ruta - Se verifica con: En el entorno del jugador - Fuentes: - [socket(7) — Linux manual page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux man-pages · SO_RCVBUF es el tamaño máximo del búfer de recepción del socket; el valor predeterminado lo fija rmem_default y el máximo, rmem_max (Android también usa el kernel de Linux) - [SOL_SOCKET Socket Options (Winsock2.h)](https://learn.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options) · Microsoft · SO_RCVBUF en Windows: espacio de búfer que se reserva para recepción en cada socket - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · El campo de ventana de TCP indica cuántos bytes más puede recibir el receptor; si es 0, el emisor espera enviando solo sondas de ventana cero - [Low Latency Workloads Management and Operations](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/hh997022(v=ws.11)) · Microsoft · Dropped Datagrams y Dropped Datagrams/sec del conjunto de contadores Microsoft Winsock BSP: datagramas UDP descartados porque llegan más rápido de lo que la app los procesa o porque falta espacio en el búfer de recepción del socket - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · Contadores UDPv4/UDPv6: Datagrams Received Errors y Microsoft Winsock BSP: Dropped Datagrams #### co-swap · Falta de memoria y swap en el cliente · Paging / swap on client Con decenas de pestañas del navegador abiertas junto al juego, el SO saca a disco parte de la memoria del juego. - Por qué → Efecto → En pantalla: Falta RAM en el sistema → El SO pasa a disco la memoria del juego que no se está usando en ese momento → Cuando el juego vuelve a usar esa parte, se detiene de decenas a cientos de ms según el almacenamiento - Síntomas: Congelamiento, Tirones / Factores: Detención - A quién: Solo yo / Cuándo: Al moverse o cambiar de zona, De vez en cuando, al azar - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Reducir el uso de memoria, mostrar un aviso cuando quede poca memoria libre. - Tareas (Externo): Informar a los jugadores de los requisitos mínimos e indicarles que cierren otros programas (pestañas del navegador, etc.) durante la partida. - En el gráfico: Picos aleatorios (Fallos de página duros, uso de memoria) - Dónde mirar: Registrar Memory\Pages Input/sec del Monitor de rendimiento (páginas leídas del disco para resolver fallos de página duros) y el uso de memoria y la memoria confirmada de la pestaña Rendimiento del Administrador de tareas, junto con el tiempo de frame - Se confirma si: En el momento de la pausa, Pages Input/sec se dispara y la memoria está casi llena. Al cerrar otros programas, como el navegador, desaparece - Se descarta si: Si hay memoria libre y Pages Input/sec está tranquilo: “Carga síncrona y compilación de shaders en el hilo principal” o “Almacenamiento lento que retrasa el streaming de assets” - Se verifica con: En el entorno del jugador - Fuentes: - [Introduction to the page file](https://learn.microsoft.com/en-us/troubleshoot/windows-client/performance/introduction-to-the-page-file) · Microsoft · El archivo de paginación es un archivo en disco que sirve para sacar de la RAM las páginas de memoria modificadas que se usan poco - [Working Set](https://learn.microsoft.com/en-us/windows/win32/memory/working-set) · Microsoft · Acceder a una página que no está en RAM provoca un fallo de página; un fallo duro solo se resuelve leyendo del disco (del archivo de paginación, por ejemplo) - [Chapter 12 - Detecting Memory Bottlenecks](https://learn.microsoft.com/en-us/previous-versions/cc749872(v=technet.10)) · Microsoft · Memory\Pages Input/sec: páginas leídas del disco para resolver fallos de página (fallos de página duros) #### co-vram · Falta de memoria gráfica (VRAM) · VRAM over-commit Si las opciones gráficas piden más memoria de la que tiene la tarjeta gráfica, el SO saca texturas a la RAM del sistema y las vuelve a traer, y hay tirones. - Por qué → Efecto → En pantalla: Las texturas en calidad alta o la enorme variedad de equipamiento y efectos de un sitio con mucha gente llenan la memoria de la tarjeta gráfica → El SO pasa a la RAM del sistema las texturas que no se usan en ese momento y, cuando hacen falta, las vuelve a traer por el bus PCIe, que es lento → Un tirón cada vez que aparece una escena o un personaje nuevo, y texturas borrosas durante un rato - Síntomas: Tirones, Congelamiento / Factores: Detención - A quién: Solo yo / Cuándo: Cuando se junta mucha gente, Al moverse o cambiar de zona - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Externo (Externo) - Tareas (Equipo de desarrollo): Ajustar las opciones predeterminadas a la memoria de la tarjeta gráfica, bajar automáticamente la calidad de texturas al superar el presupuesto de memoria, simplificar las texturas de los personajes en sitios con mucha gente. - Tareas (Externo): Indicar a los jugadores que bajen la calidad de texturas, y que la bajen aún más si abren dos clientes. - Cifras de referencia: La memoria de la tarjeta gráfica lee cientos de GB por segundo, pero el bus PCIe que la comunica con la RAM del sistema ronda los 16–64 GB por segundo según la generación: más de diez veces más lento. - En el gráfico: Topa con el límite (Memoria de GPU dedicada, memoria de GPU compartida) - Dónde mirar: Ver los gráficos de memoria de GPU dedicada y compartida del apartado GPU en la pestaña Rendimiento del Administrador de tareas (en la pestaña Detalles se pueden añadir columnas por proceso) junto con el tiempo de frame de PresentMon - Se confirma si: Mientras la memoria de GPU dedicada se aplana contra el límite y la compartida aumenta, los tirones son frecuentes, y desaparecen al bajar la calidad de texturas - Se descarta si: Si queda memoria dedicada libre: “Almacenamiento lento que retrasa el streaming de assets” o “Carga síncrona y compilación de shaders en el hilo principal” - Se verifica con: En el entorno del jugador - Para saber más: Si en el apartado GPU del Administrador de tareas de Windows la “Memoria de GPU dedicada” está llena y la “Memoria de GPU compartida” aumenta, estás en esta situación. Con dos clientes abiertos en la misma computadora se llena antes (ver “Fallo de streaming por falta de memoria o VRAM”). - Fuentes: - [Residency](https://learn.microsoft.com/en-us/windows/win32/direct3d12/residency) · Microsoft · Cada proceso tiene un presupuesto de memoria gráfica; si lo supera, el kernel pasa a la RAM del sistema parte de los heaps de la GPU dedicada (es el último recurso, por eso se recomienda gestionar el presupuesto) - [GPUs in the task manager](https://devblogs.microsoft.com/directx/gpus-in-the-task-manager/) · Microsoft · En el Administrador de tareas, la memoria de GPU dedicada es la VRAM de la tarjeta gráfica, y la memoria de GPU compartida es la RAM del sistema, que usan a la vez la GPU y la CPU - [CUDA C++ Best Practices Guide](https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html) · NVIDIA · El ancho de banda de la memoria gráfica (898 GB/s en una V100) es muy superior al de PCIe x16 de 3.ª generación (16 GB/s), por lo que se recomienda reducir las transferencias con la RAM del sistema - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Graba el tiempo de cada frame con FrameTime (tiempo de CPU entre frames) #### co-wifi-scan · Escaneo de Wi-Fi en segundo plano · Periodic Wi-Fi background scan Mientras el SO salta periódicamente de canal en canal para buscar redes Wi-Fi cercanas, la comunicación se detiene un instante. - Por qué → Efecto → En pantalla: El SO o el driver buscan redes Wi-Fi cercanas a intervalos fijos → Durante la búsqueda, el envío y la recepción se detienen un instante → Picos de ping a intervalos exactos (p. ej., cada 60 segundos) - Síntomas: Tirones, Teletransporte / Factores: Jitter - A quién: Solo yo / Cuándo: A intervalos regulares - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Solicitar durante la partida un modo que reduzca las búsquedas inalámbricas (en Android, el modo Wi-Fi de baja latencia WIFI_MODE_FULL_LOW_LATENCY; en Windows, el modo de streaming multimedia de WlanSetInterface; según el dispositivo y el driver, puede no tener efecto). - Tareas (Externo): Indicar a los jugadores que usen cable, que ajusten los servicios de ubicación y la búsqueda automática de Wi-Fi y que actualicen el driver inalámbrico. - Cifras de referencia: Normalmente de decenas a cientos de ms cada vez. Si los picos son demasiado regulares, esta es la primera causa que hay que sospechar. - En el gráfico: Picos periódicos (RTT hasta el router) - Dónde mirar: Durante la partida, medir durante unos minutos con ping /t la dirección del router (la puerta de enlace predeterminada de ipconfig) y anotar el intervalo de los picos. Repetir la medición con cable - Se confirma si: El ping al router da picos de decenas a cientos de ms a intervalos exactos (p. ej., 60 segundos), y con cable desaparecen - Se descarta si: Si los picos llegan a intervalos irregulares: “Interferencias y señal débil en el Wi-Fi”. Si hasta el router todo va bien y solo hay picos más allá, apunta a la conexión o al tramo del ISP - Se verifica con: En el entorno del jugador - Fuentes: - [WDI low latency connection quality](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/wdi-low-latency-connection-quality) · Microsoft · La búsqueda y el roaming sacan al chip inalámbrico del canal conectado, por lo que el modo de baja latencia limita las búsquedas y el tiempo fuera del canal - [WlanSetInterface function (wlanapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlansetinterface) · Microsoft · API de Windows para activar y desactivar la búsqueda en segundo plano (wlan_intf_opcode_background_scan_enabled) y el modo de streaming multimedia - [Wi-Fi low-latency mode](https://source.android.com/docs/core/connect/wifi-low-latency) · Android (Google) · En el modo de baja latencia se desactiva el ahorro de energía del Wi-Fi; la optimización de la búsqueda y el roaming depende de la implementación del fabricante del dispositivo - [ping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ping) · Microsoft · /t: envía solicitudes de eco sin parar hasta que se interrumpe - [ipconfig](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig) · Microsoft · Sin parámetros, muestra las direcciones IPv4 e IPv6 y la puerta de enlace predeterminada de cada adaptador #### co-driver · Ahorro de energía y drivers de la NIC · NIC power saving, driver bugs Si la tarjeta de red o el chip Wi-Fi entran en ahorro de energía entre paquete y paquete, tardan en volver a activarse. - Por qué → Efecto → En pantalla: El ahorro de energía del dispositivo de red está activado o el driver es antiguo → Retraso de reactivación (wake-up) y, a veces, reinicio del dispositivo → Latencia irregular y, en raras ocasiones, congelamientos de varios segundos - Síntomas: Tirones, Congelamiento / Factores: Jitter, Pérdida de paquetes - A quién: Solo yo / Cuándo: Tras un rato inactivo, De vez en cuando, al azar - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): En el cliente de Android, pedir durante la partida el modo Wi-Fi de baja latencia (WIFI_MODE_FULL_LOW_LATENCY) para desactivar el ahorro de energía del Wi-Fi. - Tareas (Externo): Indicar a los jugadores que actualicen el driver de red, que desactiven el ahorro de energía del dispositivo de red en el Administrador de dispositivos y, si toda la pantalla da tirones y el sonido chisporrotea, que busquen con LatencyMon el driver causante. - En el gráfico: Picos aleatorios (Tiempo de DPC e ISR, RTT hasta el router) - Dónde mirar: Grabar con Windows Performance Recorder (WPR) y buscar en el gráfico DPC/ISR de Windows Performance Analyzer (WPA) los drivers con ejecuciones largas (columna Module), y revisar en el Administrador de dispositivos la configuración de administración de energía (ahorro de energía) del adaptador de red - Se confirma si: En los momentos de tirones, los DPC e ISR del driver de red se prolongan varios ms, o la latencia irregular desaparece al desactivar el ahorro de energía - Se descarta si: Si los DPC son cortos y nada cambia al desactivar el ahorro de energía: “Interferencias y señal débil en el Wi-Fi” o “Escaneo de Wi-Fi en segundo plano” - Se verifica con: En el entorno del jugador - Para saber más: Si un driver ocupa la CPU mucho tiempo procesando interrupciones (en Windows se llama latencia de DPC), el hilo del juego tampoco puede usar ese núcleo mientras tanto. En ese caso, toda la pantalla da tirones y el sonido chisporrotea aunque el uso de CPU sea bajo. Herramientas como LatencyMon permiten encontrar el driver responsable; los drivers de Wi-Fi y de Ethernet son causas habituales. - Fuentes: - [Introduction to NDIS Selective Suspend](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/ndis-selective-suspend) · Microsoft · Windows puede pasar a un estado de bajo consumo los adaptadores de red inactivos (suspensión selectiva) - [Guidelines for Writing DPC Routines](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/guidelines-for-writing-dpc-routines) · Microsoft · Mientras se ejecuta un DPC, se detienen todos los hilos de ese núcleo, por lo que se recomienda que no supere los 100 µs cada vez - [Wi-Fi low-latency mode](https://source.android.com/docs/core/connect/wifi-low-latency) · Android (Google) · En el modo Wi-Fi de baja latencia de Android, el framework desactiva explícitamente el ahorro de energía del Wi-Fi - [CPU Analysis](https://learn.microsoft.com/en-us/windows-hardware/test/wpt/cpu-analysis) · Microsoft · Gráfico DPC/ISR de WPA: duración de cada tramo en que un DPC o un ISR se ejecutó sin interrupción y módulo (Module) que contiene esa función #### co-other-apps · Otras apps del dispositivo que ocupan el ancho de banda · Other apps saturating the link Si en la misma computadora hay una sincronización en la nube, una descarga grande o el parche de un juego, los paquetes del juego esperan en la cola. - Por qué → Efecto → En pantalla: Otras apps usan al máximo la subida o la bajada → Los paquetes del juego se acumulan en la cola de tu PC y la del router → Ping disparado, input lag, cámara rápida - Síntomas: Input lag, Cámara rápida / Factores: Latencia, Jitter - A quién: Solo yo, Misma casa / Cuándo: De vez en cuando, al azar - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Hacer que nuestro launcher y nuestro patcher pausen o limiten la velocidad de las descargas en segundo plano durante la partida. - Tareas (Externo): Indicar a los jugadores que limiten la velocidad de descarga y que desactiven las actualizaciones automáticas durante la partida. - En el gráfico: Sube con la carga (RTT, tráfico enviado y recibido por el sistema) - Dónde mirar: Registrar Network Interface\Bytes Sent/sec y Bytes Received/sec del Monitor de rendimiento junto con el ping. Es el mismo método que la prueba de bufferbloat, en la que se lanza a propósito una transferencia grande con el ping en marcha - Se confirma si: Mientras la descarga o la subida se acerca a la velocidad de la conexión, el ping sube decenas o cientos de ms, y vuelve a la normalidad en cuanto se detiene la transferencia - Se descarta si: Si el tráfico de tu PC es bajo y aun así el ping sube: “Bufferbloat (cola del router)” causado por otro dispositivo de la casa, o el tramo del ISP - Se verifica con: En el entorno del jugador - Fuentes: - [Introduction](https://www.bufferbloat.net/projects/bloat/wiki/Introduction/) · Bufferbloat.net · Si un router u otro dispositivo de red acumula demasiados datos, la latencia se dispara (bufferbloat) - [Delivery Optimization reference](https://learn.microsoft.com/en-us/windows/deployment/do/waas-delivery-optimization-reference) · Microsoft · Por defecto, las descargas de Windows Update (Optimización de distribución) se ajustan de forma dinámica al ancho de banda disponible, y se pueden fijar límites de ancho de banda para las descargas en segundo y en primer plano - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · Contadores Network Interface: Bytes Received/sec y Bytes Sent/sec - [Tests for Bufferbloat](https://www.bufferbloat.net/projects/bloat/wiki/Tests_for_Bufferbloat/) · Bufferbloat.net · Si, al saturar la conexión con un test de velocidad mientras corre un ping, el ping sube, hay bufferbloat #### co-unfocused · Procesamiento limitado con la ventana minimizada o sin foco · Minimized / unfocused window throttling Si miras otra ventana o minimizas el juego, el juego y Windows lo ralentizan para ahorrar energía. Al volver, los paquetes atrasados llegan de golpe o la conexión ya se cortó. - Por qué → Efecto → En pantalla: Cambiar de ventana con Alt+Tab o minimizar el juego → Mientras no se ve, el juego baja mucho los FPS o se detiene, y Windows también baja la prioridad de los programas que no se ven → Cámara rápida al volver y, si estuvo minimizado mucho tiempo, desconexión - Síntomas: Cámara rápida, Tirones, Desconexión / Factores: Detención - A quién: Solo yo / Cuándo: Al hacer ciertas acciones, Tras un rato inactivo - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Seguir recibiendo paquetes y enviando el heartbeat en un hilo aparte aunque la ventana no se vea, revisar el ajuste “ejecutar en segundo plano” del motor, sincronizar el estado más reciente de una vez al volver. - Cifras de referencia: Si con la ventana oculta los FPS bajan a 5–10, cada frame dura 100–200 ms. Un juego que procesa los paquetes en cada frame los lee con ese mismo retraso. - En el gráfico: Hueco y luego ráfaga (Intervalo entre frames (antes y después de cambiar de ventana), paquetes procesados) - Dónde mirar: Con PresentMon en marcha, probar Alt+Tab y minimizar, y ver el intervalo entre frames con la ventana oculta. Registrar en el log del juego la hora de los cambios de foco de la ventana y cruzarla con el motivo de desconexión - Se confirma si: Con la ventana oculta, el intervalo entre frames sube a 100 ms o más o el registro se corta, y al volver se procesan de una vez los paquetes atrasados, con cámara rápida. Si se deja minimizado mucho tiempo, desconexión por timeout de heartbeat - Se descarta si: Si pasa lo mismo con la ventana visible: “Procesos en segundo plano que ocupan la CPU” o la red - Se verifica con: En el entorno del jugador - Para saber más: Windows 11 no garantiza el temporizador de 1 ms a los programas de ventanas minimizadas o totalmente tapadas que no emiten sonido. En una computadora portátil que funciona con batería, Windows ejecuta esos programas a la velocidad de CPU de menor consumo y, en CPU con núcleos de distintos tipos, puede pasarlos a los núcleos de eficiencia, más lentos. Si de los dos clientes de una misma computadora solo falla el que está en segundo plano, revisa también “Procesamiento limitado de las ventanas en segundo plano”. - Fuentes: - [Quality of Service](https://learn.microsoft.com/en-us/windows/win32/procthread/quality-of-service) · Microsoft · Los programas de ventanas que no se ven ni se oyen se planifican con QoS baja (Low QoS) y, con batería, a la velocidad de CPU más eficiente y en los núcleos de eficiencia - [timeBeginPeriod function (timeapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod) · Microsoft · Windows 11 no garantiza una resolución del temporizador superior a la predeterminada a los procesos de ventanas tapadas o minimizadas - [Application.runInBackground](https://docs.unity3d.com/ScriptReference/Application-runInBackground.html) · Unity · En Unity el valor predeterminado es false, así que el bucle del juego se detiene cuando la ventana pasa a segundo plano - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · MsBetweenPresents: tiempo (ms) entre esta llamada a Present() y la anterior #### co-overlay · Interferencias de programas de overlay · Overlays and screen hooks Los programas de mensajería, los launchers, los grabadores y los contadores de FPS se meten en el proceso de renderizado del juego (hooking) para dibujar su propia UI encima de la imagen. Añaden trabajo en cada frame y, a veces, chocan con el juego y provocan un tirón o un cierre forzado. - Por qué → Efecto → En pantalla: Está activado el overlay de un programa de mensajería, un launcher de juegos, la herramienta de la tarjeta gráfica o un programa de grabación → Cada vez que se envía un frame a la pantalla, el overlay interviene y dibuja encima su propia UI → Los frames se retrasan un poco y, cuando aparece una notificación, hay un tirón, errores gráficos o un cierre forzado (que el jugador percibe como una desconexión) - Síntomas: Tirones, Congelamiento, Desconexión / Factores: Detención - A quién: Solo yo / Cuándo: Siempre, De vez en cuando, al azar - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Recoger la lista de overlays en ejecución junto con los informes de crash y los logs de tirones. - Tareas (Externo): Cuando llegue un reporte, indicar al jugador que desactive todos los overlays y vuelva a probar. - En el gráfico: Alto solo en algunos (Tiempo de frame y número de crashes (jugadores con overlays activados)) - Dónde mirar: Comparar el tiempo de frame de PresentMon en la misma escena con todos los overlays desactivados y, si hay crashes, ver el nombre del módulo con errores (Faulting module name) del evento con ID 1000 en el Visor de eventos - Se confirma si: Al desactivar los overlays desaparecen los tirones y los errores gráficos, o el módulo con errores del crash es una DLL del programa de overlay - Se descarta si: Si pasa lo mismo con todos los overlays desactivados: el driver gráfico o “Crash del cliente” - Se verifica con: En el entorno del jugador - Para saber más: Cuando solo algunos jugadores tienen tirones o cierres del juego y su hardware no lo explica, lo primero que hay que sospechar es un choque entre un overlay y el módulo de seguridad del juego. - Fuentes: - [Steam Overlay (Steamworks Documentation)](https://partner.steamgames.com/doc/features/overlay) · Valve · El overlay de Steam se engancha (hook) automáticamente a los juegos lanzados desde Steam y, por cómo lo hace, puede destapar errores de memoria en el uso que el juego hace de la API de renderizado y provocar crashes - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Graba el tiempo de cada frame con FrameTime (tiempo de CPU entre frames) - [The application or service crashing behavior troubleshooting guidance](https://learn.microsoft.com/en-us/troubleshoot/windows-server/performance/troubleshoot-application-service-crashing-behavior) · Microsoft · El evento con ID 1000 del registro de Aplicación contiene el nombre del módulo con errores (Faulting module name); a veces figura un módulo de Windows como módulo con errores por un daño causado por otro módulo #### co-display-input · Latencia de pantalla, dispositivos de entrada y generación de frames · Display, input device and frame generation latency Si el ping es normal pero el control se siente pesado, puede que el procesamiento de imagen del televisor, un controlador inalámbrico o la generación de frames estén añadiendo latencia entre el input y la pantalla. - Por qué → Efecto → En pantalla: El modo de juego del televisor está desactivado, se usa un controlador Bluetooth o inalámbrico, o la generación de frames (DLSS o FSR Frame Generation) está activada → El televisor envía los frames tarde mientras procesa la imagen, el input inalámbrico llega con el retraso de su ciclo de envío y de las interferencias, y la generación de frames espera al siguiente frame para crear uno intermedio → El ping y los FPS se ven bien, pero lo que presionas tarda en verse en pantalla: input lag - Síntomas: Input lag / Factores: Latencia - A quién: Solo yo / Cuándo: Siempre - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Dejar la generación de frames como opción y avisar de que activarla puede aumentar el input lag, integrar las funciones de baja latencia de los fabricantes de GPU (NVIDIA Reflex, AMD Anti-Lag 2) cuando se use generación de frames, mostrar dentro del juego la latencia de input a pantalla medida en la computadora, pedir al televisor el modo de baja latencia (ALLM) con Window.setPreferMinimalPostProcessing(true) en las builds para Android TV y decodificadores. - Tareas (Externo): Indicar a los jugadores que activen el modo de juego (ALLM) del televisor o el monitor, que en contenido competitivo usen un controlador con cable y desactiven la generación de frames, y que mantengan cerca los dispositivos Bluetooth y usen Wi-Fi de 5 GHz. - Cifras de referencia: Una pantalla de 60 Hz tarda 16.7 ms solo en enviar un frame, y una de 120 Hz, 8.3 ms. Los controladores de Xbox antiguos leían y enviaban el input cada 8 ms. La latencia que añade el procesamiento de imagen del televisor varía según el modelo y no se puede resumir en una cifra; el modo de juego es el ajuste que reduce ese procesamiento. AMD recomienda usar la generación de frames con al menos 60 FPS de base (antes de la generación). - En el gráfico: Siempre alto (Latencia de input a pantalla) - Dónde mirar: Comparar MsAllInputToPhotonLatency de PresentMon (desde el input de teclado o mouse hasta la salida a pantalla) con la generación de frames activada y desactivada, y comprobar con FrameType (solo se registra si el driver o el SDK lo informan) si hay frames intermedios generados. Este valor no incluye el tramo inalámbrico del controlador ni el procesamiento dentro del televisor, así que esa parte se compara alternando el modo de juego del televisor y un controlador con cable - Se confirma si: El ping es normal y la latencia de input a pantalla baja al desactivar la generación de frames, o la latencia que se percibe desaparece al pasar al modo de juego del televisor o a un controlador con cable - Se descarta si: Si nada cambia con todos estos ajustes y el ping es alto o da picos, apunta a la red. Si la latencia dentro de tu PC es alta por el V-Sync o la cola de frames: “V-Sync y cola de renderizado” - Se verifica con: En el entorno del jugador - Para saber más: La latencia de red se ve en el ping, pero esta latencia no aparece en el ping. Por eso es lo primero que hay que revisar ante reportes de “tengo lag con ping bajo”. La generación de frames casi duplica la cifra de FPS en pantalla, pero para crear un frame intermedio tiene que esperar al siguiente frame real, así que aumenta el tiempo que tarda el input en verse en pantalla (AMD indica que, por diseño, aumenta la latencia). Los dispositivos Bluetooth usan la misma banda de 2.4 GHz que el Wi-Fi, así que con interferencias el input puede cortarse o dar saltos. Para el V-Sync y la cola de renderizado, que aumentan la latencia dentro de tu PC, consulta “V-Sync y cola de renderizado”. - Fuentes: - [Auto Low Latency Mode (ALLM)](https://www.hdmi.org/spec21sub/autolowlatencymode) · HDMI Licensing Administrator · ALLM hace que el dispositivo cambie la pantalla automáticamente a un modo de baja latencia (normalmente, el modo de juego); en ese modo el televisor desactiva parte del procesamiento de imagen para reducir la latencia - [Xbox Series X: What’s the Deal with Latency?](https://news.xbox.com/en-us/2020/03/16/xbox-series-x-latency/) · Microsoft · El input lag es la suma de la ruta controlador→consola→HDMI→TV; los controladores antiguos leían y enviaban el input cada 8 ms; enviar un frame por HDMI tarda 16.6 ms a 60 Hz y 8.3 ms a 120 Hz; ALLM cambia automáticamente el televisor al modo de juego - [AMD FSR 3 game integrations out now + more details for developers](https://gpuopen.com/news/fsr3-in-games-technical-details/) · AMD · La interpolación de frames aumenta la latencia por diseño; se recomienda usarla con al menos 60 FPS antes de la interpolación; con 60 FPS de entrada genera hasta 120 FPS de salida - [AMD FSR Frame Generation](https://gpuopen.com/amd-fsr-framegeneration/) · AMD · Se recomienda usar la generación de frames con al menos 60 FPS antes de la interpolación (por debajo de 30 FPS hay que evitarla); AMD Radeon Anti-Lag 2 sincroniza el trabajo de CPU y GPU para reducir la latencia del sistema - [NVIDIA DLSS](https://developer.nvidia.com/rtx/dlss) · NVIDIA · DLSS Frame Generation está diseñado para mantener la capacidad de respuesta junto con NVIDIA Reflex (función de baja latencia) - [Resolve Wi-Fi and Bluetooth issues caused by wireless interference](https://support.apple.com/en-us/102319) · Apple · Las interferencias inalámbricas provocan cortes y pérdida de rendimiento en los dispositivos Wi-Fi y Bluetooth; Bluetooth y Wi-Fi usan la misma banda de 2.4 GHz - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · MsAllInputToPhotonLatency (latencia de input a pantalla), DisplayLatency (del envío del frame a su salida hacia el monitor), FrameType (distingue los frames que dibujó la app de los que interpoló el driver o el SDK) - [PresentMon Console Application (README-ConsoleApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-ConsoleApplication.md) · Intel · MsAllInputToPhotonLatency se basa en los inputs de teclado y mouse; FrameType solo se registra si la app o el driver emiten eventos Intel-PresentMon (--track_frame_type) - [Window.setPreferMinimalPostProcessing](https://developer.android.com/reference/android/view/Window#setPreferMinimalPostProcessing(boolean)) · Android (Google) · Las ventanas en las que la latencia importa, como los juegos, piden a la pantalla un procesamiento de imagen mínimo; con conexión HDMI se envían las señales ALLM y Game Content Type para pasar el televisor a modo de baja latencia ### L3 Red doméstica (causas: 10) #### hn-wifi · Interferencias y señal débil en el Wi-Fi · Wi-Fi interference, weak signal Con señal débil o interferencias, el tramo inalámbrico tiene que reintentar el envío varias veces y los paquetes llegan de forma irregular. - Por qué → Efecto → En pantalla: Paredes, distancia, microondas, Bluetooth o routers vecinos degradan la calidad de la señal → Fallos de transmisión en el tramo inalámbrico → varias retransmisiones → Los paquetes llegan de forma irregular (jitter) y los personajes se mueven a trompicones; en casos graves, la pérdida de paquetes provoca teletransporte - Síntomas: Tirones, Teletransporte, Rubber banding / Factores: Jitter, Pérdida de paquetes - A quién: Solo yo, Misma casa / Cuándo: De vez en cuando, al azar, Siempre - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Ajustar automáticamente la longitud del búfer de interpolación según el estado de la conexión, mostrar en pantalla el estado de la red cuando el jitter o la pérdida sean altos. - Tareas (Externo): Indicar a los jugadores que usen cable o las bandas de 5 GHz o 6 GHz, o que cambien el router de sitio. - Cifras de referencia: Cada retransmisión añade unos 1–4 ms. Con señal débil se retransmite varias veces a baja velocidad y además hay que esperar a que el canal quede libre, así que puede haber picos de 50–200 ms. La trampa es que el ping medio parece normal. - En el gráfico: Picos aleatorios (RTT hasta el router) - Dónde mirar: Medir durante unos minutos con ping /t hasta la dirección del router (la puerta de enlace predeterminada de ipconfig) y ver la intensidad de señal y el canal de tu router con netsh wlan show networks mode=bssid. Comparar con cable en el mismo sitio - Se confirma si: Los picos irregulares de decenas a cientos de ms aparecen ya en el ping al router, con alguna pérdida, y la señal es débil. Con cable o cerca del router desaparece - Se descarta si: Si hasta el router todo es estable y solo hay picos más allá, apunta a la conexión o al tramo del ISP. Si los picos llegan siempre al mismo intervalo: “Escaneo de Wi-Fi en segundo plano” - Se verifica con: En el entorno del jugador - Para saber más: En un Wi-Fi mesh cuyos nodos se conectan entre sí de forma inalámbrica (backhaul inalámbrico), el nodo que repite no puede transmitir mientras recibe y comparte las oportunidades de transmisión con los tramos anterior y posterior que usan el mismo canal, así que con mucho tráfico el throughput puede bajar y la latencia aumentar. En los productos con una banda inalámbrica dedicada al backhaul puede ocurrir menos, y si los nodos se conectan por cable (Ethernet), ese tramo deja de ser inalámbrico. Los adaptadores PLC (por la red eléctrica) también comprueban si el medio está libre antes de transmitir (CSMA/CA), como el Wi-Fi, y su calidad cambia constantemente con el ruido de los electrodomésticos y cuando estos se encienden y se apagan, lo que puede causar reintentos y jitter. - Casos reales: ffxiv-2021 - Fuentes: - [Resolve Wi-Fi and Bluetooth issues caused by wireless interference](https://support.apple.com/en-us/102319) · Apple · Fuentes de interferencia como microondas o teléfonos inalámbricos; Wi-Fi y Bluetooth usan la misma banda de 2.4 GHz; se recomienda pasar a 5 GHz y elegir un canal con menos interferencias - [RFC 8325: Mapping Diffserv to IEEE 802.11](https://www.rfc-editor.org/rfc/rfc8325) · IETF · CSMA/CA de 802.11: solo transmite cuando el canal está libre; si está ocupado, espera a que quede libre y después un backoff aleatorio adicional - [Ending the Anomaly: Achieving Low Latency and Airtime Fairness in WiFi (USENIX ATC 2017)](https://www.usenix.org/system/files/conference/atc17/atc17-hoiland-jorgensen.pdf) · USENIX · Con un Wi-Fi cargado, la cola predeterminada causa cientos de ms de latencia, y un dispositivo conectado a baja velocidad (señal débil) supera los 200 ms de mediana incluso con FQ-CoDel - [ping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ping) · Microsoft · /t: envía solicitudes de eco sin parar hasta que se interrumpe - [ipconfig](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig) · Microsoft · Sin parámetros, muestra las direcciones IPv4 e IPv6 y la puerta de enlace predeterminada de cada adaptador - [Wireless network connectivity issues troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/wireless-network-connectivity-issues-troubleshooting) · Microsoft · netsh wlan show networks mode=bssid: muestra el BSSID, la intensidad de señal, el canal y el tipo de radio de cada red Wi-Fi visible - [Capacity of Ad Hoc Wireless Networks (MobiCom 2001)](https://pdos.csail.mit.edu/papers/grid:mobicom01/paper.pdf) · ACM · Al repetir varias veces por radio 802.11, un nodo no puede transmitir mientras recibe y los tramos contiguos se interfieren entre sí, por lo que el throughput de una ruta de repetición en cadena cae en teoría a un tercio (alrededor de un séptimo en simulación) - [Electri-Fi Your Data: Measuring and Combining Power-Line Communications with WiFi (IMC 2015)](https://conferences.sigcomm.org/imc/2015/papers/p325.pdf) · ACM · Los dispositivos comerciales de comunicación por la red eléctrica (IEEE 1901, HomePlug AV) transmiten con un CSMA/CA parecido al del Wi-Fi, y el reparto desigual a corto plazo puede aumentar el jitter; la calidad del canal varía con el ruido de los electrodomésticos y con su encendido y apagado (en escalas de minutos a horas) #### hn-channel · Canal Wi-Fi saturado · Crowded Wi-Fi channel En sitios con decenas de routers, como un edificio de apartamentos, hay que compartir el mismo canal y esperar turno para transmitir. - Por qué → Efecto → En pantalla: Decenas de routers usan el mismo canal de 2.4 GHz → Para transmitir hay que esperar a que los demás dispositivos terminen y el canal quede libre → Por la noche, cuando la gente vuelve a casa, aumenta el jitter (variación en el tiempo de llegada de los paquetes) y hay tirones - Síntomas: Tirones, Input lag / Factores: Jitter, Latencia - A quién: Misma casa / Cuándo: Horas pico de la noche - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Alargar automáticamente el búfer de interpolación cuando aumente el jitter. - Tareas (Externo): Indicar a los jugadores que usen 5 GHz o 6 GHz, un canal menos saturado o cable. - En el gráfico: Alto solo a ciertas horas (RTT y jitter hasta el router) - Dónde mirar: Ver con netsh wlan show networks mode=bssid los canales y la intensidad de señal de las redes Wi-Fi cercanas, y comparar el ping al router por la noche y durante el día - Se confirma si: Se detectan muchos routers cercanos en el mismo canal de 2.4 GHz y el jitter hasta el router solo crece por la noche. Al pasar a 5 GHz o 6 GHz o a un canal menos saturado, disminuye - Se descarta si: Si los picos no dependen de la hora: “Interferencias y señal débil en el Wi-Fi”. Si hasta el router va bien y por la noche solo empeora lo que hay más allá: “Congestión del peering en horas pico” - Se verifica con: En el entorno del jugador - Fuentes: - [Recommended settings for Wi-Fi routers and access points](https://support.apple.com/en-us/102766) · Apple · Otros routers y dispositivos que usan el mismo canal son fuentes de interferencia; en 2.4 GHz se recomienda un ancho de canal de 20 MHz; en 5 GHz y 6 GHz hay menos problemas de interferencia - [RFC 8325: Mapping Diffserv to IEEE 802.11](https://www.rfc-editor.org/rfc/rfc8325) · IETF · Si el canal está ocupado, 802.11 aplaza la transmisión hasta que quede libre y transmite tras un backoff aleatorio (CSMA/CA) - [Wireless network connectivity issues troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/wireless-network-connectivity-issues-troubleshooting) · Microsoft · netsh wlan show networks mode=bssid: muestra el BSSID, la intensidad de señal, el canal y el tipo de radio de cada red Wi-Fi visible - [ping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ping) · Microsoft · /t: envía solicitudes de eco sin parar hasta que se interrumpe #### hn-bufferbloat · Bufferbloat (cola del router) · Bufferbloat Cuando alguien de la familia sube un video o descarga un archivo grande, se acumulan en la cola del router cientos de ms de paquetes, y los paquetes del juego también esperan detrás. - Por qué → Efecto → En pantalla: Las subidas de video o las copias de seguridad en la nube de la familia, tu propio streaming o una descarga grande saturan la conexión → El router o el módem acumulan los paquetes que sobran en una cola grande → Los paquetes del juego también esperan al final de la cola y el ping se dispara a cientos de ms - Síntomas: Input lag, Cámara rápida, Teletransporte / Factores: Latencia, Jitter - A quién: Misma casa, Solo yo / Cuándo: De vez en cuando, al azar, Horas pico de la noche - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Mostrar en pantalla el estado de la red cuando el ping sube de golpe a cientos de ms (avisar de que puede haber una transferencia grande en la misma conexión). - Tareas (Externo): Indicar a los jugadores que usen un router con SQM (fq_codel, CAKE) o QoS, que ajusten la velocidad del SQM al 90–95% de la velocidad de la conexión (así la cola se forma dentro del router y tiene efecto) y que limiten la velocidad de subida. - Cifras de referencia: En una conexión de 10 Mbps de subida con un búfer de 1 MB, la cola puede llegar a 800 ms. - En el gráfico: Sube con la carga (RTT, uso de subida y bajada de la conexión) - Dónde mirar: Saturar la conexión con un test de velocidad con el ping en marcha, o usar una prueba web que mida la latencia bajo carga (guía de Bufferbloat.net). Verlo junto con el uso de subida y bajada en la pantalla del router - Se confirma si: Mientras la subida o la bajada saturan la conexión, el ping sube a cientos de ms y vuelve a la normalidad al terminar la transferencia (sospechar si la latencia bajo carga supera los 50 ms). Al activar el SQM, desaparece - Se descarta si: Si el ping da picos con la conexión desocupada: “Interferencias y señal débil en el Wi-Fi” o “Mala calidad de la conexión” - Se verifica con: En el entorno del jugador - Para saber más: La subida es la que más se atasca, porque en las conexiones por cable coaxial y en las móviles la subida suele ser mucho más estrecha que la bajada. En casas con fibra de sobra, el cuello de botella pasa al tramo Wi-Fi y lo mismo ocurre en la cola inalámbrica del router. Los paquetes del juego son pequeños y casi no consumen ancho de banda, pero tienen que esperar en la cola igual que los demás. Si solo se atasca la subida, solo tus inputs llegan tarde y los movimientos de los demás se ven bien. En el teléfono pasa lo mismo cuando la copia de seguridad de fotos o las actualizaciones de apps del propio teléfono llenan las colas de su módem y de la estación base. - Fuentes: - [Setting up SQM for CeroWrt 3.10](https://www.bufferbloat.net/projects/cerowrt/wiki/Setting_up_SQM_for_CeroWrt_310/) · Bufferbloat.net · Hay que bajar la velocidad del SQM al 95% de la velocidad medida (o al 85% si se toma la velocidad anunciada) para traer el cuello de botella desde los dispositivos del ISP al interior del router; solo así tiene efecto - [SQM (Smart Queue Management)](https://openwrt.org/docs/guide-user/network/traffic-shaping/sqm) · OpenWrt · Introducir como velocidades de bajada y subida el 90% de lo medido; se recomienda cake como disciplina de cola (fq_codel si la CPU es débil) - [Ending the Anomaly: Achieving Low Latency and Airtime Fairness in WiFi (USENIX ATC 2017)](https://www.usenix.org/system/files/conference/atc17/atc17-hoiland-jorgensen.pdf) · USENIX · Cuando el tramo Wi-Fi se satura, se generan cientos de ms de latencia en la cola inalámbrica del router; al corregir la cola inalámbrica, la latencia bajo carga baja a una décima parte aproximadamente - [Tests for Bufferbloat](https://www.bufferbloat.net/projects/bloat/wiki/Tests_for_Bufferbloat/) · Bufferbloat.net · Si, al saturar la conexión con un test de velocidad mientras corre un ping, el ping sube, hay bufferbloat; si la latencia bajo carga supera los 50 ms (o la nota es inferior a B), se recomienda tomar medidas #### hn-nat · Expiración del mapeo NAT · NAT mapping timeout El router borra de la tabla NAT las conexiones inactivas por las que no pasa ningún paquete durante un tiempo. Es una causa habitual de desconexión justo cuando el jugador vuelve a moverse tras un rato quieto. - Por qué → Efecto → En pantalla: El router registra la conexión “dispositivo interno ↔ servidor externo” en la tabla NAT (tabla de traducción de direcciones) → Si no hay paquetes durante un tiempo, la entrada se borra de la tabla (en UDP, normalmente 30–120 s) → Los paquetes del servidor ya no pueden entrar en la casa y se produce la desconexión - Síntomas: Desconexión / Factores: Pérdida de paquetes - A quién: Solo yo, Misma casa / Cuándo: Tras un rato inactivo - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: enviar heartbeats a un intervalo igual o inferior a la mitad del timeout por inactividad más corto (el mapeo UDP solo se renueva con seguridad con los paquetes que salen de la casa, así que los envía el cliente), reconectar automáticamente si se corta. Servidor: responder a los heartbeats y, si deja de recibirlos durante un tiempo, cerrar primero la conexión; si se borra el mapeo y cambian la dirección y el puerto externos, confirmar con el token de sesión (el código de verificación que se recibe al conectar) que es el mismo jugador y retomar la sesión. - En el gráfico: Desconexión masiva (Desconexiones (timeout de heartbeat), tiempo de inactividad previo a la desconexión) - Dónde mirar: Reunir el motivo de desconexión en el servidor y el tiempo transcurrido desde el último paquete de esa conexión antes del corte (tiempo de inactividad), y ver su distribución. Para probarlo, alargar el intervalo entre paquetes UDP a 30, 60 y 120 s y medir a partir de qué intervalo dejan de llegar respuestas - Se confirma si: Solo se cortan las conexiones que estaban inactivas, y el tiempo de inactividad se concentra justo después de un valor concreto, entre 30 y 120 s. Con un intervalo de heartbeat más corto que ese valor, desaparece - Se descarta si: Si también se corta durante el movimiento, apunta a la conexión o a la ruta. Si solo se concentra en valores cortos con un operador móvil concreto: “IP compartida del ISP (CGNAT)” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP](https://www.rfc-editor.org/rfc/rfc4787) · IETF · El temporizador del mapeo UDP no debe expirar antes de 2 minutos y se recomienda 5 minutos o más por defecto; la renovación con paquetes salientes es obligatoria y con paquetes entrantes, opcional - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · Medición en 34 routers domésticos: el mapeo UDP dura 30–691 s, con una mediana de 90 s, y en más de la mitad dura menos de 2 minutos; en TCP la mediana es de unos 60 minutos - [RFC 9308: Applicability of the QUIC Transport Protocol](https://www.rfc-editor.org/rfc/rfc9308) · IETF · En internet, con NAT en la ruta, un keep-alive cada 30 segundos aproximadamente es razonable; más frecuente desperdicia tráfico y energía #### hn-router · Router poco potente o sobrecalentado · Router CPU / session table exhaustion Cuando un router barato tiene decenas de dispositivos y miles de conexiones, el propio router no da abasto. - Por qué → Efecto → En pantalla: Decenas de dispositivos y programas P2P o torrent abren miles de conexiones → La CPU y la tabla de sesiones del router se saturan → Retraso y pérdida en el procesamiento de paquetes, fallos al abrir conexiones nuevas - Síntomas: Tirones, No conecta / carga infinita, Desconexión / Factores: Pérdida de paquetes, Jitter - A quién: Misma casa / Cuándo: Cuanto más tiempo lleva encendido, De vez en cuando, al azar - Responsable principal: Externo (Externo) - Tareas (Externo): Indicar a los jugadores que reinicien el router (solución temporal), que lo cambien o que cierren los programas que abren muchas conexiones (P2P, torrent). - En el gráfico: Topa con el límite (CPU y conexiones del router, RTT hasta el router) - Dónde mirar: En la interfaz de administración del router, ver el uso de CPU, el número de conexiones (sesiones) y de dispositivos conectados (si el router lo permite), y comparar el ping al propio router antes y después de reiniciarlo - Se confirma si: Con muchas conexiones, los picos o las pérdidas aparecen ya en el ping al router y fallan las conexiones nuevas. Tras reiniciar, va bien un tiempo y luego vuelve a empeorar - Se descarta si: Si hasta el router todo va bien y solo falla lo que hay más allá, apunta a la conexión o al tramo del ISP - Se verifica con: En el entorno del jugador - Fuentes: - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · Los routers domésticos admiten entre 16 y unas 1,024 conexiones TCP hacia un mismo puerto de servidor (mediana: 135), y algunos modelos baratos no pasan de unos pocos Mbps de throughput - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · Número máximo de entradas de la tabla de seguimiento de conexiones de Linux (nf_conntrack_max) y tiempos de retención predeterminados por estado #### hn-handover · Handover entre estaciones base (en movimiento) · Cellular handover Al viajar en autobús o en metro, la comunicación se corta mientras el teléfono cambia de estación base. - Por qué → Efecto → En pantalla: Al desplazarse, cambia la estación base a la que está conectado el dispositivo → Normalmente es un hueco de decenas de ms, pero si la señal es mala y el cambio falla, puede cortarse de cientos de ms a varios segundos → Se detiene y luego hay teletransporte; si dura mucho, desconexión - Síntomas: Congelamiento, Teletransporte, Desconexión / Factores: Pérdida de paquetes - A quién: Solo yo / Cuándo: Al moverse o cambiar de zona - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: usar un timeout que tolere cortes breves, reconectar rápido. Servidor: usar un timeout que no expulse al jugador por unos segundos de corte, retomar la misma sesión al reconectar. - Tareas (Externo): Explicar a los jugadores que los cortes en movimiento (autobús, metro) se deben al cambio de estación base. - En el gráfico: Hueco y luego ráfaga (Paquetes recibidos, RTT) - Dónde mirar: Comprobar si el reporte de corte se produjo en movimiento (autobús, metro) y ver en el log del cliente las horas de los huecos de recepción y los cambios de tipo de red y de señal - Se confirma si: Solo en movimiento la recepción se queda vacía de cientos de ms a varios segundos y luego llega de golpe; estando quieto, no se reproduce - Se descarta si: Si pasa lo mismo estando quieto: “Señal móvil débil y zonas sin cobertura” o “Cambios frecuentes 5G↔LTE (en el límite de la cobertura 5G)” - Se verifica con: En el entorno del jugador - Fuentes: - [Report ITU-R M.2134: Requirements related to technical performance for IMT-Advanced radio interface(s)](https://www.itu.int/pub/R-REP-M.2134-2008) · ITU · Requisito del tiempo sin intercambio de datos durante el handover: 27.5 ms en la misma frecuencia y 40–60 ms entre frecuencias distintas - [Understanding Operational 5G: A First Measurement Study on Its Coverage, Performance and Energy Consumption (SIGCOMM 2020)](https://xyzhang.ucsd.edu/papers/DXu_SIGCOMM20_5Gmeasure.pdf) · ACM · Latencia de handover medida en redes comerciales: 4G↔4G, 30 ms de media; entre celdas 5G (NSA), 108 ms de media #### hn-rrc · Retraso en el cambio de estado RRC (ahorro de energía de la radio móvil) · Radio state promotion (RRC) Si no hay comunicación durante un rato, el teléfono pasa la conexión de radio a un estado de bajo consumo, y al llegar el siguiente paquete tarda en volver a activarla. - Por qué → Efecto → En pantalla: Tras un rato sin comunicación, el teléfono pasa la conexión de radio a ahorro de energía → Para enviar el siguiente paquete, hay que volver a activar la conexión → Solo la primera acción tras un rato quieto llega especialmente tarde - Síntomas: Input lag / Factores: Latencia - A quién: Solo yo / Cuándo: Tras un rato inactivo - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Mantener la conexión activa con envíos periódicos ligeros (a costa de la batería). - Cifras de referencia: En LTE, la radio suele pasar a ahorro de energía tras unos 10 segundos sin comunicación, y reactivarla lleva de decenas a cientos de ms (ejemplo medido: unos 0.3–0.6 s). En 3G, más de 1 segundo. - En el gráfico: Alto solo en algunos (RTT de la primera solicitud tras inactividad (red móvil)) - Dónde mirar: Ver el RTT del juego agrupado según el intervalo desde la comunicación anterior. En red móvil, comparar el RTT del primer paquete enviado tras más de 10 segundos de inactividad con el de los paquetes enviados seguidos - Se confirma si: En la red móvil, solo el primer paquete tras la inactividad llega cientos de ms tarde y los enviados justo después son normales. En Wi-Fi no hay diferencia - Se descarta si: Si también llegan tarde los paquetes enviados seguidos, apunta a la señal, la conexión o la ruta - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [An In-depth Study of LTE: Effect of Network Protocol and Application Behavior on Performance (SIGCOMM 2013)](https://conferences.sigcomm.org/sigcomm/2013/papers/sigcomm/p363.pdf) · ACM · Temporizador de paso a ahorro de energía (tail) medido en la red LTE: 10 segundos; mediana de la latencia de reactivación: 435 ms (percentiles 25–75: 319–558 ms); en 3G, unos 1.5–2 segundos - [Optimize network access](https://developer.android.com/develop/connectivity/network-ops/network-access-optimization) · Android (Google) · La latencia de cambio de estado de la radio y el tiempo de tail dependen de la tecnología (3G, LTE, 5G) y de la configuración del operador; ejemplo en 3G: de bajo consumo a máxima potencia, unos 1.5 s; de reposo a máxima potencia, más de 2 s - [Report ITU-R M.2134: Requirements related to technical performance for IMT-Advanced radio interface(s)](https://www.itu.int/pub/R-REP-M.2134-2008) · ITU · Requisito de latencia del plano de control para pasar de reposo a activo: menos de 100 ms (sin contar el paging ni el tramo cableado) #### hn-weak-cell · Señal móvil débil y zonas sin cobertura · Weak cellular signal En ascensores, sótanos o el interior de los edificios aumentan las retransmisiones, baja la velocidad y al final se cae la conexión. - Por qué → Efecto → En pantalla: Moverse a un sitio con poca señal → Más retransmisiones por radio, menor velocidad, cortes momentáneos → Tirones y teletransporte por el jitter y la pérdida, y al final desconexión - Síntomas: Tirones, Teletransporte, Desconexión / Factores: Jitter, Pérdida de paquetes - A quién: Solo yo / Cuándo: Al moverse o cambiar de zona - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Pulir el flujo de reconexión, mostrar la calidad de la red. - Tareas (Externo): Explicar a los jugadores que el problema aparece en sitios con poca señal (ascensores, sótanos, interior de edificios). - En el gráfico: Alto solo en algunos (RTT y pérdida (por jugador en red móvil)) - Dónde mirar: Comprobar el lugar del reporte de corte (ascensor, sótano, interior de un edificio) y el indicador de señal del teléfono, y repetir la misma acción en un sitio con buena señal para comparar - Se confirma si: Solo en sitios con poca señal suben el RTT y la pérdida y se corta la conexión, y al pasar a un sitio con buena señal desaparece - Se descarta si: Si pasa lo mismo con buena señal, apunta al tramo del ISP o al servidor - Se verifica con: En el entorno del jugador - Fuentes: - [An In-depth Study of LTE: Effect of Network Protocol and Application Behavior on Performance (SIGCOMM 2013)](https://conferences.sigcomm.org/sigcomm/2013/papers/sigcomm/p363.pdf) · ACM · LTE oculta la pérdida en el tramo de radio con retransmisiones en las capas física y MAC; el ancho de banda disponible varía mucho de un segundo a otro según la intensidad de la señal, entre otros factores #### hn-5g-flip · Cambios frecuentes 5G↔LTE (en el límite de la cobertura 5G) · 5G NSA / LTE switching En el interior de edificios con poca señal 5G o en el límite de la cobertura 5G, el teléfono salta a menudo entre 5G y LTE, y en cada cambio el ping da un pico o la comunicación se corta un instante. - Por qué → Efecto → En pantalla: Estar en un sitio donde la señal 5G va y viene (interior de edificios, límite de la cobertura 5G) → El teléfono cambia constantemente entre 5G y LTE, y cada cambio deja un hueco breve → Picos de ping sin patrón aun estando quieto y, de vez en cuando, congelamientos o teletransporte - Síntomas: Tirones, Teletransporte, Congelamiento / Factores: Jitter, Pérdida de paquetes - A quién: Solo yo / Cuándo: De vez en cuando, al azar, Al moverse o cambiar de zona - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Alargar automáticamente el búfer de interpolación cuando aumente el jitter, registrar los cambios de tipo de red (5G, LTE) en los logs que se toman cuando hay lag, para distinguir la causa. - Tareas (Externo): Indicar a los jugadores que prueben a cambiar a modo LTE preferente en los ajustes para comparar, y recomendar el uso de Wi-Fi. - Cifras de referencia: Cada cambio, de decenas a cientos de ms. En Corea, la mayor parte del 5G funciona combinado con LTE (NSA), por lo que es fácil que la parte 5G se conecte y se desconecte. - En el gráfico: Picos aleatorios (RTT, cambios de tipo de red (5G, LTE)) - Dónde mirar: Cambiar el teléfono a LTE preferente y comparar en el mismo sitio. Es más concluyente si el cliente registra junto con el RTT los cambios del indicador de red de TelephonyDisplayInfo en Android (OVERRIDE_NETWORK_TYPE_NR_NSA, etc.) - Se confirma si: Los picos de RTT coinciden con los cambios del indicador 5G↔LTE, y en modo LTE preferente desaparecen - Se descarta si: Si hay picos sin que cambie el indicador de red: “Señal móvil débil y zonas sin cobertura” o la conexión - Se verifica con: En el entorno del jugador - Fuentes: - [Understanding Operational 5G: A First Measurement Study on Its Coverage, Performance and Energy Consumption (SIGCOMM 2020)](https://xyzhang.ucsd.edu/papers/DXu_SIGCOMM20_5Gmeasure.pdf) · ACM · El 5G NSA delega el control en LTE: al cambiar de celda 5G suelta el 5G, pasa por LTE y se vuelve a conectar, con una media de 108 ms (80 ms de 4G a 5G); justo después de un cambio en el que interviene el 5G, el throughput de TCP cae un 73–83% - [5G 통신서비스 품질평가 결과 발표](https://www.korea.kr/briefing/policyBriefingView.do?newsId=156404679) · 과학기술정보통신부 · Según lo publicado en 2020, el 5G en Corea se ofrecía en modo NSA y el paso a SA estaba previsto - [TelephonyDisplayInfo](https://developer.android.com/reference/android/telephony/TelephonyDisplayInfo) · Android (Google) · OVERRIDE_NETWORK_TYPE_NR_NSA: indicador de red cuando el dispositivo, conectado a LTE, puede usar o está usando conectividad dual con 5G (NR) (EN-DC) #### hn-captive · Restricciones en Wi-Fi público y redes corporativas · Captive portal, restrictive network La página de inicio de sesión del Wi-Fi de una cafetería o el firewall de la empresa bloquean la conexión del juego. - Por qué → Efecto → En pantalla: Aún no se completó la autenticación en la página de inicio de sesión, o el firewall bloquea los puertos del juego o UDP → Se bloquea el propio intento de conexión o solo pasa una parte → El juego no conecta, o se inicia sesión pero no se puede entrar a la partida - Síntomas: No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Solo yo / Cuándo: Al conectar o tras un mantenimiento - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: mostrar el motivo cuando la conexión esté bloqueada (autenticación pendiente en la página de inicio de sesión, UDP bloqueado, etc.), pasar automáticamente a una ruta alternativa si UDP está bloqueado. Servidor: ofrecer una ruta alternativa, como TCP 443. - Tareas (Externo): Indicar a los jugadores que en un Wi-Fi público completen primero la autenticación en la página de inicio de sesión y que, en redes restringidas como las de empresa, usen otra red. - En el gráfico: Alto solo en algunos (Fallos de conexión (por red)) - Dónde mirar: Pedir al jugador afectado que pruebe a conectarse por otra red, como los datos móviles, y ver en los logs de conexión del servidor si llegó el primer paquete UDP y si conecta por la ruta alternativa TCP 443 - Se confirma si: Solo falla en un Wi-Fi concreto (cafetería, empresa) y por otras redes conecta enseguida. La autenticación en la página de inicio de sesión está pendiente o solo el tráfico UDP no llega al servidor - Se descarta si: Si falla en cualquier red, apunta a la cuenta, al servidor o a “Fallos y lentitud del DNS”. Si falla en todo un país o un ISP: “Restricciones de UDP e inspección de paquetes por país o ISP” - Se verifica con: En el entorno del jugador - Fuentes: - [RFC 8952: Captive Portal Architecture](https://www.rfc-editor.org/rfc/rfc8952) · IETF · Portal cautivo: red que limita el acceso hasta que se cumplen requisitos como aceptar unas condiciones o autenticarse - [RFC 9308: Applicability of the QUIC Transport Protocol](https://www.rfc-editor.org/rfc/rfc9308) · IETF · Según estudios de medición, el 3–5% de las redes bloquean todo el tráfico UDP, así que las apps basadas en UDP deben tener preparada una ruta alternativa por TCP (TLS) ### L4 Ruta por internet (causas: 14) #### isp-distance · Retardo de propagación (distancia física) · Propagation delay Ni siquiera la luz pasa de unos 200,000 km por segundo dentro de la fibra óptica. Un servidor lejano siempre responde tarde, por muy bueno que sea. - Por qué → Efecto → En pantalla: El servidor está lejos (servidor en el extranjero, otro continente) → El tiempo de ida y vuelta crece con la distancia (al menos 10 ms por cada 1,000 km) → Input lag constante en todas las acciones y desventaja en el registro de impactos - Síntomas: Input lag / Factores: Latencia - A quién: Una región o un ISP / Cuándo: Siempre - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Infraestructura de red (Equipo de infraestructura), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Solo cabe mitigarlo (el código no cambia las leyes de la física), ofrecer selección de región para que el jugador elija un servidor cercano, reducir la desventaja en el registro de impactos con compensación de lag (rebobinado). - Tareas (Equipo de infraestructura): Servidores/SO: poner servidores regionales donde haya muchos jugadores. Red: poner puntos de presencia (edge) cerca de los jugadores, elegir enlaces y rutas con menos rodeos. - Cifras de referencia: Seúl–Tokio, unos 30 ms; Seúl–Singapur, unos 75 ms; Seúl–costa oeste de EE. UU., unos 140 ms; Seúl–Europa, unos 230–270 ms (ida y vuelta, por rutas reales). Hacia Europa casi no hay cables importantes en línea recta, así que el tráfico da un rodeo por el sudeste asiático y Suez o por EE. UU., y la latencia es mucho mayor de lo que indicaría la distancia. - En el gráfico: Siempre alto (RTT (por país/región)) - Dónde mirar: Etiquetar las IP de conexión con su país y ver la distribución del RTT por país. Medir con ping y traceroute hasta el servidor desde una VM en una región de nube de esa zona o desde sondas de RIPE Atlas (elegidas por país o ASN) - Se confirma si: El RTT de los países lejanos es siempre alto, sin importar la hora, y se acerca a la latencia mínima calculada por la distancia (10 ms de ida y vuelta por cada 1,000 km) y a las estadísticas públicas de latencia - Se descarta si: Si es mucho más alto de lo que explica la distancia, apunta a “Enrutamiento con rodeos”; si solo sube por la noche, a “Congestión del peering en horas pico” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Casos reales: riot-direct-2015 - Fuentes: - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Valor de planificación del retardo de propagación en fibra óptica: 5 µs/km (unos 200,000 km por segundo, 10 ms de ida y vuelta por cada 1,000 km) - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Mediana medida del tiempo de ida y vuelta desde Seúl (Korea Central): Tokio 30 ms, Singapur 68 ms, oeste de EE. UU. 124–136 ms, Europa 234–244 ms - [AAE-1 & SMW5 cable cuts impact millions of users across multiple countries](https://blog.cloudflare.com/aae-1-smw5-cable-cuts/) · Cloudflare · El tráfico entre Europa y Asia pasa casi siempre por cables submarinos que cruzan Egipto (Suez) - [Probe Selection (RIPE Atlas REST API)](https://atlas.ripe.net/docs/apis/rest-api-manual/measurements/creating-measurements/probe-selection/) · RIPE NCC · Las sondas de una medición de RIPE Atlas se eligen por país, región, ASN o rango de direcciones para ejecutar ping y traceroute #### isp-satellite · Internet satelital (órbita baja y geoestacionaria) · Satellite internet (LEO, GEO) En internet satelital la señal tiene que ir al espacio y volver. Con satélites geoestacionarios, solo la ida y vuelta ya supera los 0.5 segundos. Los satélites de órbita baja como Starlink suelen ser rápidos, pero cuando se reasigna la ruta la latencia oscila y la conexión puede cortarse un instante. - Por qué → Efecto → En pantalla: Conexión desde casa, un barco o un avión por internet satelital geoestacionario o de órbita baja, o por Wi-Fi a bordo que usa satélites → El satélite geoestacionario está a unos 36,000 km de altura, así que el recorrido ya es largo de por sí. En órbita baja, la ruta terminal–satélite–estación terrestre se reasigna a intervalos cortos y en cada cambio aparecen latencia y pérdida de paquetes durante un momento → Geoestacionario: input lag grande en todas las acciones. Órbita baja: bien la mayor parte del tiempo, pero con tirones y teletransporte a intervalos regulares - Síntomas: Input lag, Tirones, Teletransporte / Factores: Latencia, Jitter, Pérdida de paquetes - A quién: Solo yo, Misma casa, Una región o un ISP / Cuándo: Siempre, A intervalos regulares - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: alargar automáticamente el búfer de interpolación según el jitter, enviar los inputs duplicados para aguantar pérdidas breves, mostrar la calidad de la conexión. Servidor: tener en cuenta la latencia satelital al fijar las ventanas de tiempo y el límite de la compensación de lag, usar timeouts que no expulsen al jugador por huecos de alrededor de 1 segundo. - Tareas (Externo): Indicar a los jugadores que internet satelital puede tener latencia alta o picos periódicos, recomendar una conexión terrestre por cable para el contenido competitivo siempre que se pueda. - Cifras de referencia: En órbita geoestacionaria (36,000 km de altura), la señal tarda 260 ms en un solo sentido solo en cruzar el espacio, así que la ida y vuelta supera los 520 ms (ITU-T G.114). Para Starlink, en órbita baja, los datos oficiales (promedios de 15 segundos) dan una mediana de 33 ms en horas pico en EE. UU., y aun el peor 1% (p99) queda por debajo de 65 ms (2024). Estudios de medición observaron que la latencia cambia en cada reasignación de ruta, cada 15 segundos, con cortes breves de menos de 1 segundo. En mediciones de internet a bordo de 2018, la latencia media de ida y vuelta de los sistemas satelitales fue de 750 ms. - En el gráfico: Alto solo en algunos (RTT/jitter (por ASN del proveedor satelital)) - Dónde mirar: Comprobar si el ASN de la IP de conexión es de un proveedor de internet satelital y graficar aparte la distribución y la serie temporal del RTT de sus jugadores. Medir con ping durante unos minutos seguidos desde sondas de RIPE Atlas de ese ASN hasta el servidor, o pedir al jugador que deje un ping corriendo y mida el intervalo entre picos - Se confirma si: Proveedores geoestacionarios: RTT siempre por encima de 500 ms. Proveedores de órbita baja: normalmente decenas de ms, con cambios de RTT o cortes breves aproximadamente cada 15 s - Se descarta si: Si no es un proveedor satelital y el RTT es siempre alto, apunta a “Retardo de propagación (distancia física)” o “Enrutamiento con rodeos”; si hay picos irregulares, a la señal del Wi-Fi o de la red móvil - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Los satélites de órbita baja están cerca (un salto de Starlink tarda 1.8–3.6 ms), así que la latencia habitual puede parecerse a la de una conexión terrestre. Pero si el punto donde la estación terrestre sale a internet (PoP) está lejos del servidor del juego, la ruta se alarga en la misma medida, y si el tráfico da un rodeo por los enlaces láser entre satélites, se suma más latencia. Los estudios de medición atribuyen la oscilación cada 15 segundos a una reasignación de rutas que ocurre en el mismo instante en todo el mundo, sin relación con el cambio de satélite. La latencia del Wi-Fi a bordo varía mucho según la tecnología (satélite o estaciones base terrestres), y los sistemas que usan satélites geoestacionarios tienen la misma ida y vuelta larga descrita arriba. - Fuentes: - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Valores de planificación del retardo de propagación en un sentido para enlaces satelitales: 12 ms a 400 km de altura, 110 ms a 14,000 km, 260 ms a 36,000 km (geoestacionario) - [Improving Starlink’s Latency](https://starlink.com/public-files/StarlinkLatency.pdf) · Starlink · Mediana en horas pico en EE. UU.: 48.5 ms→33 ms; el 1% más lento (p99): más de 150 ms→menos de 65 ms (2024); propagación en un salto satelital: 1.8–3.6 ms; los rodeos por enlaces láser suman latencia, y la distancia de la estación terrestre al punto de acceso a internet (PoP) también influye - [A Multifaceted Look at Starlink Performance (WWW 2024)](https://www.nitindermohan.com/documents/2024/pubs/starlinkWWW2024.pdf) · ACM · Starlink reasigna las rutas cada 15 segundos en el mismo instante en todo el mundo; en esos límites oscilan la latencia y el throughput y aparecen cortes breves de menos de 1 segundo (no se deben al cambio de satélite); latencia del tramo terminal↔satélite↔estación terrestre: unos 40 ms - [Mile High WiFi: A First Look at In-Flight Internet Connectivity (WWW 2018)](https://aqualab.cs.northwestern.edu/publication/2018/jrula-www18/) · ACM · 45 horas de mediciones de internet a bordo: latencia media de ida y vuelta de 200 ms con estaciones base terrestres y de 750 ms con satélite; mediana de pérdida de paquetes del 7% con satélite - [Probe Selection (RIPE Atlas REST API)](https://atlas.ripe.net/docs/apis/rest-api-manual/measurements/creating-measurements/probe-selection/) · RIPE NCC · Las sondas de una medición de RIPE Atlas se eligen por país, región, ASN o rango de direcciones para ejecutar ping y traceroute #### isp-routing · Enrutamiento con rodeos · Suboptimal routing Por los acuerdos de interconexión entre ISP, el tráfico hacia un servidor cercano puede dar un rodeo por un lugar lejano. - Por qué → Efecto → En pantalla: Tu ISP y el ISP del servidor no están conectados directamente → El tráfico pasa por otro país u otra ciudad, con más distancia y más dispositivos en el camino → Solo los jugadores de ciertos ISP tienen un ping especialmente alto - Síntomas: Input lag / Factores: Latencia - A quién: Una región o un ISP / Cuándo: Siempre - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Externo (Externo) - Tareas (Equipo de infraestructura): Conectarse a varios ISP (multihoming), monitorear el ping por ISP para encontrar los que dan rodeos, negociar ajustes de ruta con los ISP. - Tareas (Externo): Pedir al ISP afectado que ajuste la ruta. - Cifras de referencia: Incluso dentro del mismo país, el ping puede ser dos o tres veces mayor según la ruta. - En el gráfico: Siempre alto (RTT (por ISP/ASN)) - Dónde mirar: Comparar el RTT por ISP (ASN) y ver por qué países y ciudades pasa la ruta con traceroute o mtr desde sondas de RIPE Atlas del ISP lento o desde los jugadores. Medir IPv4 e IPv6 por separado (mtr -4, -6) - Se confirma si: En la misma región, un ISP concreto está siempre más alto y su ruta pasa por otro país o por una ciudad lejana. O solo una familia de direcciones (IPv4 o IPv6) está alta - Se descarta si: Si todos los ISP están igual de altos, apunta a “Retardo de propagación (distancia física)”; si solo sube por la noche, a “Congestión del peering en horas pico” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: En IPv4 e IPv6 las rutas se eligen por separado, así que con el mismo servidor una de las dos puede dar un rodeo largo y ser lenta (una medición de APNIC de 2016 encontró, dentro de un mismo ISP, grupos de usuarios en los que IPv6 era 15, 25 o 75 ms más lento que IPv4). Las apps que usan Happy Eyeballs (RFC 8305) se quedan con la que conecte primero entre IPv6 e IPv4: prueban IPv6 primero y, si conecta dentro de los 250 ms recomendados, ni siquiera intentan IPv4. Por eso tienden a conectarse por IPv6 aunque esa ruta sea algo más lenta. Si el ping es alto solo en un ISP concreto, hay que medir IPv4 e IPv6 por separado. - Casos reales: riot-direct-2015 - Fuentes: - [Quantifying the Causes of Path Inflation (SIGCOMM 2003)](https://conferences.sigcomm.org/sigcomm/2003/papers/p113-spring.pdf) · ACM · Análisis de 65 ISP: las políticas de peering entre ISP y el enrutamiento entre dominios alargan mucho las rutas - [The Internet at the Speed of Light (HotNets 2014)](https://conferences.sigcomm.org/hotnets/2014/papers/hotnets-XIII-final111.pdf) · ACM · Las rutas reales entre routers miden alrededor de 1.5 veces (mediana) la distancia en línea recta por fibra, y hay casos en que los paquetes entre dos puntos cercanos dan la vuelta por el otro lado del planeta (hairpinning) - [Probe Selection (RIPE Atlas REST API)](https://atlas.ripe.net/docs/apis/rest-api-manual/measurements/creating-measurements/probe-selection/) · RIPE NCC · Las sondas de una medición de RIPE Atlas se eligen por país, región, ASN o rango de direcciones para ejecutar ping y traceroute - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · Con -4 y -6 se mide la ruta solo por IPv4 o solo por IPv6 - [RFC 8305: Happy Eyeballs Version 2: Better Connectivity Using Concurrency](https://www.rfc-editor.org/rfc/rfc8305) · IETF · Una dirección o una familia de direcciones (IPv4/IPv6) puede estar bloqueada, rota o lenta según la red; se prueba IPv6 primero y se esperan 250 ms (valor recomendado) antes del siguiente intento de conexión - [IPv6 Performance – Revisited](https://blog.apnic.net/2016/08/22/ipv6-performance-revisited/) · APNIC · Comparación del tiempo de ida y vuelta por IPv6 y por IPv4 de los mismos usuarios de doble pila: algunas redes de acceso tratan los paquetes IPv6 de forma muy distinta, y dentro de un mismo ISP aparecen grupos en los que IPv6 es 15, 25 o 75 ms más lento #### isp-peak · Congestión del peering en horas pico · Peak-hour congestion at peering Entre las 9 y las 11 de la noche, más o menos, el tráfico de video se dispara y los enlaces de interconexión entre ISP (peering) tienden a congestionarse. - Por qué → Efecto → En pantalla: Por la noche se concentran el streaming y las descargas → Se forman colas y hay pérdida de paquetes en los enlaces de peering → Solo por la noche, los jugadores de ciertos ISP sufren tirones y teletransporte - Síntomas: Tirones, Teletransporte, Rubber banding / Factores: Jitter, Pérdida de paquetes, Latencia - A quién: Una región o un ISP / Cuándo: Horas pico de la noche - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Externo (Externo) - Tareas (Equipo de infraestructura): Aumentar las conexiones directas con ese ISP, desviar el tráfico de las rutas congestionadas, monitorear por la noche la pérdida y el ping de cada ISP. - Tareas (Externo): Pedir al ISP afectado que amplíe la capacidad del enlace de peering. - En el gráfico: Alto solo a ciertas horas (RTT/pérdida (por ISP)) - Dónde mirar: Graficar el RTT y la pérdida por ISP (ASN) según la hora del día, y obtener mtr de noche y de día desde sondas de RIPE Atlas de ese ISP o desde jugadores para ver en qué salto empieza la pérdida - Se confirma si: Solo un ISP concreto ve subir el RTT y la pérdida cada noche entre las 9 y las 11, y en mtr la pérdida y la latencia continúan desde el enlace entre ISP hasta el destino - Se descarta si: Si suben todos los ISP a la vez, apunta a nuestros enlaces o servidores. Si solo una casa va mal por la noche, a “Canal Wi-Fi saturado” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Inferring Persistent Interdomain Congestion (SIGCOMM 2018)](https://www.caida.org/catalog/papers/2018_inferring_persistent_interdomain_congestion/inferring_persistent_interdomain_congestion.pdf) · ACM · Congestión recurrente en algunos enlaces entre ISP: la latencia sube todos los días en horas pico y la tasa de pérdida también aumenta en esas horas - [Probe Selection (RIPE Atlas REST API)](https://atlas.ripe.net/docs/apis/rest-api-manual/measurements/creating-measurements/probe-selection/) · RIPE NCC · Las sondas de una medición de RIPE Atlas se eligen por país, región, ASN o rango de direcciones para ejecutar ping y traceroute #### isp-cable · Fallos en cables submarinos y enlaces internacionales · Submarine cable fault Cuando se corta un cable submarino, el tráfico da un rodeo por rutas lejanas durante semanas (a veces meses) hasta que se repara, y los enlaces que quedan se saturan. - Por qué → Efecto → En pantalla: Corte del cable o fallo de un dispositivo → El tráfico se concentra en rutas alternativas lejanas y en los enlaces que quedan → Subidas bruscas de ping y pérdida de paquetes para los jugadores que se conectan desde el extranjero, durante días o semanas - Síntomas: Input lag, Teletransporte / Factores: Latencia, Pérdida de paquetes - A quién: Una región o un ISP / Cuándo: Siempre - Responsable principal: Externo (Externo) / También: Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Contratar enlaces por otras rutas, mover el tráfico a esas rutas durante el incidente. - Tareas (Externo): Informar a los jugadores del extranjero de la causa y del plazo estimado de recuperación, pedir al proveedor del enlace el calendario de reparación. - En el gráfico: Salto en escalón (RTT (por país extranjero)) - Dónde mirar: Buscar en el gráfico de RTT y pérdida por país el momento de la subida, cruzarlo con los resúmenes de caídas de internet de Cloudflare Radar y los avisos de los operadores de cables submarinos, y comprobar con traceroute si la ruta da la vuelta por otro continente - Se confirma si: A partir de cierto momento, el RTT de una región concreta del extranjero sube un escalón y se queda así durante días o semanas, con reportes de fallos de cable en las mismas fechas. La ruta cambió a un rodeo lejano distinto del habitual - Se descarta si: Si vuelve a la normalidad en pocos días y no hay reportes de fallos, apunta a “Cambios de ruta BGP y convergencia” o al tramo de un ISP - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [AAE-1 & SMW5 cable cuts impact millions of users across multiple countries](https://blog.cloudflare.com/aae-1-smw5-cable-cuts/) · Cloudflare · Reparar un cable submarino exige enviar un buque de reparación y suele llevar de días a semanas (38 días en el caso de Tonga); los cortes aumentan la latencia y la pérdida en las rutas Europa–Asia - [Q2 2024 Internet disruption summary](https://blog.cloudflare.com/q2-2024-internet-disruption-summary/) · Cloudflare · Los cables del mar Rojo dañados en febrero de 2024 seguían en reparación en julio (zona de conflicto); los cortes de EASSy y Seacom de mayo se repararon en 19 días - [Q1 2024 Internet disruption summary](https://blog.cloudflare.com/q1-2024-internet-disruption-summary/) · Cloudflare · Los cortes de cables en África Occidental (14 de marzo) se repararon entre 3 y 6 semanas después; mientras tanto, el tráfico se pasó a otros cables #### isp-bgp · Cambios de ruta BGP y convergencia · Route change / BGP convergence Cuando cambia la información de rutas de internet, se pierden paquetes durante los segundos o decenas de segundos (rara vez, unos minutos) que tarda en volver a converger. - Por qué → Efecto → En pantalla: Cambia la información de rutas en el tramo de algún ISP → Durante unos segundos o decenas de segundos, los paquetes desaparecen o pasan a una ruta nueva → Congelamiento repentino de unos segundos, y después el ping se queda en otro valor (p. ej., 40 → 70 ms) - Síntomas: Congelamiento, Teletransporte / Factores: Pérdida de paquetes, Latencia - A quién: Una región o un ISP / Cuándo: De vez en cuando, al azar - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo), Externo (Externo) - Tareas (Equipo de desarrollo): Usar timeouts que aguanten cortes breves (no cortar en el acto una conexión que lleva unos segundos sin responder). - Tareas (Equipo de infraestructura): Monitorear las rutas (vigilar los cambios de ruta y de ping de nuestros rangos de IP), detectar con BFD en menos de 1 segundo los fallos de nuestros enlaces y conmutar (el hold time por defecto de BGP es de 90–180 s), mover el tráfico a otro enlace si la ruta cambia a un camino lejano y no vuelve. - Tareas (Externo): Pedir a los ISP cuyos tramos cambian de ruta con frecuencia que investiguen la causa. - En el gráfico: Salto en escalón (RTT, ruta de traceroute) - Dónde mirar: Comparar las rutas de traceroute y mtr de antes y después del momento en que cambió el RTT, y revisar en RIPEstat BGPlay el historial de cambios de ruta BGP de nuestro rango de direcciones (prefijo) - Se confirma si: Una interrupción de unos segundos y después el RTT pasa a otro valor, con actualizaciones BGP y cambios en la ruta de AS (AS path) a la misma hora - Se descarta si: Si no hay cambios de ruta registrados y solo sube por la noche, apunta a “Congestión del peering en horas pico”; si solo van mal algunas conexiones, a “Una ruta ECMP defectuosa” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Casos reales: cloudflare-2020, meta-2021, cloudflare-dns-2025 - Fuentes: - [RFC 4271: A Border Gateway Protocol 4 (BGP-4)](https://www.rfc-editor.org/rfc/rfc4271) · IETF · Valor por defecto recomendado del hold time de BGP: 90 s (si en ese tiempo no llega ningún mensaje del vecino, se corta la sesión) - [BGP updates in 2024](https://blog.apnic.net/2025/01/07/bgp-updates-in-2024/) · APNIC · Tiempo medio diario que tarda una ruta inestable en volver a estabilizarse: 25–35 s (IPv4), 40–50 s (IPv6) - [Delayed Internet Routing Convergence (SIGCOMM 2000)](https://conferences.sigcomm.org/sigcomm/2000/conf/paper/sigcomm2000-5-2.pdf) · ACM · Tras un fallo de ruta, la convergencia puede tardar hasta varios minutos, y mientras tanto aumentan la pérdida y la latencia (medición del año 2000) - [BGPlay (RIPEstat Data API)](https://stat.ripe.net/docs/data-api/api-endpoints/bgplay) · RIPE NCC · Muestra las rutas BGP de un rango de direcciones (prefijo) al inicio del periodo, las actualizaciones BGP observadas durante ese periodo y los AS de la ruta #### isp-ecmp · Una ruta ECMP defectuosa · ECMP / link bundle member fault Los ISP y los centros de datos tienen varias rutas hacia el mismo destino y asignan una a cada conexión. Si se estropea una sola ruta, solo los jugadores asignados a ella siguen con lag. - Por qué → Efecto → En pantalla: En un tramo que agrupa varios enlaces, un enlace o un dispositivo está defectuoso o saturado → La ruta se elige según la combinación de direcciones y puertos (hash), así que solo las conexiones asignadas a esa ruta sufren pérdida y latencia → En la misma región y con el mismo ISP, solo algunos jugadores sufren teletransporte constante. A veces se arregla al reconectar - Síntomas: Teletransporte, Rubber banding, Tirones / Factores: Pérdida de paquetes, Jitter - A quién: Solo yo, Una región o un ISP / Cuándo: Siempre - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo), Externo (Externo) - Tareas (Equipo de desarrollo): Registrar estadísticas de pérdida y retransmisión por conexión para poder sacar la IP, el puerto y la hora de los afectados (en TCP, el número de retransmisiones de TCP_INFO; en UDP, calcularla con los números de secuencia que faltan). - Tareas (Equipo de infraestructura): Reunir la IP, el puerto y la hora de los afectados y pasarlos al ISP o al centro de datos, monitorear la pérdida por ruta, medir las rutas con el mismo protocolo y puerto que el juego (mtr --tcp o --udp con --port), sacar del grupo el enlace o el dispositivo defectuoso si la ruta pasa por nuestros dispositivos. - Tareas (Externo): Pedir al ISP que revise y reemplace la ruta defectuosa, indicar a los jugadores que de momento pueden esquivarlo reconectándose (cuando al reconectar cambia el puerto). - Cifras de referencia: Con 4 rutas, solo lo sufre más o menos una cuarta parte de los jugadores. La medición de ping puede ir por una ruta distinta a la del juego y salir perfecta. - En el gráfico: Alto solo en algunos (Pérdida/retransmisiones por conexión (por IP/puerto)) - Dónde mirar: Desglosar la pérdida y las retransmisiones por conexión según IP y puerto de origen. Lanzar mtr en UDP (-u) al puerto del juego (-P) con un puerto de origen fijo (-L), y repetir varias veces cambiando el puerto de origen. Con -P y sin -L, el puerto de origen cambia en cada sonda y se mezclan varias rutas - Se confirma si: En la misma región y con el mismo ISP, solo ciertas combinaciones de puerto (o dirección) de origen pierden paquetes de forma constante, y todo va bien cuando el puerto cambia al reconectar - Se descarta si: Si va mal con cualquier puerto, apunta a congestión o a un fallo en todo un tramo - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Para que los paquetes de una conexión no lleguen desordenados, los dispositivos (ECMP, LAG) fijan una ruta por conexión según un valor calculado a partir de las direcciones y los puertos (o solo de las direcciones, según la configuración del dispositivo). Donde solo se usan las direcciones, reconectar lleva a la misma ruta y no mejora nada. Por eso, si llegan juntos reportes como “el ping está bien, pero el juego va con lag” y “se arregló al reconectar”, hay que sospechar de esta causa. - Fuentes: - [RFC 7424: Mechanisms for Optimizing Link Aggregation Group (LAG) and Equal-Cost Multipath (ECMP) Component Link Utilization in Networks](https://www.rfc-editor.org/rfc/rfc7424) · IETF · LAG y ECMP eligen un enlace por flujo con un hash de campos de la cabecera para mantener el orden de los paquetes (asignación de flujos a enlaces de muchos a uno) - [RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection](https://www.rfc-editor.org/rfc/rfc2991) · IETF · El criterio para distinguir flujos varía según la implementación (solo la dirección de destino, el par de direcciones o también los puertos); con varias rutas, los resultados de ping y traceroute son poco confiables - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · Opciones -u (UDP), -P (puerto de destino) y -L (puerto de origen UDP); con solo -P, el número de secuencia de la sonda va en el puerto de origen, así que cambia en cada sonda #### isp-shaping · Limitación de velocidad y gestión del tráfico del ISP · Traffic shaping, data caps En los planes que limitan la velocidad al superar el consumo de datos o que gestionan cierto tipo de tráfico, los paquetes se retrasan o se descartan. - Por qué → Efecto → En pantalla: Velocidad limitada al agotar los datos del plan, o restricción de cierto tráfico → Los paquetes esperan en una cola o se descartan → Lag a partir de cierto consumo, sobre todo con datos móviles - Síntomas: Input lag, Teletransporte / Factores: Latencia, Pérdida de paquetes - A quién: Solo yo, Una región o un ISP / Cuándo: Siempre, Horas pico de la noche - Responsable principal: Externo (Externo) / También: Desarrollo de servidor (Equipo de desarrollo), Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Reducir el tráfico del juego (compresión, enviar solo lo necesario). - Tareas (Equipo de infraestructura): Si el tráfico del juego se retrasa o se descarta solo en un ISP concreto, reunir datos y escalarlo a ese ISP. - Tareas (Externo): Indicar a los jugadores que revisen si agotaron los datos del plan o tienen la velocidad limitada y si otras apps del mismo teléfono están usando datos, preguntar al ISP si limita el tráfico de juegos. - Cifras de referencia: En Corea, los planes móviles suelen limitar la velocidad a 1–5 Mbps al agotar los datos, y los planes baratos a cientos de kbps. Aunque el juego consuma poco, si otras apps del mismo teléfono usan datos, se forma una cola delante del dispositivo que limita la velocidad. - En el gráfico: Topa con el límite (Throughput, RTT) - Dónde mirar: Pedir al jugador que mire en la app de su operador cuántos datos le quedan y si tiene la velocidad limitada, y que haga un test de velocidad para ver la velocidad máxima. En el lado del servidor, comparar la pérdida y el RTT por ISP - Se confirma si: El throughput no pasa de un valor fijo, como 1–5 Mbps o unos cientos de kbps, y a partir de ahí el RTT y la pérdida suben cuando otras apps del mismo teléfono usan datos. Desaparece al recargar datos o pasar al Wi-Fi - Se descarta si: Si no hay limitación de velocidad y solo va mal un ISP, apunta a “Congestión del peering en horas pico” o “Enrutamiento con rodeos” - Se verifica con: En el entorno del jugador - Fuentes: - [SKT, 고객 선택권과 혜택 강화한 신규 5G 요금제 출시](https://news.sktelecom.com/180213) · SK텔레콤 · Ejemplos de control de velocidad al agotar los datos incluidos en un plan 5G: máximo de 400 kbps, 1 Mbps o 3 Mbps - [SKT, 요금제 개편](https://news.sktelecom.com/225487) · SK텔레콤 · Se puede seguir usando la conexión a un máximo de 400 kbps después de agotar los datos incluidos (programa coreano de datos garantizados para toda la población) #### isp-udp-block · Restricciones de UDP e inspección de paquetes por país o ISP · UDP blocking, throttling and inspection by networks Algunas redes bloquean ciertas direcciones y puertos UDP o limitan la velocidad del UDP, y sus dispositivos de inspección de paquetes filtran los protocolos que no reconocen. En esas redes, los juegos que se comunican por UDP no conectan o se desconectan a menudo. - Por qué → Efecto → En pantalla: Conexión desde la red de un ISP que limita la velocidad del UDP, o desde una red con dispositivos de inspección (censura) del tráfico a nivel de país o de ISP → Se bloquean ciertas direcciones y puertos UDP, se limita la velocidad del UDP en las horas de más tráfico, se filtran los puertos y protocolos que no están en la lista de permitidos, o se dejan pasar solo los primeros paquetes y luego se bloquea → Solo para los jugadores de ciertos países o ISP: el juego no conecta o se queda en carga infinita, se desconecta poco después de entrar, o hay teletransporte por pérdida de paquetes en las horas de más tráfico - Síntomas: No conecta / carga infinita, Desconexión, Teletransporte / Factores: Pérdida de paquetes - A quién: Una región o un ISP / Cuándo: Al conectar o tras un mantenimiento, Siempre, Horas pico de la noche - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo), Desarrollo de servidor (Equipo de desarrollo), Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Cliente: pasar automáticamente a una ruta alternativa por TCP/TLS 443 si el UDP no conecta en unos segundos, detectar también las conexiones que entran y se cortan enseguida y reintentarlas por la ruta alternativa, registrar en el log por qué ruta se conectó. Servidor: aceptar el mismo protocolo del juego también por TCP 443 (TLS), ajustar los timeouts porque la ruta alternativa puede añadir latencia. - Tareas (Equipo de infraestructura): Antes de abrir un país nuevo, medir en las redes de los ISP locales si llega el UDP y cuánta pérdida hay en horas pico, poner cerca de esa región servidores relay o gateways que acepten la ruta alternativa por TCP 443, vigilar la tasa de conexiones UDP y TCP exitosas por país y ASN, reunir datos y escalar a los ISP en los que se confirme la limitación del UDP. - Tareas (Externo): Preguntar al ISP o al organismo correspondiente por sus criterios de restricción del UDP y si puede relajarlos, indicar a los jugadores que prueben a conectarse desde otra red para comparar. - Cifras de referencia: Según mediciones citadas en un documento del IETF, el 3–5% de las redes bloquea el UDP por completo. Cuando Google revisó en 2016 el uso de QUIC (basado en UDP), el 4.4% de los clientes no podía usar UDP/QUIC porque estaba bloqueado o porque la MTU de la ruta era pequeña, casi siempre detrás de firewalls corporativos, y no vio ningún caso de un ISP entero que lo bloqueara. Otro 0.3% estaba en redes donde la pérdida subía mucho en horas pico, al parecer porque limitaban la velocidad del UDP; pidiendo cambios a los ISP, esa cifra bajó desde el 1% de 2015. - En el gráfico: Alto solo en algunos (Tasa de éxito de conexión UDP (por país/ASN)) - Dónde mirar: Separar por país y ASN la tasa de éxito de conexión UDP y la de la ruta alternativa por TCP 443. Desde una VM en la nube dentro de la red de ese ISP o desde la computadora de un jugador conectado a él, probar la conexión al puerto UDP del juego y a TCP 443 por separado, y comparar mtr -u -P (puerto del juego) con mtr -T -P 443 para ver a partir de qué salto desaparecen las respuestas - Se confirma si: Solo en un país o ASN concreto, el UDP no recibe la primera respuesta o se corta a los pocos segundos, mientras que TCP 443 funciona desde el mismo lugar. Si es limitación de velocidad, la pérdida del UDP sube claramente solo en horas pico y el TCP se ve menos afectado - Se descarta si: Si el TCP también falla, apunta a una caída de la ruta, un bloqueo de IP o “Fallos y lentitud del DNS”. Si pasa igual en todos los países, a la configuración de nuestros servidores o firewalls. Si la pérdida aparece solo con ráfagas de tráfico, tanto en UDP como en TCP, a “Descarte del exceso por un policer” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Según un documento de estudio del IRTF, los dispositivos de inspección de paquetes pueden seleccionar flujos UDP por dirección, puerto y protocolo para bloquearlos, o bloquear todo salvo los protocolos permitidos (lista de permitidos). Si el dispositivo decide mirando solo algunos campos del paquete, basta un pequeño cambio en el protocolo para que lo bloquee. En los inicios de QUIC, tras cambiar un bit de la cabecera, un firewall dejaba pasar los primeros paquetes y bloqueaba los siguientes, así que la lógica del cliente para cambiar a TCP no llegaba a activarse. Al abrir un país nuevo, puede aparecer en reportes como “en Corea va bien, pero en ese país no se puede conectar desde algunos ISP”. Si solo se bloquea en la red de un lugar, como una cafetería o una oficina, consulta la entrada “Restricciones en Wi-Fi público y redes corporativas”. - Fuentes: - [RFC 9308: Applicability of the QUIC Transport Protocol](https://www.rfc-editor.org/rfc/rfc9308) · IETF · Según los estudios de medición, el 3–5% de las redes bloquea el UDP por completo, así que las apps basadas en UDP deben aceptar fallos de conexión o tener una ruta alternativa por TCP (TLS); los firewalls pueden bloquear los puertos que no corresponden a un servicio registrado - [The QUIC Transport Protocol: Design and Internet-Scale Deployment (SIGCOMM 2017)](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46403.pdf) · ACM · 2016: el 4.4% de los clientes no podía usar QUIC sobre UDP (UDP/QUIC bloqueado o MTU de ruta pequeña, casi siempre detrás de firewalls corporativos; no se observó ningún bloqueo de un ISP entero); el 0.3% estaba en redes que parecían limitar la velocidad del UDP (más pérdida en horas pico; bajó desde el 1% de 2015 tras pedírselo a los ISP); caso de un firewall que, tras el cambio de 1 bit de la cabecera, dejaba pasar solo los primeros paquetes y bloqueaba el resto, lo que anulaba la lógica de cambio a TCP - [RFC 9505: A Survey of Worldwide Censorship Techniques](https://www.rfc-editor.org/rfc/rfc9505) · IRTF · Los dispositivos de inspección de la red pueden seleccionar flujos TCP y UDP por dirección, puerto y protocolo para bloquearlos (con QUIC se observó el bloqueo de endpoints UDP); permitir solo ciertos protocolos lleva a bloquear de más, y también se usa la limitación de velocidad de cierto tráfico - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · Envía UDP con -u o TCP SYN con -T y fija el puerto de destino con -P, para medir la ruta con el mismo protocolo y puerto que el juego #### isp-line · Mala calidad de la conexión · Faulty last-mile line / modem Un conector flojo, un cableado viejo o un módem averiado provocan pérdida de paquetes constante y cortes periódicos de la conexión. - Por qué → Efecto → En pantalla: Cable dañado, mal contacto, módem o terminal óptico (ONT) averiado → Se descartan paquetes por errores de bits, y a veces la conexión se corta entre unos segundos y un minuto mientras vuelve a conectarse → Pérdida leve pero constante; a veces, congelamientos de unos segundos o desconexiones - Síntomas: Teletransporte, Congelamiento, Desconexión / Factores: Pérdida de paquetes - A quién: Misma casa / Cuándo: De vez en cuando, al azar - Responsable principal: Externo (Externo) - Tareas (Externo): Indicar a los jugadores que comprueben si también se cortan otros juegos y las videollamadas y, si es así, que pidan al ISP una revisión de la línea. - En el gráfico: Picos aleatorios (Tasa de pérdida, historial de reconexiones de la línea) - Dónde mirar: Medir durante unos minutos con pathping (o mtr) la pérdida hasta el primer salto del ISP, y mirar las horas de reconexión en el historial de conexión a internet (WAN) de la página de administración del router - Se confirma si: Pérdida constante desde el primer salto del ISP incluso con la línea libre, y las horas de reconexión del historial del router coinciden con los congelamientos y las desconexiones. Otros juegos y las videollamadas se cortan a la vez - Se descarta si: Si la pérdida empieza en el tramo inalámbrico hasta el router, apunta a “Interferencias y señal débil en el Wi-Fi”; si empieza en un tramo lejano del ISP, a la ruta del ISP - Se verifica con: En el entorno del jugador - Fuentes: - [RFC 3635: Definitions of Managed Objects for the Ethernet-like Interface Types](https://www.rfc-editor.org/rfc/rfc3635) · IETF · Las tramas que no pasan la comprobación de trama (FCS) se cuentan como errores de FCS (dot3StatsFCSErrors) y se suman a los errores de entrada (ifInErrors) - [Understanding and Mitigating Packet Corruption in Data Center Networks (SIGCOMM 2017)](https://www.microsoft.com/en-us/research/wp-content/uploads/2017/06/CorrOpt_SIGCOMM2017.pdf) · ACM · Las causas principales de los paquetes corruptos son transceptores ópticos defectuosos, fibra dañada, conectores sucios y una mala instalación; la pérdida por corrupción es constante y no depende del uso - [pathping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/pathping) · Microsoft · Envía pings a cada salto durante un tiempo y calcula la tasa de pérdida por router y enlace para mostrar en qué tramo se produce la pérdida #### isp-dns · Fallos y lentitud del DNS · DNS failure / slowness Si el DNS, que traduce los nombres de servidor a direcciones, va lento o falla, el juego no encuentra los servidores de login ni de parches. - Por qué → Efecto → En pantalla: Caída o error de configuración del DNS del ISP → No se encuentran las direcciones de los servidores de login y de parches → Larga espera tras presionar el botón de conectar, o no conecta. Los que ya están conectados no notan nada - Síntomas: No conecta / carga infinita / Factores: Latencia, Pérdida de paquetes - A quién: Una región o un ISP, Solo yo / Cuándo: Al conectar o tras un mantenimiento - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Guardar las direcciones en caché (recordar la última dirección de servidor con la que se conectó bien), preparar varios DNS (si uno falla, volver a consultar en otro). - Tareas (Externo): Indicar a los jugadores que prueben a cambiar a otro DNS, como un DNS público. - En el gráfico: Alto solo en algunos (Inicios de sesión fallidos (por ISP), tiempo de consulta DNS) - Dónde mirar: Preguntar por el nombre del servidor de login al DNS del ISP y a un DNS público por separado con Resolve-DnsName -Server (o nslookup), y comparar tiempos de respuesta y resultados - Se confirma si: Solo el DNS del ISP no responde o tarda mucho, y al cambiar a un DNS público conecta enseguida. Los jugadores ya conectados no notan nada - Se descarta si: Si cualquier DNS devuelve la dirección al instante y aun así no conecta, apunta a la ruta, un firewall o el servidor - Se verifica con: En el entorno del jugador - Casos reales: meta-2021, cloudflare-dns-2025, aws-2025 - Fuentes: - [Cloudflare 1.1.1.1 Incident on July 14, 2025](https://blog.cloudflare.com/cloudflare-1-1-1-1-incident-on-july-14-2025/) · Cloudflare · Cuando un resolver DNS público se detuvo durante 62 minutos, los usuarios que ya no podían resolver nombres perdieron en la práctica el acceso a todos los servicios de internet - [RFC 8767: Serving Stale Data to Improve DNS Resiliency](https://www.rfc-editor.org/rfc/rfc8767) · IETF · Aguantar el incidente siguiendo con los registros de caché vencidos cuando no se llega a los servidores autoritativos (serve-stale) - [Resolve-DnsName](https://learn.microsoft.com/en-us/powershell/module/dnsclient/resolve-dnsname) · Microsoft · Consulta un nombre en el servidor DNS indicado con -Server - [nslookup](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/nslookup) · Microsoft · Comando que consulta un nombre directamente a un servidor DNS #### isp-ddos-path · Enlaces compartidos saturados por un DDoS · DDoS saturating shared links Un ataque masivo dirigido a la empresa del juego, o a otro destino de la misma red, llena los enlaces compartidos. - Por qué → Efecto → En pantalla: Se genera un gran volumen de tráfico de ataque → El tráfico legítimo que usa los mismos enlaces también se retrasa y se descarta → Teletransporte, desconexiones o el juego no conecta, para muchos jugadores a la vez - Síntomas: Teletransporte, Desconexión, No conecta / carga infinita / Factores: Pérdida de paquetes, Latencia - A quién: Todo el servidor, Una región o un ISP / Cuándo: De vez en cuando, al azar, Cuando se junta mucha gente - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Externo (Externo) - Tareas (Equipo de infraestructura): Usar un servicio de protección DDoS, desviar el tráfico durante los ataques, ocultar las direcciones de los servidores (ponerlos detrás de los dispositivos de protección y no exponer su dirección real). - Tareas (Externo): Si el ataque va contra otro destino de la misma red, pedir al ISP que lo bloquee en un tramo superior (upstream). - En el gráfico: Topa con el límite (Tráfico entrante del enlace (bps/pps), descartes en la interfaz) - Dónde mirar: Tráfico entrante y paquetes descartados en las interfaces de nuestros enlaces y dispositivos, y el registro de ataques detectados del servicio de protección DDoS, junto a las horas en que se acumulan las desconexiones - Se confirma si: El tráfico entrante se pega a la capacidad del enlace y queda plano, los descartes aumentan y, a la misma hora, jugadores de muchas regiones y de distintos ISP sufren teletransporte o desconexiones a la vez - Se descarta si: Si los enlaces tienen margen y solo van mal algunos ISP, apunta a congestión o problemas de ruta en el tramo del ISP - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Infrastructure layer attacks](https://docs.aws.amazon.com/whitepapers/latest/aws-best-practices-ddos-resiliency/infrastructure-layer-attacks.html) · AWS · Los ataques volumétricos, como la reflexión UDP o el SYN flood, superan la capacidad de la red o acaparan los recursos de firewalls y balanceadores de carga - [Obfuscating AWS resources (BP1, BP4, BP5)](https://docs.aws.amazon.com/whitepapers/latest/aws-best-practices-ddos-resiliency/obfuscating-aws-resources-bp1-bp4-bp5.html) · AWS · Poner servicios de edge como CloudFront o un balanceador de carga delante de los servidores de origen para reducir su exposición directa - [RFC 7999: BLACKHOLE Community](https://www.rfc-editor.org/rfc/rfc7999) · IETF · La comunidad BLACKHOLE, que se anuncia por BGP para pedir a las redes vecinas que descarten el tráfico hacia una dirección concreta #### isp-cgnat · IP compartida del ISP (CGNAT) · Carrier-grade NAT En las redes móviles y en algunos ISP, varios abonados comparten una misma IP, y el mapeo de las conexiones inactivas se borra al poco tiempo. - Por qué → Efecto → En pantalla: Un dispositivo del ISP (CGNAT) gestiona la tabla de sesiones de muchísimos abonados → Límite de la tabla de sesiones, timeout por inactividad corto → Desconexión tras un rato inactivo, falsos positivos que bloquean a la vez a todos los que comparten la misma IP - Síntomas: Desconexión, No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Una región o un ISP / Cuándo: Tras un rato inactivo - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo), Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Cliente: enviar heartbeats a intervalos de como mucho la mitad del timeout por inactividad más corto (en redes móviles a veces ronda los 30 s), enviarlos desde el cliente (el mapeo CGNAT del ISP solo se renueva con seguridad con los paquetes que salen desde dentro), reconectar automáticamente si se corta. Servidor: responder a los heartbeats y cerrar primero la conexión si no llegan durante cierto tiempo, reconocer al mismo jugador con un token de sesión aunque el mapeo cambie y llegue desde otra dirección y otro puerto, ser prudente con los bloqueos por IP porque muchas personas pueden compartir una IP (decidir junto con criterios de cuenta y dispositivo). - Tareas (Equipo de infraestructura): Ajustar a las IP compartidas de los ISP los límites de conexiones por IP y de conexiones nuevas por segundo de los firewalls y los dispositivos de protección DDoS (subir el umbral para los rangos de los operadores móviles o dejarlos como excepción). - Cifras de referencia: En redes móviles, el timeout por inactividad de UDP a veces ronda los 30 segundos. - En el gráfico: Desconexión masiva (Desconexiones (timeout de heartbeat), tiempo inactivo antes de la desconexión (por ISP)) - Dónde mirar: En los logs de conexión, ver cuántas cuentas se conectan a la vez desde una IP y de qué ISP (ASN) son, y reunir por ISP el tiempo inactivo de las conexiones que se cortaron tras estar inactivas. En el lado del jugador, mirar la dirección de internet (WAN) en la página de administración del router - Se confirma si: En los rangos de los operadores móviles, varias cuentas se conectan desde una misma IP y el tiempo inactivo antes de la desconexión se concentra en valores cortos, de unos 30–60 s. La dirección WAN del router está en 100.64.0.0/10 (espacio de direcciones compartido para el NAT del operador) o no coincide con la que ve el servidor - Se descarta si: Si se concentra en jugadores con router doméstico, sin importar el ISP, apunta a “Expiración del mapeo NAT” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [A Multi-perspective Analysis of Carrier-Grade NAT Deployment (IMC 2016)](https://www.icir.org/vern/papers/cgn-imc16.pdf) · ACM · Duración medida del mapeo UDP en NAT: 10–200 s, el 74% de 1 minuto o menos; mediana de CGN: 65 s en redes móviles y 35 s en redes fijas - [RFC 6888: Common Requirements for Carrier-Grade NATs (CGNs)](https://www.rfc-editor.org/rfc/rfc6888) · IETF · El CGN debe permitir limitar el número de puertos externos por abonado y la velocidad de creación de mapeos nuevos - [RFC 6269: Issues with IP Address Sharing](https://www.rfc-editor.org/rfc/rfc6269) · IETF · Cuando varios comparten una dirección, el bloqueo por IP (penalty box) también bloquea a los demás abonados de esa dirección - [RFC 6598: IANA-Reserved IPv4 Prefix for Shared Address Space](https://www.rfc-editor.org/rfc/rfc6598) · IETF · 100.64.0.0/10 es el rango de direcciones compartido que se usa entre el dispositivo NAT del operador (CGN) y el router de cada abonado #### isp-vpn · Paso por una VPN o un acelerador de juegos · VPN / game accelerator detour Con una VPN o un acelerador de juegos activado, los paquetes pasan por los servidores intermedios (relay) de esa empresa. Si el relay está lejos o saturado, la conexión acaba siendo más lenta que sin él. - Por qué → Efecto → En pantalla: La VPN o el acelerador desvía todos los paquetes del juego por sus servidores intermedios → Se suman la distancia hasta el servidor intermedio y su congestión, y las cabeceras del túnel también reducen la MTU (el tamaño máximo de paquete que se puede enviar de una vez) → Ping más alto y pérdida de paquetes; no conecta si bloquean la dirección del relay junto con todos los que la usan - Síntomas: Input lag, Teletransporte, No conecta / carga infinita / Factores: Latencia, Pérdida de paquetes - A quién: Solo yo / Cuándo: Siempre, Al conectar o tras un mantenimiento - Responsable principal: Externo (Externo) / También: Infraestructura de red (Equipo de infraestructura), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Mantener los paquetes UDP en 1,200 bytes o menos (para que no se fragmenten aunque las cabeceras del túnel reduzcan la MTU), tener en cuenta en los bloqueos por IP las direcciones relay compartidas de VPN y aceleradores y decidir junto con criterios de cuenta y dispositivo. - Tareas (Equipo de infraestructura): Si hay muchos jugadores en el extranjero, poner puntos de presencia propios cerca de ellos, revisar la ruta de los ISP que acumulan reportes de “al activar el acelerador mejoró”. - Tareas (Externo): Indicar a los jugadores que desactiven la VPN o el acelerador y comparen. - Cifras de referencia: Con un servidor intermedio cercano se suman unos pocos ms; si da un rodeo por otro país, de decenas de ms a más de 100 ms. - En el gráfico: Alto solo en algunos (RTT (por jugador), operador de la IP de conexión) - Dónde mirar: Comprobar si el ASN de la IP de conexión es de un proveedor de VPN, aceleradores o hosting, y pedir al jugador que desactive la VPN o el acelerador y compare ping y traceroute - Se confirma si: Solo con la VPN o el acelerador activado suben el RTT y la pérdida o se bloquea la conexión, y en traceroute aparecen saltos por el servidor intermedio - Se descarta si: Si da igual activarlo o no, apunta a la conexión o al tramo del ISP. Si con él activado va mejor, a un problema en la ruta original del ISP (“Enrutamiento con rodeos”, “Congestión del peering en horas pico”) - Se verifica con: En el entorno del jugador - Para saber más: Al revés, cuando la ruta del ISP es mala, el acelerador puede ir por una ruta mejor y bajar el ping. Los reportes de “al activar el acelerador mejoró” son una pista de un problema en la ruta del ISP, como un enrutamiento con rodeos o la congestión de la noche. - Fuentes: - [RFC 4459: MTU and Fragmentation Issues with In-the-Network Tunneling](https://www.rfc-editor.org/rfc/rfc4459) · IETF · Problemas de fragmentación y de MTU de la ruta que aparecen cuando las cabeceras de encapsulación de los túneles dentro de la red reducen el tamaño que se puede enviar - [RFC 8899: Packetization Layer Path MTU Discovery for Datagram Transports](https://www.rfc-editor.org/rfc/rfc8899) · IETF · Se recomiendan 1,200 bytes como tamaño seguro básico (BASE_PLPMTU) para transportes de datagramas como UDP - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Latencia de ida y vuelta que se suma al pasar por un punto de presencia en otro país: Seúl–Tokio 30 ms, Seúl–Hong Kong 39 ms, Seúl–Singapur 68 ms ### L5 Equipos de red del centro de datos (causas: 11) #### dc-firewall · Tabla de sesiones del firewall llena · Firewall session table exhaustion El firewall registra en la tabla de sesiones cada conexión que deja pasar para hacerle seguimiento. Cuando la tabla se llena, ya no puede aceptar conexiones nuevas. - Por qué → Efecto → En pantalla: Una avalancha de conexiones o un ataque lleva el número de sesiones al límite → No queda ninguna entrada libre para registrar una conexión nueva, así que se rechaza → Para quien intenta entrar, el juego no conecta o se queda en carga infinita; algunas conexiones ya abiertas también se desconectan - Síntomas: No conecta / carga infinita, Desconexión / Factores: Pérdida de paquetes - A quién: Todo el servidor / Cuándo: Al conectar o tras un mantenimiento, Cuando se junta mucha gente - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: regular con una cola de inicio de sesión las conexiones que llegan de golpe, reutilizar conexiones para no abrir conexiones cortas una y otra vez, cerrar primero las conexiones cuyo heartbeat se cortó (para que las conexiones muertas no ocupen la tabla de sesiones mucho tiempo). Cliente: enviar heartbeats a intervalos de como mucho la mitad del timeout por inactividad más corto, reconectar automáticamente si se corta, pero con intervalos de reintento crecientes y aleatorios (para que no vuelvan todos a la vez). - Tareas (Equipo de infraestructura): Ampliar la tabla de sesiones, limpiar rápido las conexiones que terminan pronto (acortar el timeout de las sesiones cerradas), avisar al equipo de desarrollo del nuevo valor cuando se acorte el timeout de sesiones inactivas para que ajuste el intervalo de heartbeat, bloquear los ataques, poner alertas sobre el uso de la tabla de sesiones. - En el gráfico: Topa con el límite (Sesiones del firewall, conexiones nuevas fallidas) - Dónde mirar: Graficar las sesiones simultáneas del firewall junto con su límite y buscar en el log del dispositivo los paquetes descartados por no poder crear la sesión. En un firewall Linux, comparar nf_conntrack_count con nf_conntrack_max y buscar en dmesg “nf_conntrack: table full, dropping packet”; en una instancia de AWS, mirar conntrack_allowance_exceeded en ethtool -S - Se confirma si: Desde el momento en que el número de sesiones queda plano en el límite, aumentan las conexiones nuevas fallidas, junto con los registros de fallos al crear sesiones o los contadores de descartes - Se descarta si: Si el número de sesiones está muy por debajo del límite y aun así no conecta, apunta a “Desbordamiento de la cola de conexiones pendientes (backlog)” o al servidor de login. Si solo se cortan las conexiones inactivas, a “Expiración del seguimiento de conexiones en grupos de seguridad de la nube” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · Número máximo de entradas de la tabla de seguimiento de conexiones (nf_conntrack_max), tiempo que se conservan las conexiones que se están cerrando (TIME_WAIT y FIN_WAIT: 120 s por defecto), TCP establecido: 5 días por defecto, número actual de entradas (nf_conntrack_count) - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Si una instancia supera el número de conexiones que puede seguir, se descartan los paquetes de las conexiones nuevas; las conexiones inactivas pueden agotar la tabla de seguimiento - [Infrastructure layer attacks](https://docs.aws.amazon.com/whitepapers/latest/aws-best-practices-ddos-resiliency/infrastructure-layer-attacks.html) · AWS · Los ataques como el SYN flood acaparan los recursos de servidores, firewalls y balanceadores de carga - [net/netfilter/nf_conntrack_core.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_conntrack_core.c?h=v6.12) · Linux kernel · Cuando la tabla de seguimiento de conexiones se llena, se registra “nf_conntrack: table full, dropping packet” y se descartan los paquetes de las conexiones nuevas - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · conntrack_allowance_exceeded: número de paquetes descartados por superar el límite de seguimiento de conexiones de la instancia; se ve con ethtool -S #### dc-ddos · Desvío por la protección DDoS y falsos positivos · DDoS scrubbing latency, false positives Para frenar un ataque, el tráfico se desvía a un centro de depuración (scrubbing), lo que alarga la ruta, y a veces se bloquea a jugadores legítimos tomándolos por atacantes. - Por qué → Efecto → En pantalla: Tras detectar un ataque (o de forma permanente), el tráfico entrante se desvía a un centro de depuración → La ruta se alarga y algunos paquetes legítimos se clasifican como ataque → El ping sube para todos; en ciertas regiones o ISP el juego no conecta - Síntomas: Input lag, No conecta / carga infinita, Teletransporte / Factores: Latencia, Pérdida de paquetes - A quién: Todo el servidor, Una región o un ISP / Cuándo: Cuando se junta mucha gente, De vez en cuando, al azar - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Documentar el patrón de tráfico del juego (puertos, tamaño de los paquetes, paquetes por segundo) y compartirlo con el equipo de infraestructura, mantener los paquetes UDP en 1,200 bytes o menos. - Tareas (Equipo de infraestructura): Ajustar las reglas de protección al patrón de tráfico del juego, usar puntos de depuración regionales, reducir el tamaño de los paquetes TCP en los tramos con túnel (ajuste del MSS), detectar falsos positivos con la tasa de fallos de conexión por región y por ISP. - Cifras de referencia: Si el punto de depuración está en el mismo país, se suman unos pocos ms; si se pasa por un punto de otro país, se suman 30–100 ms o más. Normalmente solo el tráfico entrante da el rodeo y las respuestas del servidor salen directamente. Si el tráfico filtrado vuelve por un túnel, también se reduce el tamaño máximo que se puede enviar de una vez (MTU), lo que puede acabar en el problema de que solo desaparecen los paquetes grandes. - En el gráfico: Salto en escalón (RTT (ping), tasa de fallos de conexión por región/ISP) - Dónde mirar: Poner en el mismo eje de tiempo los registros de inicio y fin del desvío (scrubbing) y los logs de bloqueo del dispositivo o servicio de protección, el gráfico de RTT y la tasa de fallos de conexión por región y por ISP. Desde la región afectada, comprobar con mtr o traceroute si aparece un punto de depuración en la ruta - Se confirma si: El RTT sube un escalón cuando se activa el desvío, se mantiene y vuelve a bajar cuando se desactiva. O aparecen direcciones de jugadores legítimos en el log de bloqueo y solo en esa región o ISP sube la tasa de fallos de conexión - Se descarta si: Si el RTT sube en momentos sin registros de desvío ni de bloqueo, apunta a “Enrutamiento con rodeos” o “Cambios de ruta BGP y convergencia”. Si solo desaparecen los paquetes grandes, a “Desajuste de MTU (solo desaparecen los paquetes grandes)” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Maximum transmission unit and maximum segment size](https://developers.cloudflare.com/magic-transit/reference/mtu-mss/) · Cloudflare · Tras el filtrado, el tráfico entrante se entrega por un túnel GRE (MTU 1,476) y las respuestas salientes van directas a internet (DSR); se recomienda limitar el MSS de TCP a 1,436 o menos, y si no se ajusta, los paquetes grandes se descartan o se fragmentan - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Latencia de ida y vuelta según la ubicación del punto de presencia: Seúl–zona de Busan 8 ms, Seúl–Tokio 30 ms, Seúl–Singapur 68 ms #### dc-lb-idle · Timeout por inactividad del balanceador de carga · Load balancer idle timeout El balanceador de carga borra las conexiones inactivas después de cierto tiempo. El juego cree que la conexión sigue abierta, hasta que el jugador sufre una desconexión. - Por qué → Efecto → En pantalla: El jugador no envía ningún paquete durante un rato (ventana de chat abierta, ausente del teclado) → El balanceador de carga elimina la conexión inactiva (valores por defecto habituales: 60–350 s) → Desconexión en el momento en que vuelve a moverse - Síntomas: Desconexión / Factores: Pérdida de paquetes - A quién: Solo yo, Todo el servidor / Cuándo: Tras un rato inactivo - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de cliente (Equipo de desarrollo), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: enviar heartbeats a intervalos de como mucho la mitad del timeout por inactividad más corto (30 s o menos detrás de un ALB de 60 s), reconectar automáticamente si se corta. Servidor: responder a los heartbeats y cerrar primero la conexión si no llegan durante cierto tiempo, retomar la sesión con un token de sesión. - Tareas (Equipo de infraestructura): Revisar el timeout por inactividad de cada balanceador de carga de la ruta, compartir los valores con el equipo de desarrollo y ampliarlos si hace falta. - Cifras de referencia: Los valores por defecto son 60 segundos en AWS ALB, 350 segundos para TCP y 120 segundos para UDP en NLB, y 4 minutos para TCP en Azure Load Balancer. Los valores de TCP de ALB y NLB se pueden cambiar, pero los 120 segundos de UDP en NLB no. Al vencer el tiempo, ALB también cierra la conexión del lado del servidor, mientras que NLB la borra en silencio, así que es fácil que el servidor no se entere. - En el gráfico: Desconexión masiva (Desconexiones, tiempo inactivo antes de la desconexión) - Dónde mirar: Revisar el timeout por inactividad configurado en cada balanceador de carga de la ruta y reunir, para cada conexión cortada, el tiempo entre su último paquete y la desconexión. En AWS NLB, mirar también TCP_ELB_Reset_Count en CloudWatch (número de RST enviados por el balanceador de carga) - Se confirma si: El tiempo inactivo de las conexiones cortadas se concentra justo después del valor configurado (60 s en ALB, 350 s para TCP en NLB, etc.), y se reproduce al quedarse quieto más tiempo que eso y luego moverse. En NLB, TCP_ELB_Reset_Count sube a esas horas - Se descarta si: Si se corta sin relación con el tiempo inactivo, no es esta causa. Si se concentra cerca de los 350 s en un servidor al que se conecta directamente, sin balanceador de carga, apunta a “Expiración del seguimiento de conexiones en grupos de seguridad de la nube”; si ocurre en el router doméstico del jugador, a “Expiración del mapeo NAT” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Edit attributes for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/edit-load-balancer-attributes.html) · AWS · Timeout por inactividad de ALB: 60 s por defecto (1–4,000 s); si la conexión con el cliente o con el destino pasa ese tiempo en silencio, el balanceador de carga la cierra - [Network Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html) · AWS · Timeout por inactividad TCP de NLB: 350 s por defecto (60–6,000 s); al vencer, solo deja de seguir la conexión y responde con RST a los datos que lleguen después; los flujos UDP tienen 120 s fijos - [Configure load balancer TCP reset and idle timeout](https://learn.microsoft.com/en-us/azure/load-balancer/load-balancer-tcp-idle-timeout) · Microsoft Azure · Timeout por inactividad de Azure Load Balancer: 4 minutos por defecto (4–100 minutos); pasado ese tiempo no se garantiza que la sesión se mantenga; el reset de TCP es opcional - [CloudWatch metrics for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html) · AWS · TCP_ELB_Reset_Count: número de paquetes RST generados y enviados por el balanceador de carga #### dc-cloud-conntrack · Expiración del seguimiento de conexiones en grupos de seguridad de la nube · Cloud security group connection tracking timeout El firewall asociado a un servidor en la nube (grupo de seguridad) también hace seguimiento de las conexiones, y la entrada de seguimiento de una conexión inactiva expira pasado cierto tiempo. Incluso en servidores a los que se conecta directamente, sin balanceador de carga, un jugador que estuvo quieto puede sufrir una desconexión. - Por qué → Efecto → En pantalla: El grupo de seguridad está configurado de forma que hace seguimiento de las conexiones del juego (solo se permiten ciertas direcciones, reglas de salida restringidas, paso por un NLB, etc.) → La entrada de seguimiento de una conexión que pasó un rato inactiva expira, y el grupo de seguridad descarta en silencio los paquetes que llegan después → Tras estar ausente, el jugador vuelve a moverse, no hay respuesta y llega la desconexión. El programa del servidor tarda mucho en enterarse - Síntomas: Desconexión / Factores: Pérdida de paquetes - A quién: Solo yo, Todo el servidor / Cuándo: Tras un rato inactivo - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de cliente (Equipo de desarrollo), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: enviar heartbeats a intervalos de como mucho la mitad del timeout por inactividad más corto (175 s o menos si son 350 s en TCP, 90 s o menos si son 180 s en streams UDP), reconectar automáticamente si se corta. Servidor: responder a los heartbeats y cerrar primero la conexión si no llegan durante cierto tiempo, retomar la sesión con un token de sesión. - Tareas (Equipo de infraestructura): Revisar el tiempo de seguimiento de conexiones de la instancia (TcpEstablishedTimeout) y ampliarlo si hace falta (en UDP no se puede, porque 180 s ya es el máximo), estudiar una configuración del grupo de seguridad que no genere seguimiento (puertos del juego abiertos a todas las direcciones y todas las salidas permitidas; las conexiones que pasan por un NLB se siguen igualmente), hacer pruebas de inactividad al migrar a una nueva generación de instancias. - Cifras de referencia: En AWS, los tipos de instancia Nitro v6 borran por defecto la entrada de seguimiento de una conexión TCP inactiva a los 350 segundos (5 días en los demás tipos). En UDP, el valor por defecto es de 180 segundos para los flujos con varios intercambios de solicitud y respuesta (streams) y de 30 segundos para los flujos que fueron en un solo sentido o tuvieron una sola solicitud y respuesta. - En el gráfico: Desconexión masiva (Desconexiones, tiempo inactivo antes de la desconexión) - Dónde mirar: Revisar el tiempo de seguimiento configurado en la instancia y las reglas del grupo de seguridad (si la configuración genera seguimiento), y reunir el tiempo inactivo de las conexiones cortadas. Justo después de una desconexión, ver con ss -tnoi en el servidor si esa conexión sigue en ESTABLISHED con el temporizador de retransmisión (timer:(on,…)) activo y un backoff cada vez mayor - Se confirma si: El tiempo inactivo de las conexiones cortadas se concentra justo después de 350 s en TCP, 180 s en streams UDP o 30 s en UDP de un solo sentido, y el socket del servidor sigue en ESTABLISHED sin detectar el corte (si el servidor tiene datos que enviar, solo repite retransmisiones) - Se descarta si: Si el grupo de seguridad no hace seguimiento (puertos del juego abiertos a todas las direcciones, todas las salidas permitidas, sin pasar por un NLB), no es esta causa. Si pasa por un NLB, comparar los valores con “Timeout por inactividad del balanceador de carga” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Seguimiento de TCP inactivo: 350 s por defecto (Nitro v6; 432,000 s = 5 días en los demás), UDP en un solo sentido 30 s y stream 180 s (máximo 180); las reglas que permiten todas las direcciones no generan seguimiento; las conexiones que pasan por un NLB siempre se siguen - [Update the TCP idle timeout for your Network Load Balancer listener](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/update-idle-timeout.html) · AWS · Si el timeout por inactividad del NLB es más largo que el tiempo de seguimiento de conexiones de la instancia de destino, la instancia descarta primero, en silencio, el estado de la conexión - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · En -o, timer:(on,…) es el temporizador de retransmisión; en -i, backoff es el número de veces que la espera de retransmisión se ha duplicado #### dc-nat-gateway · Límites de conexiones y puertos del gateway NAT en la nube · Cloud NAT gateway connection / port limits Cuando los servidores de una subred privada abren conexiones hacia fuera (autenticación de la plataforma, pagos, API externas), el gateway NAT cambia su dirección y su puerto antes de enviarlas. Si las conexiones simultáneas hacia un mismo destino superan el límite de puertos del gateway, las conexiones nuevas fallan. - Por qué → Efecto → En pantalla: Los servidores abren muchas conexiones cortas hacia una misma dirección externa, como la autenticación de la plataforma o los pagos, o mantienen conexiones abiertas mucho tiempo → El gateway NAT no puede asignar más puertos de origen para ese destino, así que las conexiones nuevas fallan → Dentro del juego todo va bien, pero fallan o tardan solo las funciones que llaman a servicios externos, como el inicio de sesión, los pagos o la entrega de recompensas (el juego no conecta o se queda en carga infinita; acciones perdidas o rollback) - Síntomas: No conecta / carga infinita, Acción perdida / rollback / Factores: Pérdida de paquetes, Latencia - A quién: Solo una función, Todo el servidor / Cuándo: Al conectar o tras un mantenimiento, Horas pico de la noche, Cuando se junta mucha gente - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Reutilizar las conexiones a las API externas (HTTP keep-alive, pool de conexiones) y no abrir una conexión nueva por cada solicitud, enviar keepalive en las conexiones inactivas del pool a intervalos más cortos que el timeout por inactividad del NAT (350 s en AWS) o cerrarlas antes, reintentar los fallos con intervalos crecientes y aleatorios, registrar la tasa de fallos y la latencia de cada llamada externa. - Tareas (Equipo de infraestructura): Añadir direcciones IP al gateway NAT (un gateway NAT público de AWS solo admite 2 IP elásticas por defecto; para más, pedir un aumento de cuota), separar los gateways por zona de disponibilidad y subred, poner alertas sobre las métricas de fallos de asignación de puertos (ErrorPortAllocation en AWS, Failed en SNAT Connection Count de Azure, OUT_OF_RESOURCES en dropped_sent_packets_count de Google Cloud), subir el mínimo de puertos por VM o usar la asignación dinámica de puertos en Google Cloud NAT. - Cifras de referencia: Un gateway NAT de AWS puede abrir hasta 55,000 conexiones simultáneas hacia un mismo destino (IP, puerto y protocolo) por cada dirección IP, y se amplía asociando hasta 8 IP. Borra las conexiones que pasan 350 segundos en silencio y responde con RST a los paquetes que se envíen después por ellas. Azure NAT Gateway tiene 64,512 puertos SNAT por IP pública (hasta 16 IP). Google Cloud NAT reparte entre las VM 64,512 puertos por cada IP de NAT, pero el mínimo por defecto es de 64 puertos por VM (asignación estática), así que con la configuración por defecto una VM suele quedar limitada a 64 conexiones simultáneas hacia un mismo destino. - En el gráfico: Topa con el límite (Conexiones simultáneas del gateway NAT, fallos de asignación de puertos) - Dónde mirar: Poner las métricas del gateway NAT ErrorPortAllocation, ActiveConnectionCount y PacketsDropCount de CloudWatch en AWS (en Azure, SNAT Connection Count filtrado por el estado Failed y Dropped Packets; en Google Cloud, dropped_sent_packets_count con reason OUT_OF_RESOURCES) junto a las horas en que fallaron las llamadas externas del servidor del juego - Se confirma si: Cuando fallan las llamadas externas, ErrorPortAllocation (en Azure, SNAT Connection Count en estado Failed; en Google Cloud, los descartes por OUT_OF_RESOURCES) pasa de 0, y los fallos se concentran en las llamadas a uno o dos destinos con muchas conexiones, como los servidores de autenticación o de pagos - Se descarta si: Si los fallos de asignación de puertos están en 0, pero el connect del servidor del juego falla con EADDRNOTAVAIL y las conexiones en TIME_WAIT se acercan al tamaño del rango de puertos efímeros, apunta a “Agotamiento de puertos efímeros en conexiones entre servidores”. Si conecta, pero las respuestas tardan, a “Dependencia de servicios externos” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: En “Agotamiento de puertos efímeros en conexiones entre servidores” se acaban los puertos efímeros de un solo servidor. Este límite, en cambio, está en el gateway NAT y lo comparten todos los servidores que hay detrás (Google Cloud NAT lo reparte por VM). Si solo fallan las llamadas externas mientras los servidores tienen margen de sobra en TIME_WAIT y en el rango de puertos efímeros, la causa es esta. Los puertos de las conexiones cerradas tampoco se reutilizan enseguida para el mismo destino (Azure aplica un periodo de espera y Google Cloud no los deja usar durante TIME_WAIT), así que cuantas más conexiones cortas se repiten, antes se llega al límite. - Fuentes: - [NAT gateway basics](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-basics.html) · AWS · 55,000 conexiones simultáneas por dirección IPv4 hacia un mismo destino (IP, puerto y protocolo de destino), ampliable asociando hasta 8 IP (los gateways NAT públicos tienen 2 IP elásticas por defecto y se amplían pidiendo un aumento de cuota); el ancho de banda escala automáticamente de 5 a 100 Gbps y el throughput de 1 millón a 10 millones de paquetes por segundo, y los paquetes que superan ese límite se descartan - [NAT gateway metrics and dimensions](https://docs.aws.amazon.com/vpc/latest/userguide/metrics-dimensions-nat-gateway.html) · AWS · ErrorPortAllocation: veces que no se pudo asignar un puerto de origen (si pasa de 0, hay demasiadas conexiones simultáneas), ActiveConnectionCount, IdleTimeoutCount (conexiones eliminadas tras 350 s de inactividad), PacketsDropCount - [Troubleshoot NAT gateways](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-troubleshooting.html) · AWS · Tras 350 s de inactividad la conexión expira y, si se sigue enviando, se responde con RST; se recomienda un keepalive de menos de 350 s; al llegar al límite de conexiones, añadir gateways por zona de disponibilidad, añadir IP o reducir las conexiones - [Source Network Address Translation (SNAT) with Azure NAT Gateway](https://learn.microsoft.com/en-us/azure/nat-gateway/nat-gateway-snat) · Microsoft Azure · 64,512 puertos SNAT por IP pública (hasta 16 IP); cada conexión hacia un mismo destino necesita un puerto distinto; los puertos cerrados pasan un periodo de espera (cooldown) antes de reutilizarse para el mismo destino - [Metrics and alerts for Azure NAT Gateway](https://learn.microsoft.com/en-us/azure/nat-gateway/nat-metrics) · Microsoft Azure · Si SNAT Connection Count filtrado por el estado Failed pasa de 0, es posible que se hayan agotado los puertos SNAT; Dropped Packets - [IP addresses and ports](https://cloud.google.com/nat/docs/ports-and-addresses) · Google Cloud · 64,512 puertos para TCP y otros tantos para UDP por IP de NAT; mínimo de puertos por VM por defecto: 64 (asignación estática) o 32 (asignación dinámica); los puertos reservados para una VM limitan sus conexiones simultáneas hacia un mismo destino; los puertos de las conexiones cerradas no se pueden usar durante TIME_WAIT - [Logs and metrics](https://cloud.google.com/nat/docs/monitoring) · Google Cloud · dropped_sent_packets_count con reason OUT_OF_RESOURCES: paquetes descartados por falta de IP o puertos de NAT #### dc-lb-imbalance · Desbalance del balanceador de carga y health checks erróneos · LB imbalance, bad health checks Las conexiones se concentran en un solo servidor, o se sigue enviando gente a un servidor que ya está caído. - Por qué → Efecto → En pantalla: La regla de reparto no encaja o el health check no ve el estado real → Un solo servidor sobrecargado, o intentos de conexión a un servidor caído → Cámara lenta, o el juego no conecta o se queda en carga infinita, solo en algunos canales o para algunos jugadores - Síntomas: Cámara lenta, No conecta / carga infinita / Factores: Detención, Pérdida de paquetes - A quién: Una zona o un canal / Cuándo: Al conectar o tras un mantenimiento, Cuando se junta mucha gente - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Implementar un health check que responda a las comprobaciones del balanceador de carga según el estado real del juego (avance del tick, conexiones a la BD), informar también de la carga del servidor. - Tareas (Equipo de infraestructura): Cambiar a health checks que verifiquen respuestas reales del juego, repartir según la carga de los servidores, monitorear las diferencias en el número de conexiones entre servidores. - En el gráfico: Alto solo en algunos (Conexiones/utilización de CPU por servidor) - Dónde mirar: Superponer en un gráfico el número de conexiones (ss -s) y la utilización de CPU de cada servidor detrás del balanceador de carga, y comparar el estado de salud de los destinos en el balanceador (en AWS, HealthyHostCount y UnHealthyHostCount de CloudWatch) con el estado real de los servidores del juego - Se confirma si: Solo uno o dos servidores tienen muchas más conexiones y CPU que los demás, o un servidor con el tick detenido sigue marcado “en buen estado” y recibiendo conexiones nuevas - Se descarta si: Si el número de conexiones es parejo entre servidores y solo va lento un canal, apunta a la carga dentro de ese canal (“Sobrecarga de una zona de un solo hilo (hotspot)”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Casos reales: aws-2025 - Fuentes: - [Load Balancing in the Datacenter](https://sre.google/sre-book/load-balancing-datacenter/) · Google · Con un round robin simple, el uso de CPU entre tareas llega a diferir hasta 2 veces; reparto ponderado en el que los backends informan de su carga en las respuestas y en los health checks; estado lame duck, en el que un backend pide que no le envíen más solicitudes - [Health checks for Network Load Balancer target groups](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/target-group-health-checks.html) · AWS · Health check cada 30 s por defecto y exclusión tras 2 fallos; los servicios UDP se comprueban con health checks TCP o HTTP, así que se recomienda configurarlos para que reflejen el estado real del servicio - [CloudWatch metrics for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html) · AWS · HealthyHostCount y UnHealthyHostCount: número de destinos considerados en buen estado y en mal estado #### dc-microburst · Microrráfagas en el switch · Switch microburst drops Cuando varios servidores envían paquetes a miles de jugadores en el mismo instante, el pequeño búfer del puerto del switch donde se junta ese tráfico se desborda en menos de 1 ms. - Por qué → Efecto → En pantalla: Aparición de un world boss o habilidades masivas, o ticks de varios servidores que coinciden en el mismo instante y envían todo a la vez → Los búferes de los puntos donde varios puertos confluyen en uno o donde un puerto rápido pasa a uno lento (de cientos de KB a unos pocos MB por puerto) se llenan en un instante → Se descartan algunos paquetes; muchos jugadores sufren a la vez teletransporte o habilidades que no salen - Síntomas: Teletransporte, Acción perdida / rollback / Factores: Pérdida de paquetes - A quién: Una zona o un canal / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de red (Equipo de infraestructura), Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Repartir los envíos de forma uniforme dentro del tick (pacing), desfasar un poco el inicio del tick de cada servidor. - Tareas (Equipo de infraestructura): Red: usar switches con búferes más grandes, repartir el tráfico (distribuir los servidores entre varios switches y puertos), vigilar los contadores de descartes por puerto del switch. Servidores/SO: limitar la velocidad total de envío de cada servidor (shaper tc de Linux). - Cifras de referencia: Un puerto de 10 Gbps puede enviar unos 1.25 MB en 1 ms. Si el tráfico de dos puertos confluye a la vez en uno solo, se acumulan 1.25 MB cada 1 ms. Aunque la utilización media en 1 segundo sea del 10%, a escala de 1 ms puede desbordarse. - En el gráfico: Sube con la carga (Descartes de salida del puerto del switch) - Dónde mirar: Recoger, con el intervalo más corto posible, los contadores de descartes de salida (ifOutDiscards, o output drops según el dispositivo) de los puertos del switch donde están los servidores y de los puertos donde se junta su tráfico, y cruzarlos con la aparición de jefes y las batallas masivas. Los gráficos de utilización media de 1 segundo o de 1 minuto no lo muestran - Se confirma si: La utilización media es baja, pero los descartes de salida suben cada vez que la gente se concentra en un lugar, y en esos momentos muchos jugadores reportan a la vez teletransporte y habilidades que no salen - Se descarta si: Si los descartes suben de forma constante en las horas de utilización media alta, apunta a “Saturación del enlace del centro de datos”. Si suben los errores de entrada (CRC), a “Cables defectuosos y errores de puerto” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [High-Resolution Measurement of Data Center Microbursts (IMC 2017)](https://conferences.sigcomm.org/imc/2017/papers/imc17-final60.pdf) · ACM · Más del 70% de las ráfagas en un centro de datos terminan en unas decenas de µs; las ráfagas provocan descartes incluso en puertos con una utilización media de alrededor del 9% - [Data Center TCP (DCTCP) (SIGCOMM 2010)](https://conferences.sigcomm.org/sigcomm/2010/papers/sigcomm/p63.pdf) · ACM · Los switches de uso general tienen búferes poco profundos (48 puertos comparten 4 MB y un puerto puede usar hasta unos 700 KB); si varios flujos confluyen en un puerto durante un instante, hay pérdida - [RFC 2863: The Interfaces Group MIB](https://www.rfc-editor.org/rfc/rfc2863) · IETF · ifOutDiscards: número de paquetes que no se enviaron y se descartaron aunque no hubiera errores, por motivos como liberar espacio en el búfer #### dc-uplink · Saturación del enlace del centro de datos · Uplink saturation Cuando la distribución de parches, el envío de logs o las copias de seguridad usan el mismo enlace que el juego, el enlace se llena. - Por qué → Efecto → En pantalla: Las transferencias masivas acaparan el mismo enlace → Aumentan las colas y la pérdida en el enlace → Sube el ping y hay teletransporte en todo el servidor - Síntomas: Input lag, Teletransporte / Factores: Latencia, Pérdida de paquetes - A quién: Todo el servidor / Cuándo: A intervalos regulares, Cuando se junta mucha gente - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Red: dar prioridad al tráfico del juego (QoS), separar los enlaces de las transferencias masivas, poner alertas sobre la utilización del enlace. Servidores/SO: limitar la velocidad de las copias de seguridad, el envío de logs y los despliegues, y ejecutarlos en horas tranquilas. - En el gráfico: Topa con el límite (Utilización del enlace, RTT (ping)) - Dónde mirar: Poner la utilización de la interfaz del enlace del centro de datos (uplink), calculada con SNMP ifHCInOctets e ifHCOutOctets, y sus descartes de salida (ifOutDiscards) en el mismo eje de tiempo que el calendario de copias de seguridad, despliegues y envío de logs - Se confirma si: Cuando la utilización del enlace se pega al límite de ancho de banda y queda plana, suben el RTT y los descartes en todo el servidor, y esas horas coinciden con las transferencias masivas - Se descarta si: Si la utilización por minuto está muy por debajo del límite y aun así hay descartes, apunta a “Microrráfagas en el switch” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 4594: Configuration Guidelines for DiffServ Service Classes](https://www.rfc-editor.org/rfc/rfc4594) · IETF · Tratar en clases de servicio distintas el tráfico interactivo en tiempo real, como el de los juegos, y las transferencias masivas, como las copias de seguridad - [RFC 7567: IETF Recommendations Regarding Active Queue Management](https://www.rfc-editor.org/rfc/rfc7567) · IETF · Cuando a un dispositivo llega más tráfico del que puede enviar, se acumulan colas, y el exceso de cola es una de las principales causas de latencia - [RFC 2863: The Interfaces Group MIB](https://www.rfc-editor.org/rfc/rfc2863) · IETF · ifHCInOctets e ifHCOutOctets: bytes recibidos y enviados por la interfaz (64 bits); ifOutDiscards: paquetes descartados sin enviarse #### dc-failover · Failover de equipos de red · Network device failover Cuando falla un router o un firewall y el tráfico pasa al dispositivo de reserva (failover), todos se quedan congelados durante unos segundos. - Por qué → Efecto → En pantalla: Paso al dispositivo de reserva por una avería o un mantenimiento → El cambio tarda unos segundos, y si la información de sesión no está sincronizada, las conexiones se reinician → Congelamiento simultáneo de todos los jugadores del servidor, desconexión masiva - Síntomas: Congelamiento, Desconexión / Factores: Pérdida de paquetes - A quién: Todo el servidor / Cuándo: De vez en cuando, al azar - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: usar timeouts que aguanten cortes breves (unos segundos), permitir retomar la sesión con un token de sesión al reconectar tras un corte. Cliente: reconectar automáticamente si se corta (con intervalos de reintento aleatorios para que no se conecten todos a la vez). - Tareas (Equipo de infraestructura): Usar redundancia que comparta el estado de las conexiones, detectar averías en menos de 1 segundo con BFD, probar el failover con regularidad. - Cifras de referencia: Unos 1–3 segundos si el dispositivo detecta la avería al instante. Sin detección rápida de fallos (BFD), si todo depende de los temporizadores por defecto de BGP, la ruta puede quedar cortada 90–180 segundos hasta que los dispositivos vecinos lo detectan. - En el gráfico: Desconexión masiva (Conexiones, tráfico total del servidor (entrada/salida)) - Dónde mirar: Los logs de eventos de routers y firewalls (cambios de rol VRRP, caída de sesiones BFD y BGP, registros de failover) junto al número total de conexiones y el tráfico del servidor a la misma hora - Se confirma si: A la hora del cambio en el log del dispositivo, el tráfico de todos los servidores que hay detrás cae a 0 durante unos segundos o el número de conexiones baja a la vez - Se descarta si: Si solo bajan las conexiones de un servidor, apunta a “Crash del servidor” o “Problemas de driver y firmware de la NIC”. Si los logs de los dispositivos están limpios y el servidor que se detuvo es una sola VM en la nube, a “Mantenimiento del host en la nube y migración en vivo” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 5880: Bidirectional Forwarding Detection (BFD)](https://www.rfc-editor.org/rfc/rfc5880) · IETF · El mecanismo Hello de los protocolos de enrutamiento tarda 1 segundo o más en detectar un fallo; BFD se creó para detectarlo en menos tiempo - [RFC 7938: Use of BGP for Routing in Large-Scale Data Centers](https://www.rfc-editor.org/rfc/rfc7938) · IETF · Si solo se confía en los keepalive de BGP, la convergencia es lenta; si la sesión se corta en cuanto cae el enlace, el fallo se detecta en ms y se vuelve a converger - [RFC 5798: Virtual Router Redundancy Protocol (VRRP) Version 3 for IPv4 and IPv6](https://www.rfc-editor.org/rfc/rfc5798) · IETF · Anuncios VRRP cada 1 s por defecto; el dispositivo de reserva toma el rol si los anuncios se interrumpen durante más de unas 3 veces el intervalo (poco más de 3 s con la configuración por defecto) #### dc-bad-cable · Cables defectuosos y errores de puerto · Bad cable / optics (CRC errors) Si un transceptor óptico o un cable está defectuoso, se corrompe una proporción constante de los paquetes que pasan por esa ruta. - Por qué → Efecto → En pantalla: Errores de bits por un transceptor óptico o un cable defectuoso → El dispositivo descarta en silencio los paquetes corruptos → Solo algunos servidores o jugadores que usan esa ruta sufren teletransporte o rubber banding por una pérdida constante - Síntomas: Teletransporte, Rubber banding / Factores: Pérdida de paquetes - A quién: Una zona o un canal / Cuándo: Siempre - Responsable principal: Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Monitorear los contadores de errores de puerto (CRC) y poner alertas, reemplazar piezas como transceptores ópticos y cables, sacar el enlace problemático y desviar el tráfico hasta que se reemplace. - En el gráfico: Alto solo en algunos (Errores CRC por puerto, tasa de pérdida por servidor/ruta) - Dónde mirar: Mirar los contadores CRC de los dos extremos del enlace. En los switches, los errores de FCS (dot3StatsFCSErrors) y de entrada (ifInErrors) del puerto; en los servidores, crc dentro de RX errors en ip -s -s link (estadística del kernel rx_crc_errors) - Se confirma si: Los errores CRC de un puerto suben de forma constante, sin relación con el volumen de tráfico ni con la hora, y solo hay pérdida en los servidores y jugadores que pasan por ese puerto - Se descarta si: Si no hay errores CRC y solo suben los descartes de salida, apunta a congestión (“Microrráfagas en el switch”, “Saturación del enlace del centro de datos”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Understanding and Mitigating Packet Corruption in Data Center Networks (SIGCOMM 2017)](https://www.microsoft.com/en-us/research/wp-content/uploads/2017/06/CorrOpt_SIGCOMM2017.pdf) · ACM · Análisis de 350,000 enlaces de centros de datos: la corrupción viene de transceptores ópticos defectuosos, fibra dañada y conectores sucios; la tasa de corrupción es constante y no depende del uso; los enlaces problemáticos se sacan para repararlos manteniendo suficientes rutas - [RFC 3635: Definitions of Managed Objects for the Ethernet-like Interface Types](https://www.rfc-editor.org/rfc/rfc3635) · IETF · Contador de fallos de la comprobación de trama, FCS (dot3StatsFCSErrors); estos errores se suman a los errores de entrada (ifInErrors) - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · rx_crc_errors: número de paquetes recibidos con errores CRC; ip -s -s link muestra los errores por tipo #### dc-mtu · Desajuste de MTU (solo desaparecen los paquetes grandes) · MTU black hole Si la MTU (el tamaño máximo que se puede enviar de una vez) se reduce en un tramo intermedio y los avisos de tamaño excedido están bloqueados, solo los paquetes grandes desaparecen una y otra vez. - Por qué → Efecto → En pantalla: La MTU se reduce en un tramo con túnel o VPN → Un firewall bloquea los avisos de tamaño excedido (ICMP) y el emisor no se entera → Congelamiento y luego desconexión solo al abrir pantallas grandes, como el inventario o la lista de personajes - Síntomas: Congelamiento, Desconexión, No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Una región o un ISP, Solo yo / Cuándo: Al hacer ciertas acciones, Al conectar o tras un mantenimiento - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Para bajarlo directamente desde el servidor, configurar en el socket el tamaño máximo de segmento con TCP_MAXSEG (partir los mensajes en trozos más pequeños en el código del juego no basta para evitarlo), mantener los paquetes UDP en 1,200 bytes o menos. - Tareas (Equipo de infraestructura): Red: reducir el tamaño de los paquetes TCP en los tramos con túnel (ajuste del MSS), permitir los avisos de tamaño excedido (ICMP) en los firewalls y las ACL de red en la nube. Servidores/SO: permitir también los avisos de tamaño excedido (ICMP) en los firewalls de los servidores y los grupos de seguridad en la nube, activar la detección de MTU en el kernel del servidor (tcp_mtu_probing=1), una última red de seguridad que solo actúa después de que la conexión pase unos segundos detenida. - Cifras de referencia: Normalmente es de 1,500 bytes, y al pasar por un túnel baja a unos 1,400. - En el gráfico: Alto solo en algunos (Desconexiones por región/ISP, respuestas grandes fallidas) - Dónde mirar: Desde la computadora del jugador afectado, enviar al servidor pings con la marca de no fragmentar (DF) variando el tamaño. En Windows, ping /f /l 1472 SERVER_IP; en Linux, ping -M do -s 1472 SERVER_IP (1,472 es la MTU de 1,500 menos los 20 bytes de la cabecera IP y los 8 bytes de la cabecera ICMP). Bajar el tamaño poco a poco hasta encontrar el máximo que pasa, y comprobar si los grupos de seguridad y firewalls del lado del servidor permiten los avisos ICMP de tamaño excedido (Fragmentation Needed) - Se confirma si: Los pings pequeños pasan, pero el ping DF de 1,472 bytes falla (sin respuesta o con un error de que hace falta fragmentar), y el tamaño máximo que pasa es pequeño, de unos 1,400. Los jugadores de una misma región se congelan solo al abrir pantallas grandes - Se descarta si: Si el ping DF de 1,472 bytes también pasa, no es un problema de MTU de la ruta. Si ni siquiera pasan los pings pequeños, el ICMP está bloqueado del todo y este método no sirve para saberlo - Se verifica con: En el entorno del jugador - Fuentes: - [RFC 2923: TCP Problems with Path MTU Discovery](https://www.rfc-editor.org/rfc/rfc2923) · IETF · Si un firewall bloquea el ICMP (Fragmentation Needed), la detección de la MTU de la ruta falla y solo los paquetes grandes siguen desapareciendo (agujero negro); el ping y los mensajes pequeños funcionan, lo que dificulta el diagnóstico - [Maximum transmission unit and maximum segment size](https://developers.cloudflare.com/magic-transit/reference/mtu-mss/) · Cloudflare · MTU de una ruta por internet: 1,500; al pasar por un túnel GRE, 1,476; se recomienda limitar el MSS de TCP a 1,436 o menos - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_mtu_probing=1 está normalmente apagado y activa la detección de MTU de la ruta en TCP solo cuando detecta un agujero negro ICMP - [ping(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ping.8.html) · iputils · -M do activa la marca DF y rechaza los paquetes más grandes que la MTU de la ruta; -s fija el tamaño de los datos (56 bytes por defecto, más 8 bytes de cabecera ICMP) - [ping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ping) · Microsoft · /f activa la marca DF y sirve para encontrar problemas de MTU de la ruta; /l fija el tamaño de los datos ### L6 Tarjeta de red del servidor (causas: 9) #### nic-irq · Interrupciones de la NIC concentradas en un solo núcleo · Single-queue NIC / no RSS Si la NIC envía las interrupciones de llegada de paquetes a un solo núcleo de CPU, ese núcleo se convierte en el cuello de botella. - Por qué → Efecto → En pantalla: Hay una sola cola de recepción o está desactivado RSS, que reparte los paquetes entre varios núcleos → Un núcleo llega al 100% y no saca los paquetes a tiempo → Pérdida y latencia en todo el servidor cuando se junta mucha gente (teletransporte, input lag) - Síntomas: Teletransporte, Rubber banding, Input lag / Factores: Pérdida de paquetes, Latencia - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Configurar RSS (reparto en la NIC) y RPS (reparto en el kernel), repartir las interrupciones entre varios núcleos, hacer que en UDP la cola se elija mirando también los puertos (rx-flow-hash udp4 sdfn de ethtool -N), separar los núcleos que atienden interrupciones de los del hilo del tick del juego, vigilar el %soft por núcleo. - Cifras de referencia: Un núcleo puede procesar a través del kernel aproximadamente cientos de miles de paquetes por segundo, según el tamaño de los paquetes y la configuración. Si en la utilización por núcleo la parte del procesamiento de recepción (%soft de mpstat) se concentra en un solo núcleo, es este caso. - En el gráfico: Topa con el límite (%soft por núcleo, paquetes recibidos por segundo) - Dónde mirar: Ver el %soft (proporción de tiempo dedicada a procesar interrupciones de software) por núcleo con mpstat -P ALL 1, a qué núcleo van las interrupciones de cada cola de la NIC en /proc/interrupts, el número de colas con ethtool -l y los paquetes por cola con ethtool -S (los nombres cambian según el driver) - Se confirma si: Un solo núcleo tiene el %soft pegado cerca del 100% mientras los demás están libres, y las interrupciones y los paquetes se concentran en una cola. A partir de ahí, los paquetes recibidos por segundo ya no suben más - Se descarta si: Si el %soft está repartido de forma uniforme entre los núcleos, no es esta causa. Si la CPU está libre y hay pérdida, apunta a “Límite de PPS de la nube superado” o “Búfer circular (ring buffer) insuficiente” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Aunque haya varias colas, si casi todo el tráfico viene de unas pocas direcciones, como gateways o proxies, se concentra en una sola cola. En UDP, algunas NIC eligen la cola por defecto mirando solo las direcciones, y el tráfico solo se reparte de forma uniforme al cambiarlo para que mire también los puertos. - Fuentes: - [Scaling in the Linux Networking Stack](https://docs.kernel.org/networking/scaling.html) · Linux kernel · RSS (la NIC reparte entre varias colas de recepción) y RPS (reparte el kernel), configuración que da a cada cola su propia interrupción y las reparte entre núcleos; se recomienda RSS cuando el cuello de botella es el procesamiento de las interrupciones de recepción - [How to receive a million packets per second](https://blog.cloudflare.com/how-to-receive-a-million-packets/) · Cloudflare · Mediciones en las que una cola de recepción atendida por un solo núcleo se atascaba en unos 350,000–430,000 paquetes por segundo; caso en que la NIC aplicaba el hash a UDP solo por dirección IP y todo se concentraba en una cola - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · La opción ethtool -N rx-flow-hash udp4, que añade los puertos (f y n) al hash de UDP - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · %soft: proporción del tiempo de CPU dedicada a procesar interrupciones de software; por núcleo con -P ALL #### nic-ring · Búfer circular (ring buffer) insuficiente · RX ring buffer overflow Si el búfer circular, donde la NIC guarda los paquetes un momento, es pequeño, se desborda cuando llegan muchos de golpe y los paquetes se descartan. - Por qué → Efecto → En pantalla: El búfer circular se deja en su valor por defecto, que es pequeño (256–2,048 slots según el driver) → En una ráfaga, el búfer se desborda antes de que la CPU saque los paquetes → Pérdida solo en los momentos de ráfaga (teletransporte, habilidades que no salen). Sin rastro en los logs del servidor del juego - Síntomas: Teletransporte, Acción perdida / rollback / Factores: Pérdida de paquetes - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Ampliar el búfer circular (ethtool -G), vigilar los contadores de descartes (drop), como rx_missed_errors en ethtool -S (los nombres cambian según el driver). - Cifras de referencia: Si llega 1 millón de paquetes por segundo, 1,024 slots se llenan en aproximadamente 1 ms. Basta con que la CPU llegue tarde una sola vez en ese intervalo para que se desborde. La mayoría de las NIC permiten ampliarlo a varios miles. - En el gráfico: Picos aleatorios (Contadores de descartes de recepción de la NIC) - Dónde mirar: Recoger a intervalos cortos los contadores de descartes de recepción de ethtool -S (rx_missed_errors, rx_fifo_errors, etc.; los nombres cambian según el driver) y el missed de ip -s -s link, y ver con ethtool -g el tamaño actual y el máximo del búfer circular - Se confirma si: Los contadores de descartes suben en los momentos de ráfaga y el tamaño actual del búfer está muy por debajo del máximo. Al ampliarlo, los descartes bajan - Se descarta si: Si los contadores de descartes no se mueven y aun así hay pérdida, apunta a la siguiente etapa del kernel (“Búferes de socket del kernel insuficientes”) o a la red. Si el %soft de un núcleo está al 100%, a “Interrupciones de la NIC concentradas en un solo núcleo” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Linux Base Driver for Intel(R) Ethernet Network Connection (e1000)](https://docs.kernel.org/networking/device_drivers/ethernet/intel/e1000.html) · Linux kernel · Descriptores de recepción (slots del búfer circular) de e1000: 256 por defecto, ampliables hasta 4,096 - [drivers/net/ethernet/intel/ice/ice.h (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/intel/ice/ice.h?h=v6.12) · Linux kernel · Descriptores de recepción del driver ice: 2,048 por defecto, máximo 8,160 - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · Los paquetes que el dispositivo descarta por falta de búfer se cuentan en rx_missed_errors; las estadísticas de cada driver se ven con ethtool -S - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · -g muestra el tamaño del búfer circular (actual y máximo), -G lo cambia, -S muestra las estadísticas del driver #### nic-coalesce · Coalescencia de interrupciones excesiva · Interrupt coalescing Para reducir la carga de la CPU, la NIC junta paquetes y avisa de una sola vez, así que los paquetes se retrasan lo que dura esa espera. - Por qué → Efecto → En pantalla: La NIC junta paquetes durante cierto tiempo o hasta cierto número antes de avisar → Los paquetes esperan mientras se juntan → Leve aumento de la latencia. Normalmente es pequeño, pero si se exagera llega al orden de ms - Síntomas: Input lag / Factores: Latencia - A quién: Todo el servidor / Cuándo: Siempre - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Usar coalescencia adaptativa, ajustar los valores para un servidor de juegos (ethtool -C). - Cifras de referencia: Normalmente de decenas a cientos de µs. Para un juego suele ser despreciable, pero con una configuración excesiva llega a ms. - En el gráfico: Siempre alto (Tiempo de ida y vuelta dentro del mismo centro de datos) - Dónde mirar: Ver con ethtool -c la configuración actual de coalescencia (adaptive-rx, rx-usecs, rx-frames) y comparar el tiempo de ida y vuelta del ping a otro servidor del mismo centro de datos antes y después de cambiarla - Se confirma si: rx-usecs está configurado alto (cientos de µs o más) y, al bajarlo, el tiempo de ida y vuelta dentro del centro de datos se reduce en la misma medida - Se descarta si: Si al bajarlo el tiempo de ida y vuelta no cambia, no es esta causa - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Linux Driver for Intel(R) Ethernet Network Connection (e1000e)](https://docs.kernel.org/networking/device_drivers/ethernet/intel/e1000e.html) · Linux kernel · Por defecto, moderación adaptativa de interrupciones de 4,000–20,000 por segundo (cada 50–250 µs); menos interrupciones ahorran CPU, pero aumentan la latencia - [Linux Base Driver for Intel(R) Ethernet Network Connection (e1000)](https://docs.kernel.org/networking/device_drivers/ethernet/intel/e1000.html) · Linux kernel · RxIntDelay puede retrasar las interrupciones de recepción en unidades de 1.024 µs hasta 65,535 (unos 67 ms), y cuanto mayor es el valor, más latencia de recepción hay - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Los ajustes adaptive-rx, rx-usecs y rx-frames de ethtool -C #### nic-cloud-pps · Límite de PPS de la nube superado · Cloud PPS / bandwidth allowance Cada tipo de servidor en la nube tiene límites de paquetes por segundo y de ancho de banda, y lo que los supera se descarta en silencio. - Por qué → Efecto → En pantalla: Al subir los jugadores conectados a la vez (CCU), los paquetes por segundo superan el límite de la instancia → La red de la nube descarta el exceso → Teletransporte y habilidades que no salen por una pérdida sin causa aparente. La CPU del servidor va sobrada - Síntomas: Teletransporte, Acción perdida / rollback / Factores: Pérdida de paquetes - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente, Horas pico de la noche - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo), Externo (Externo) - Tareas (Equipo de desarrollo): Agrupar paquetes (los mensajes de un tick en un solo paquete), no enviar con frecuencia paquetes muy pequeños. - Tareas (Equipo de infraestructura): Revisar los contadores de límite superado (en AWS, pps_allowance_exceeded, conntrack_allowance_exceeded, etc.) y poner alertas, pasar a una instancia más grande, evitar el límite de seguimiento de conexiones con una configuración del grupo de seguridad que no genere seguimiento. - Tareas (Externo): Preguntar al proveedor de nube los límites de paquetes por segundo y de seguimiento de conexiones de cada tipo de instancia. - Cifras de referencia: Los límites varían según el tamaño de la instancia, y el límite de paquetes por segundo muchas veces no se publica. El “hasta 10 Gbps” de las instancias pequeñas es una velocidad de ráfaga disponible solo mientras quedan créditos (normalmente 5–60 minutos), y la velocidad base habitual es mucho menor. - En el gráfico: Topa con el límite (Paquetes por segundo, contadores de allowance superado) - Dónde mirar: Recoger a intervalos cortos los contadores ENA pps_allowance_exceeded, bw_in_allowance_exceeded, bw_out_allowance_exceeded y conntrack_allowance_exceeded de ethtool -S y verlos junto a los paquetes por segundo. También se pueden publicar con el agente de CloudWatch y ponerles alarmas - Se confirma si: A la hora de la pérdida suben los contadores de allowance superado y los paquetes por segundo no pasan de un valor fijo. La CPU del servidor va sobrada - Se descarta si: Si los contadores de límite superado no se mueven, no es esta causa. Si el %soft de un núcleo está al 100%, apunta a “Interrupciones de la NIC concentradas en un solo núcleo” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: conntrack_allowance_exceeded indica que la tabla de seguimiento de conexiones se llenó y se descartaron conexiones nuevas. Si la tabla tiene margen y solo se cortan las conexiones inactivas porque su seguimiento expiró, consulta la entrada “Expiración del seguimiento de conexiones en grupos de seguridad de la nube”. - Fuentes: - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · Cada instancia tiene límites de ancho de banda, PPS y seguimiento de conexiones; lo que los supera se encola y luego se descarta; contadores pps_allowance_exceeded y conntrack_allowance_exceeded - [Amazon EC2 instance network bandwidth](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-network-bandwidth.html) · AWS · El “hasta N Gbps” de las instancias de 16 vCPU o menos es una ráfaga que consume créditos de E/S de red (normalmente 5–60 minutos); cuando se acaban los créditos, vuelve al ancho de banda base #### nic-saturate · Saturación del ancho de banda de la NIC · NIC bandwidth saturation Si una tarjeta de 1 Gbps o 10 Gbps se usa hasta su límite, la cola de transmisión crece y al final los paquetes se descartan. - Por qué → Efecto → En pantalla: Con más broadcasts, el tráfico llega al límite de la tarjeta → La cola de transmisión crece y, cuando se desborda, se descartan paquetes → Latencia y pérdida en todo el servidor (input lag, teletransporte) - Síntomas: Input lag, Teletransporte / Factores: Latencia, Pérdida de paquetes - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Reducir el tráfico (área de interés, compresión, enviar solo los cambios). - Tareas (Equipo de infraestructura): Ampliar la tarjeta (una NIC más rápida o, en la nube, una instancia más grande), poner alertas sobre la utilización de la NIC. - En el gráfico: Topa con el límite (Volumen de transmisión de la NIC, descartes de transmisión) - Dónde mirar: Comparar txkB/s y %ifutil (utilización respecto a la velocidad de la interfaz) de sar -n DEV 1 con la velocidad de la NIC o el ancho de banda de la instancia, junto con TX dropped de ip -s link - Se confirma si: El volumen de transmisión queda plano cerca del ancho de banda de la NIC o de la instancia, y a partir de ahí aumentan los descartes de transmisión y la latencia de todo el servidor - Se descarta si: Si el ancho de banda tiene margen, no es esta causa. Si hay muchos paquetes pequeños y pérdida, apunta a “Límite de PPS de la nube superado” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · tx_dropped: número de paquetes descartados durante la transmisión por falta de recursos - [Amazon EC2 instance network bandwidth](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-network-bandwidth.html) · AWS · El ancho de banda que puede usar una instancia depende de su número de vCPU (tamaño de la instancia) - [sar(1) — Linux manual page](https://man7.org/linux/man-pages/man1/sar.1.html) · sysstat · rxkB/s, txkB/s y %ifutil (utilización respecto a la velocidad de la interfaz) de -n DEV #### nic-noisy · Sobrecarga de virtualización y vecino ruidoso · Noisy neighbors in virtualization Cuando otras máquinas virtuales del mismo servidor físico usan mucha red o CPU, el procesamiento de nuestro servidor se retrasa de forma irregular. - Por qué → Efecto → En pantalla: Otras máquinas virtuales del mismo servidor físico usan muchos recursos → El procesamiento de paquetes de nuestra máquina virtual se retrasa de forma irregular → De vez en cuando aparece jitter (variación en el tiempo de llegada de los paquetes) sin una causa clara, y el juego va a tirones - Síntomas: Tirones / Factores: Jitter - A quién: Todo el servidor / Cuándo: De vez en cuando, al azar - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Externo (Externo) - Tareas (Equipo de infraestructura): Usar hosts dedicados o instancias con rendimiento garantizado, detener y volver a iniciar las instancias con jitter persistente para moverlas a otro host. - Tareas (Externo): Reportar el host problemático al proveedor de nube. - En el gráfico: Picos aleatorios (Jitter del tiempo de ida y vuelta dentro del centro de datos, %steal) - Dónde mirar: Enviar ping de forma continua a otro servidor del mismo centro de datos para registrar el jitter del tiempo de ida y vuelta, y compararlo, junto con el %steal de mpstat, con otras instancias de la misma configuración - Se confirma si: Solo esta instancia tiene picos irregulares de jitter o de %steal, y las demás de la misma configuración están tranquilas. Al detenerla y volver a iniciarla para moverla a otro host, desaparece - Se descarta si: Si todas las instancias de la misma configuración tienen los mismos picos, no es un problema del host. Hay que revisar la carga del servidor del juego o la red - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [How EC2 instance stop and start works](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-ec2-instance-stop-start-works.html) · AWS · Al detener e iniciar una instancia, casi siempre pasa a un host nuevo (salvo en hosts dedicados) - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · %steal: porcentaje de tiempo que esta CPU virtual tuvo que esperar mientras el hipervisor atendía a otra CPU virtual #### nic-host-maintenance · Mantenimiento del host en la nube y migración en vivo · Cloud host maintenance / live migration Cuando el proveedor de nube hace mantenimiento de un servidor físico (host), mueve las máquinas virtuales a otro host (migración en vivo) o las pausa un momento. Mientras tanto, todo el servidor se detiene y, si la pausa es larga, las conexiones se cortan. - Por qué → Efecto → En pantalla: El proveedor mueve la máquina virtual a otro host o la pausa un momento por mantenimiento del host o por una avería prevista → Durante el traslado, la CPU, la memoria y la red van más lentas, y al final la máquina virtual se detiene por completo un instante (de menos de 1 segundo a unos 30 segundos, según el proveedor y el método) → Todos los jugadores del servidor se congelan a la vez y luego hay cámara rápida y teletransporte; si la pausa dura más que el timeout, desconexión masiva - Síntomas: Congelamiento, Cámara rápida, Teletransporte, Desconexión / Factores: Detención, Pérdida de paquetes - A quién: Todo el servidor / Cuándo: De vez en cuando, al azar - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo), Externo (Externo) - Tareas (Equipo de desarrollo): Usar timeouts que aguanten pausas de unos segundos, poner un límite a los ticks que se recuperan tras una pausa, calcular el tiempo transcurrido con un reloj monotónico, tener un procedimiento que guarde el progreso y mueva a los jugadores a otro servidor al recibir el aviso de mantenimiento. - Tareas (Equipo de infraestructura): Suscribirse a los avisos de mantenimiento y poner alertas (Google Cloud maintenance-event, eventos programados de AWS y AWS Health, Azure Scheduled Events), reemplazar el servidor de antemano en horas con pocos jugadores al recibir un aviso, ajustar la hora del mantenimiento cuando el proveedor lo permita (Azure Maintenance Configuration, eventos programados de AWS según el tipo), cruzar los registros de mantenimiento con los de incidentes. - Tareas (Externo): Consultar al proveedor de nube el calendario de mantenimiento y su alcance, reportar las instancias que se pausan una y otra vez. - Cifras de referencia: Según Google Compute Engine, la pausa de la migración en vivo suele ser mucho más corta que 1 segundo, y durante la pausa el reloj del sistema puede saltar hasta 5 segundos hacia delante. El valor maintenance-event de los metadatos cambia 60 segundos antes del traslado (si se consultó al menos una vez antes). En Azure, el mantenimiento que no requiere reinicio casi siempre detiene la VM menos de 10 segundos y, rara vez (no más de una vez cada 18 meses en los tamaños de uso general), unos 30 segundos; la migración en vivo no suele pasar de 5 segundos. Azure Scheduled Events avisa de estas pausas (Freeze) con al menos 15 minutos de antelación. Pero si el hardware del host falla de repente, la recuperación empieza enseguida, sin aviso. - En el gráfico: Hueco y luego ráfaga (Paquetes enviados/recibidos del servidor, intervalo de tick) - Dónde mirar: Cruzar la hora de la pausa con los registros del proveedor. Google Cloud: compute.instances.migrateOnHostMaintenance en los logs de auditoría; AWS: eventos programados en describe-instance-status y AWS Health; Azure: Microsoft.Compute/virtualMachines/liveMigration/action en el registro de actividad (Activity Log) y la hora en que la métrica de disponibilidad de la VM (VmAvailabilityMetric) cayó a 0. Dentro del servidor, ver si las métricas y los logs tienen un hueco durante la pausa y si el reloj saltó justo después (logs de sincronización horaria) - Se confirma si: La hora a la que se detuvo todo el servidor coincide con un mantenimiento o una migración que el proveedor tiene registrados, y durante esos segundos todas las métricas y los logs del servidor están vacíos - Se descarta si: Si no aparece en los registros del proveedor y se repiten pausas cortas a menudo, apunta a “CPU steal (máquinas virtuales)”. Si el log del kernel tiene registros de reinicio (reset) de la NIC, a “Problemas de driver y firmware de la NIC” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: AWS avisa mediante eventos programados. system-reboot significa que la instancia se reiniciará y pasará a un host nuevo; system-maintenance significa que un mantenimiento de red o de alimentación puede afectarla un momento. Aunque la pausa dure unos segundos, los clientes que no recibieron el ACK de los paquetes enviados al servidor en ese tiempo van duplicando la espera de retransmisión, así que la conexión TCP puede seguir detenida un rato más después de la pausa (“RTO de TCP y backoff exponencial”). Al despertar, el reloj puede saltar y provocar un “Salto del reloj del sistema (step de NTP)”, y los health checks del balanceador de carga pueden fallar y sacar ese servidor durante un tiempo. Las instancias que no se pueden mover (como las instancias bare metal de Google Cloud) se detienen o se reinician durante el mantenimiento. - Fuentes: - [Live migration process during maintenance events](https://cloud.google.com/compute/docs/instances/live-migration-process) · Google Cloud · La pausa de la migración en vivo suele ser mucho más corta que 1 segundo; durante la pausa el reloj del sistema salta hasta 5 segundos hacia delante; durante el traslado baja un momento el rendimiento de disco, CPU, memoria y red; las VM que no hacen migración en vivo se apagan durante el mantenimiento (las instancias bare metal no la admiten) - [Query metadata server for maintenance event notices](https://cloud.google.com/compute/docs/metadata/getting-live-migration-notice) · Google Cloud · El valor maintenance-event de los metadatos cambia 60 segundos antes de la migración en vivo (si la VM está configurada para migración en vivo y el valor se consultó al menos una vez desde el último mantenimiento) - [Monitor and plan for a host maintenance event](https://cloud.google.com/compute/docs/instances/monitor-plan-host-maintenance-event) · Google Cloud · El mantenimiento deja en los logs de auditoría un evento de sistema compute.instances.migrateOnHostMaintenance - [Scheduled events for Amazon EC2 instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-instances-status-check_sched.html) · AWS · Tipos de eventos programados (system-reboot: reinicio y traslado a un host nuevo; system-maintenance: efecto breve por mantenimiento de red o de alimentación), aviso por correo y por AWS Health, consulta con describe-instance-status, hora ajustable según el tipo - [Maintenance and updates](https://learn.microsoft.com/en-us/azure/virtual-machines/maintenance-and-updates) · Microsoft Azure · El mantenimiento sin reinicio casi siempre pausa menos de 10 s, rara vez (no más de una vez cada 18 meses en los tamaños de uso general) unos 30 s, y la migración en vivo suele durar 5 s o menos; tras la pausa el reloj se sincroniza solo; las conexiones TCP largas pueden cortarse, o la recuperación puede tardar más porque el otro extremo retransmite con backoff exponencial los datos enviados a la VM pausada; los health checks del balanceador de carga la marcan en mal estado en unos 10 s; se confirma con Microsoft.Compute/virtualMachines/liveMigration/action en el registro de actividad y con VmAvailabilityMetric, que cae a 0 durante la pausa; con Maintenance Configuration se elige cuándo se aplica - [Scheduled Events for Linux VMs in Azure](https://learn.microsoft.com/en-us/azure/virtual-machines/linux/scheduled-events) · Microsoft Azure · Freeze (pausa de unos segundos; la CPU y la red pueden detenerse) se avisa con al menos 15 minutos de antelación; si falla el hardware del host, la recuperación empieza enseguida, sin periodo de aviso #### nic-reset · Problemas de driver y firmware de la NIC · NIC hang / reset Cuando un bug del driver o una función que falla deja colgada la tarjeta, se corta todo el envío y la recepción mientras se reinicia. - Por qué → Efecto → En pantalla: Bug del driver, fallo de una función de offload → La NIC se cuelga y se reinicia (unos segundos) → Todos los jugadores de ese servidor se congelan a la vez y luego hay teletransporte o desconexión - Síntomas: Congelamiento, Desconexión / Factores: Pérdida de paquetes - A quién: Todo el servidor / Cuándo: De vez en cuando, al azar, Cuanto más tiempo lleva encendido - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Revisar en el log del kernel los registros “transmit queue … timed out” y “Link is Down” y poner alertas, actualizar drivers y firmware, desactivar la función problemática (un offload, por ejemplo). - En el gráfico: Hueco y luego ráfaga (Paquetes enviados/recibidos del servidor) - Dónde mirar: Buscar con dmesg en el log del kernel “NETDEV WATCHDOG … transmit queue N timed out”, los reinicios del driver y los registros “Link is Down” y “Link is Up”, y mirar los paquetes enviados y recibidos del servidor a esas horas - Se confirma si: En el momento del corte, el log del kernel tiene un timeout de la cola de transmisión o registros de enlace caído y restablecido (down/up), y durante esos segundos los paquetes enviados y recibidos caen a 0 - Se descarta si: Si el log del kernel está limpio y el puerto del lado del switch está bien, apunta a una detención del proceso del servidor del juego (“Pausa stop-the-world del GC en el servidor”, “Deadlock”) o a “Failover de equipos de red” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [net/sched/sch_generic.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/sched/sch_generic.c?h=v6.12) · Linux kernel · Cuando una cola de transmisión se atasca, el watchdog del kernel registra “NETDEV WATCHDOG … transmit queue N timed out” y llama a la función de reinicio del driver - [drivers/net/ethernet/intel/ixgbe/ixgbe_main.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c?h=v6.12) · Linux kernel · El driver ixgbe reinicia el adaptador cuando la transmisión se cuelga y registra “NIC Link is Down” cuando cae el enlace - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · La opción ethtool -K para desactivar las funciones de offload una a una #### nic-offload · Retraso por agrupación en GRO/LRO · GRO/LRO batching Son funciones que agrupan varios paquetes en uno para reducir la carga de la CPU. Según la configuración, un paquete pequeño del juego puede esperar un momento al siguiente paquete con el que agruparse. - Por qué → Efecto → En pantalla: La NIC y el kernel agrupan los paquetes que llegan para procesarlos juntos → Si está activada la agrupación por hardware (LRO) o un tiempo de espera de agrupación, el paquete espera un momento al siguiente → Leve aumento de la latencia (normalmente decenas de µs o menos) - Síntomas: Input lag / Factores: Latencia - A quién: Todo el servidor / Cuándo: Siempre - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Ajustarlo al tráfico del juego (desactivar LRO, revisar la configuración del tiempo de espera de agrupación), revisarlo después de otras causas porque el efecto suele ser pequeño. - En el gráfico: Siempre alto (Tiempo de ida y vuelta dentro del mismo centro de datos) - Dónde mirar: Ver con ethtool -k el estado de lro y gro y el valor de gro_flush_timeout en la configuración sysfs del dispositivo, y comparar el tiempo de ida y vuelta de paquetes pequeños dentro del centro de datos antes y después de cambiarlos - Se confirma si: LRO está activado o gro_flush_timeout es mayor que 0, y al desactivarlo o ponerlo a 0, el tiempo de ida y vuelta de los paquetes pequeños baja - Se descarta si: Si con el cambio la diferencia queda dentro de unos pocos µs, no es esta causa - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [NAPI](https://docs.kernel.org/networking/napi.html) · Linux kernel · Un gro_flush_timeout grande agrupa más el procesamiento, pero añade latencia cuando la carga es baja - [Linux Base Driver for the Intel(R) Ethernet 10 Gigabit PCI Express Adapters (ixgbe)](https://docs.kernel.org/networking/device_drivers/ethernet/intel/ixgbe.html) · Linux kernel · GRO ahorra CPU uniendo el tráfico entrante en bloques grandes y es una evolución de LRO - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Los ajustes gro y lro on|off de ethtool -K ### L7 SO del servidor (kernel) (causas: 14) #### so-backlog · Desbordamiento de la cola de conexiones pendientes (backlog) · Listen backlog / SYN queue overflow Cuando decenas de miles de jugadores se conectan a la vez justo después de un mantenimiento, la cola de conexiones pendientes (backlog) del kernel se desborda y se descartan intentos de conexión. - Por qué → Efecto → En pantalla: Al terminar el mantenimiento, las conexiones llegan más rápido de lo que el servidor del juego puede aceptarlas con accept → La cola de conexiones pendientes del kernel (backlog: el menor entre el valor que el código del servidor pasa a listen y el límite del kernel) se llena → Se descartan intentos de conexión y los reintentos se repiten: el juego no conecta o se queda en carga infinita - Síntomas: No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Todo el servidor / Cuándo: Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: aumentar el valor que el código pasa a listen, evitar que el hilo que acepta conexiones se detenga por otras tareas, implantar un sistema de cola de inicio de sesión. Cliente: alargar el intervalo entre reintentos (repartidos al azar). - Tareas (Equipo de infraestructura): Aumentar somaxconn en el kernel (solo surte efecto si también se sube el valor de listen en el código del servidor), mantener activadas las SYN cookies, vigilar el número de desbordamientos (TcpExtListenOverflows de nstat). - Cifras de referencia: El límite del kernel de Linux (somaxconn) es 4,096 por defecto desde la versión 5.4 (antes, 128), pero si el código del servidor pasa a listen un valor menor, el límite es ese valor. Cuando la cola se llena, Linux descarta las solicitudes de conexión en silencio, sin devolver error. Como el SO del cliente reenvía la solicitud varias veces, la primera al cabo de 1 segundo, el jugador lo percibe como una carga larga. Los servidores Windows devuelven una respuesta de rechazo, y el cliente muestra “Error de conexión” al momento. - En el gráfico: Avalancha tras la apertura (Desbordamientos de la cola de conexiones pendientes (ListenOverflows), intentos de conexión) - Dónde mirar: Incremento de TcpExtListenOverflows y TcpExtListenDrops en nstat -az; con ss -ltn, comparar el Recv-Q (conexiones esperando accept) y el Send-Q (límite del backlog) del socket de escucha - Se confirma si: ListenOverflows sube a la hora en que se concentran las conexiones y el Recv-Q del socket de escucha se queda pegado al valor de Send-Q - Se descarta si: Si ListenOverflows no cambia, no es esta causa. Si la conexión se establece pero la carga no termina: “Avalancha de inicios de sesión y consultas N+1”; si se bloquea justo al llegar a cierto número de jugadores: “Límite de descriptores de archivo” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · El backlog de listen se recorta en silencio si supera somaxconn; somaxconn es 4,096 por defecto (desde 5.4; antes, 128); con la cola llena, se pueden ignorar las solicitudes y dejar que el cliente reintente - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_syn_retries: la solicitud de conexión (SYN) se reenvía varias veces, con una primera espera de retransmisión de 1 segundo; tcp_abort_on_overflow, desactivado por defecto (no hay respuesta de rechazo aunque la cola se desborde); tcp_syncookies, activado por defecto - [listen function (winsock2.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen) · Microsoft · En Windows, cuando la cola está llena, el cliente recibe el error WSAECONNREFUSED - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtListenOverflows: veces que se descartó una solicitud de conexión (SYN) porque la cola de accept estaba llena; en ese caso, TcpExtListenDrops también sube - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q y Send-Q de ss: en un socket de escucha, conexiones esperando accept y límite del backlog; en un socket conectado, bytes que la aplicación aún no ha leído y bytes enviados que no han recibido ACK #### so-fd · Límite de descriptores de archivo · File descriptor limit (ulimit) Cada conexión necesita un descriptor de archivo (fd, el número que el SO asigna a cada archivo o socket abierto), y el número de fd que puede abrir un proceso es limitado. - Por qué → Efecto → En pantalla: Los jugadores conectados a la vez alcanzan el límite de descriptores de archivo del proceso → El servidor no puede aceptar conexiones nuevas (Too many open files). También falla la apertura de logs y de conexiones a la BD → A partir de un número exacto de jugadores ya nadie puede entrar: el juego no conecta o se queda en carga infinita - Síntomas: No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Todo el servidor / Cuándo: Al conectar o tras un mantenimiento, Cuando se junta mucha gente - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cerrar siempre el socket al terminar una conexión (para evitar fugas de fd); si accept falla con EMFILE (sin fd libres), dejar de aceptar conexiones un momento, o aceptar con un fd de reserva guardado de antemano y cerrar la conexión enseguida (para no gastar CPU procesando una y otra vez el mismo aviso de conexión). - Tareas (Equipo de infraestructura): Revisar ulimit y la configuración del servicio (LimitNOFILE de systemd), alertar cuando se acerque al límite. - Cifras de referencia: En Linux, si no se configura el servicio aparte, el límite sigue siendo 1,024 en muchos casos. Los servidores de juegos suelen subirlo a decenas o cientos de miles. Windows no tiene un límite predeterminado tan bajo. - En el gráfico: Topa con el límite (Número de fd abiertos del proceso, jugadores conectados a la vez) - Dónde mirar: fd-nr (descriptores de archivo abiertos) del proceso del servidor del juego con pidstat -v, el límite de archivos abiertos en /proc/PID/limits y fallos de accept (EMFILE, Too many open files) en los logs del servidor - Se confirma si: El número de fd se aplana en el valor del límite y, desde ese momento, accept falla con EMFILE - Se descarta si: Si el número de fd queda muy por debajo del límite, no es esta causa. Si el kernel descarta las solicitudes de conexión: “Desbordamiento de la cola de conexiones pendientes (backlog)”; si el problema está en el seguimiento de conexiones: “Tabla conntrack del servidor llena” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Las conexiones que no se aceptan se quedan en la cola de conexiones pendientes (backlog) del kernel, así que, según cómo esté escrito el código del servidor, este puede seguir recibiendo avisos de “conexión nueva” y gastar CPU en ellos. - Fuentes: - [systemd-system.conf(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd-system.conf.5.html) · systemd · El valor predeterminado de DefaultLimitNOFILE para los servicios es 1024:524288 (límite blando de 1,024) - [accept(2) — Linux manual page](https://man7.org/linux/man-pages/man2/accept.2.html) · Linux man-pages · Al alcanzar el límite de fd del proceso, accept falla con EMFILE - [Maximum Number of Sockets Supported](https://learn.microsoft.com/en-us/windows/win32/winsock/maximum-number-of-sockets-supported-2) · Microsoft · Winsock de Windows limita el número de sockets solo por la memoria disponible - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · fd-nr de -v: número de descriptores de archivo que tiene abiertos el proceso - [proc_pid_limits(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_pid_limits.5.html) · Linux man-pages · /proc/PID/limits muestra los valores blando y duro de los límites de recursos de cada proceso #### so-sockbuf · Búferes de socket del kernel insuficientes · Small socket buffers Si los búferes de envío y recepción son pequeños, cuando llega una ráfaga de tráfico se descartan paquetes recibidos por UDP y los envíos por TCP se bloquean porque no queda espacio en el búfer. - Por qué → Efecto → En pantalla: SO_SNDBUF y SO_RCVBUF con el valor predeterminado o demasiado pequeños → Durante una ráfaga, o mientras el hilo que recibe se detiene un momento, el búfer de recepción UDP se desborda y se descartan paquetes; en TCP, el envío espera porque no queda espacio en el búfer de envío → Teletransporte (pérdida en UDP) o cámara rápida (espera en TCP) - Síntomas: Teletransporte, Cámara rápida / Factores: Pérdida de paquetes, Detención - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Fijar en el código tamaños de búfer adecuados al tráfico (SO_SNDBUF y SO_RCVBUF); en TCP, tener en cuenta que fijar el tamaño a mano desactiva el ajuste automático de Linux; no pasarse con el tamaño, porque los datos viejos se acumulan en el búfer y aumenta la latencia; evitar que el hilo que recibe se detenga. - Tareas (Equipo de infraestructura): Ajustar los límites del kernel (rmem_max y wmem_max; los tamaños fijados en el código tampoco pueden superarlos) y el valor predeterminado (rmem_default), vigilar el contador de desbordamientos del búfer (RcvbufErrors). - Cifras de referencia: El búfer de recepción UDP de Linux es de unos 208 KB por defecto. Cada paquete, por pequeño que sea, ocupa en la memoria del kernel mucho más que su tamaño real, así que bastan decenas o cientos de paquetes para llenarlo. En un servidor que recibe 100,000 paquetes por segundo, basta con que el hilo que recibe se detenga unos pocos ms para que se desborde. - En el gráfico: Picos aleatorios (Desbordamientos del búfer de recepción UDP (UdpRcvbufErrors)) - Dónde mirar: Incremento de UdpRcvbufErrors en nstat -az y skmem en ss -uamn (rb es el tamaño del búfer de recepción; d, los paquetes descartados sin llegar al socket); en TCP, si en el skmem de ss -tm la memoria pendiente de envío (w) llega al tamaño del búfer de envío (tb) - Se confirma si: UdpRcvbufErrors (o la d del socket) sube en el momento de la ráfaga o de la detención del hilo que recibe, con rb cerca del valor predeterminado (unos 208 KB). En TCP, w pegado a tb y send bloqueado - Se descarta si: Si el contador no cambia pero hay pérdida, apunta a la NIC (“Búfer circular (ring buffer) insuficiente”) o a un tramo de la red - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [socket(7) — Linux manual page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux man-pages · Los valores predeterminados de SO_RCVBUF y SO_SNDBUF son rmem_default y wmem_default, y los límites, rmem_max y wmem_max; el kernel duplica el valor configurado - [include/net/sock.h (Linux v6.18)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/sock.h?h=v6.18) · Linux kernel · Define el búfer de socket predeterminado como 256 paquetes de 256 bytes con la sobrecarga de sk_buff incluida (SKB_TRUESIZE(256)×256); incluso una trama pequeña cuenta como sk_buff + MTU (la cifra de unos 208 KB es el valor calculado en x86-64) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rmem y tcp_wmem: si se fijan SO_RCVBUF o SO_SNDBUF a mano, se desactiva el ajuste automático de tamaño de ese socket - [net/ipv4/udp.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/udp.c?h=v6.12) · Linux kernel · Si la cola de recepción UDP supera el tamaño del búfer de socket, el paquete se descarta de inmediato y sube RcvbufErrors - [net/ipv4/proc.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nombres de contador que muestra nstat: RcvbufErrors y SndbufErrors del grupo Udp - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · skmem de -m: rb, tamaño del búfer de recepción; tb, tamaño del búfer de envío; w, memoria pendiente de envío; d, paquetes descartados antes de entrar en el socket #### so-context · Exceso de hilos y cambios de contexto · Thread oversubscription, context switching Si se ejecutan muchos más hilos que núcleos, el SO gasta CPU solo en irlos turnando. - Por qué → Efecto → En pantalla: Cientos o miles de hilos, por ejemplo uno por conexión → Aumentan el costo de los cambios de contexto (cambiar el hilo en ejecución) y los fallos de caché → La CPU está ocupada pero procesa poco y el tick se vuelve irregular: tirones y cámara lenta - Síntomas: Tirones, Cámara lenta / Factores: Detención, Jitter - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Ajustar el número de hilos al de núcleos, usar E/S asíncrona (epoll, IOCP). - Tareas (Equipo de infraestructura): Monitorear el número de cambios de contexto y de hilos esperando ejecución (cs y r de vmstat). - Cifras de referencia: Un cambio de contexto cuesta varios µs, y más si se suma el costo de los fallos de caché que vienen después. - En el gráfico: Sube con la carga (Cambios de contexto por segundo, hilos esperando ejecución) - Dónde mirar: cs (cambios de contexto por segundo) y r (procesos en ejecución o esperando CPU) de vmstat 1 frente al número de núcleos; cambios de contexto voluntarios (cswch/s) e involuntarios (nvcswch/s) por hilo del servidor del juego con pidstat -w -t - Se confirma si: Al subir los jugadores conectados, r sube muy por encima del número de núcleos, cs se dispara con él y hay cientos de hilos con muchos cambios de contexto involuntarios - Se descarta si: Si r se queda en el número de núcleos o por debajo, no es esta causa. Si solo abundan los cambios voluntarios, los hilos están esperando locks o E/S (“Contención de locks”, “Modelo de E/S bloqueante”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Quantifying The Cost of Context Switch (ExpCS 2007)](https://www.usenix.org/legacy/events/expcs07/papers/2-li.pdf) · ACM · Costo directo de un cambio de contexto: unos 3.8 µs; costo indirecto con el efecto en la caché: de varios µs a más de 1,000 µs (según el entorno de medición) - [vmstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/vmstat.8.html) · procps-ng · Campos cs (cambios de contexto por segundo) y r (procesos en ejecución o esperando para ejecutarse) - [I/O Completion Ports](https://learn.microsoft.com/en-us/windows/win32/fileio/i-o-completion-ports) · Microsoft · Procesar mucha E/S asíncrona con un pool de hilos creado de antemano e IOCP, y ajustar el número de hilos que corren a la vez a la concurrencia de la CPU - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · cswch/s de -w: cambios de contexto voluntarios (el hilo se detiene por sí mismo para esperar un recurso); nvcswch/s: cambios de contexto involuntarios (forzados al agotar su time slice); con -t, por hilo #### so-steal · CPU steal (máquinas virtuales) · CPU steal time Mientras el servidor físico (hipervisor) cede por un momento el tiempo de CPU de la máquina virtual a otra máquina virtual (CPU steal), el servidor del juego se detiene. - Por qué → Efecto → En pantalla: Otra máquina virtual del mismo host usa mucha CPU → Nuestra máquina virtual pierde turnos de ejecución de varios ms a decenas de ms cada vez → Picos de tiempo de tick sin causa aparente: tirones y congelamiento - Síntomas: Tirones, Congelamiento / Factores: Detención - A quién: Todo el servidor / Cuándo: De vez en cuando, al azar - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Externo (Externo) - Tareas (Equipo de infraestructura): Monitorear el indicador de steal (st de top y vmstat), usar núcleos u hosts dedicados, evitar las instancias de tipo ráfaga (burstable), que se ralentizan al agotar sus créditos de CPU, detener y volver a iniciar las instancias con steal alto sostenido para moverlas a otro host. - Tareas (Externo): Informar al proveedor de nube de los hosts con steal alto sostenido. - En el gráfico: Picos aleatorios (%steal, tiempo de tick del servidor) - Dónde mirar: %steal de mpstat -P ALL 1 en el mismo eje de tiempo que el tiempo de tick del servidor - Se confirma si: %steal sube a la vez que los picos de tick y baja al detener la instancia y volver a iniciarla en otro host - Se descarta si: Si %steal está cerca de 0 y aun así hay picos de tick, la causa está dentro del servidor del juego (“Pausa stop-the-world del GC en el servidor”, “Contención de locks”). En contenedores: “Throttling de CPU en contenedores (cuota de CFS)” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [proc_stat(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_stat.5.html) · Linux man-pages · steal: tiempo que se pierde en un entorno virtualizado mientras se ejecutan otros sistemas operativos - [Standard mode for burstable performance instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances-standard-mode.html) · AWS · Las instancias de tipo ráfaga superan su rendimiento base gastando créditos y, cuando se agotan, el uso de CPU baja al nivel base - [How EC2 instance stop and start works](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-ec2-instance-stop-start-works.html) · AWS · Al detener e iniciar una instancia, en la mayoría de los casos pasa a un host nuevo - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · %steal: porcentaje de tiempo que esta CPU virtual tuvo que esperar mientras el hipervisor atendía a otra CPU virtual #### so-cpu-quota · Throttling de CPU en contenedores (cuota de CFS) · Container CPU throttling (CFS quota) Si un contenedor tiene un límite de CPU, en cuanto agota su cuota dentro del periodo fijado (normalmente 100 ms), se detiene a la fuerza el resto del periodo (throttling). - Por qué → Efecto → En pantalla: El contenedor del servidor del juego tiene un límite de CPU (limit) en Kubernetes u otro orquestador → Cuando se acumula el cálculo del tick, agota la cuota y queda detenido decenas de ms hasta el siguiente periodo → La CPU media es baja, pero el tick tiene picos periódicos: tirones y cámara lenta - Síntomas: Tirones, Cámara lenta / Factores: Detención, Jitter - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente, De vez en cuando, al azar - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Ajustar el número de hilos de trabajo al límite de CPU (que el runtime no cree tantos hilos como núcleos tiene el host completo). - Tareas (Equipo de infraestructura): Dejar un límite de CPU holgado, o quitarlo y asignar núcleos dedicados, vigilar el número de veces con throttling (nr_throttled). - Cifras de referencia: En un servidor con un límite de 2 núcleos, si 8 hilos trabajan a la vez, agotan la cuota del periodo de 100 ms en 25 ms y quedan detenidos 75 ms. - En el gráfico: Sube con la carga (Veces con throttling (nr_throttled), tiempo de tick del servidor) - Dónde mirar: Incremento de nr_throttled y throttled_usec (en cgroup v1, nr_throttled y throttled_time) en cpu.stat del cgroup del contenedor, junto al tiempo de tick del servidor - Se confirma si: El uso medio de CPU está por debajo del límite, pero nr_throttled y throttled_usec no dejan de subir y coinciden con los picos de tick - Se descarta si: Si nr_throttled no sube, no es esta causa. Si la que se retrasa es la propia máquina virtual: “CPU steal (máquinas virtuales)” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [CFS Bandwidth Control](https://docs.kernel.org/scheduler/sched-bwc.html) · Linux kernel · Al agotar la cuota de cada periodo, los hilos se detienen hasta el siguiente (throttling); periodo predeterminado de 100 ms; estadística nr_throttled - [Control Group v2](https://docs.kernel.org/admin-guide/cgroup-v2.html) · Linux kernel · cpu.max tiene el formato “$MAX $PERIOD” (cuota, periodo) y su valor predeterminado es “max 100000” (periodo de 100 ms) - [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) · Kubernetes · El límite de CPU (limit) de un contenedor es un tope estricto que el kernel impone mediante throttling de CPU #### so-cstate · Picos de latencia por la gestión de energía del servidor (C-states, escalado de frecuencia) · CPU power management latency (C-states, frequency scaling) Los núcleos de CPU inactivos entran en estados de ahorro de energía profundos (C-states) y bajan su frecuencia para ahorrar electricidad. Cuando llega un paquete o vence un temporizador, despertar y subir la frecuencia lleva tiempo, y eso añade latencia al procesar paquetes pequeños. - Por qué → Efecto → En pantalla: La política de escalado de frecuencia del SO (governor) o la configuración de energía de la BIOS permiten C-states profundos y frecuencias bajas → Cada vez que un núcleo inactivo sale de un estado de ahorro profundo se retrasa hasta varios cientos de µs, y si la frecuencia se queda fijada baja, el propio cálculo del tick se vuelve lento → Casi siempre es imperceptible, pero con muchas llamadas entre servidores se acumula y aparece input lag, curiosamente cuando hay poca gente. Si la frecuencia se queda fijada baja, el tick se retrasa cuando se junta mucha gente: cámara lenta - Síntomas: Input lag, Cámara lenta / Factores: Latencia, Jitter, Detención - A quién: Todo el servidor / Cuándo: Siempre, De vez en cuando, al azar - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Poner la configuración de energía de la BIOS en modo rendimiento y el governor del SO en performance (scaling_governor de cpufreq), limitar los C-states profundos en los servidores sensibles a la latencia (perfil latency-performance de tuned, /dev/cpu_dma_latency de PM QoS, parámetro del kernel intel_idle.max_cstate), comparar después del cambio el tiempo de ida y vuelta dentro del centro de datos, el jitter del tiempo de tick y el consumo eléctrico. - Cifras de referencia: Según la tabla del driver intel_idle de Linux 6.12, en las CPU de servidor de Intel el C1 (poco profundo) tarda 1–2 µs en despertar, y el C6 (profundo), de 133 µs (Skylake-SP) a 290 µs (Sapphire Rapids). Cada vez es poco, pero si una solicitud pasa por varios servidores, se acumula. El kernel elige estados más profundos cuanto más largo prevé el tiempo inactivo, así que ocurre más a menudo en servidores con poca carga, donde los paquetes llegan espaciados. El governor powersave del cpufreq genérico fija la frecuencia más baja del rango permitido (el algoritmo del mismo nombre de intel_pstate la ajusta según la carga). - En el gráfico: Siempre alto (Tiempo de ida y vuelta dentro del mismo centro de datos, frecuencia de los núcleos) - Dónde mirar: Porcentaje de tiempo en cada C-state y frecuencia real por núcleo con cpupower monitor; name, latency (µs que tarda en despertar) y usage de cada state en /sys/devices/system/cpu/cpu0/cpuidle/; scaling_governor de cpufreq y el perfil actual con tuned-adm active - Se confirma si: Con poca carga, los núcleos pasan mucho tiempo en el C-state más profundo o la frecuencia se queda fijada cerca del mínimo, y al pasar al governor performance con C-states poco profundos bajan el tiempo de ida y vuelta y el jitter de las solicitudes pequeñas - Se descarta si: Si al cambiarlo la diferencia es de unas decenas de µs o menos, se puede ignorar esta causa. Si los picos son del orden de ms: “CPU steal (máquinas virtuales)” u otra capa - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: En los servidores bare metal del centro de datos hay que revisar a la vez la configuración de energía de la BIOS (firmware) y la del SO. En la nube, el SO solo puede cambiar los C-states y la frecuencia en algunos tipos de instancia, y en AWS la configuración predeterminada prioriza el máximo rendimiento, así que casi siempre se puede dejar como está. El perfil latency-performance de tuned, de la familia Red Hat, pone el governor en performance y, con PM QoS, limita el uso a C-states poco profundos. Desactivar el ahorro de energía aumenta el consumo eléctrico, así que solo conviene hacerlo en los servidores sensibles a la latencia. - Fuentes: - [CPU Idle Time Management](https://docs.kernel.org/admin-guide/pm/cpuidle.html) · Linux kernel · Cada estado de ahorro tiene un tiempo de salida (exit latency) y un tiempo mínimo de permanencia (target residency), y el estado profundo se elige según el tiempo inactivo previsto; latency, usage y time por state en sysfs; limitar los estados profundos con PM QoS (/dev/cpu_dma_latency) e intel_idle.max_cstate - [drivers/idle/intel_idle.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/idle/intel_idle.c?h=v6.12) · Linux kernel · Tiempo de salida por C-state en CPU de servidor de Intel: Skylake-SP C1 2 µs, C1E 10 µs, C6 133 µs; Ice Lake C6 170 µs; Sapphire Rapids C1 1 µs, C6 290 µs - [CPU Performance Scaling](https://docs.kernel.org/admin-guide/pm/cpufreq.html) · Linux kernel · Consultar y cambiar el governor con scaling_governor; performance pide la frecuencia más alta del rango permitido y powersave, la más baja - [intel_pstate CPU Performance Scaling Driver](https://docs.kernel.org/admin-guide/pm/intel_pstate.html) · Linux kernel · El algoritmo powersave de intel_pstate, a diferencia del governor powersave genérico, ajusta la frecuencia según la carga (parecido a schedutil y ondemand) - [Chapter 2. Getting started with TuneD](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/monitoring_and_managing_system_status_and_performance/getting-started-with-tuned_monitoring-and-managing-system-status-and-performance) · Red Hat · El perfil latency-performance desactiva las funciones de ahorro de energía, pone el governor en performance y, con PM QoS, limita el uso a C-states poco profundos; consultar el perfil actual con tuned-adm active - [tools/power/cpupower/man/cpupower-monitor.1 (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/power/cpupower/man/cpupower-monitor.1?h=v6.12) · Linux kernel · cpupower monitor: estadísticas de frecuencia y de estados de ahorro por núcleo - [Processor state control for Amazon EC2 Linux instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/processor_state_control.html) · AWS · Solo en algunos tipos de instancia el SO puede controlar los C-states y P-states, y se pueden cambiar para reducir la latencia; la configuración predeterminada es de máximo rendimiento, adecuada para la mayoría de las cargas; Graviton tiene frecuencia fija y el SO no la controla #### so-oom · OOM killer · Out-of-memory killer Cuando Linux se queda sin memoria, elige el proceso que más memoria usa y lo mata a la fuerza. Casi siempre es el servidor del juego. - Por qué → Efecto → En pantalla: Memoria agotada por una fuga o un pico de uso, o límite de memoria del contenedor alcanzado → El kernel cierra a la fuerza el proceso del servidor del juego → Desconexión simultánea de todos los jugadores de ese servidor, con posible rollback del progreso reciente - Síntomas: Desconexión, Acción perdida / rollback / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuanto más tiempo lleva encendido, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Corregir las fugas, fijar un tope de uso de memoria y un procedimiento que guarde y cierre el servidor de forma ordenada al acercarse a él. - Tareas (Equipo de infraestructura): Configurar alertas de memoria, ajustar el límite de memoria del contenedor al uso real, ajustar el orden en que se matan los procesos (oom_score_adj). - Cifras de referencia: En el log del kernel (dmesg) queda “Out of memory: Killed process”, y en Kubernetes se ve como OOMKilled. Windows no tiene OOM killer; muchas veces la asignación de memoria falla y el servidor se cae con un error. - En el gráfico: Desconexión masiva (Número de conexiones, uso de memoria) - Dónde mirar: Registro “Out of memory: Killed process” en dmesg; en Kubernetes, OOMKilled en el estado del pod; en cgroup v2, aumento de oom_kill en memory.events; todo cruzado con la hora de las desconexiones - Se confirma si: A la hora de la desconexión masiva hay un registro de que se mató el proceso del servidor del juego, y hasta justo antes el uso de memoria subió hasta el límite - Se descarta si: Si no hay registro de OOM pero el proceso murió, revisar los logs de crash y el core dump (ver “Crash del servidor”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [mm/oom_kill.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/oom_kill.c?h=v6.12) · Linux kernel · El cálculo da la puntuación más alta al proceso que más memoria usa (teniendo en cuenta oom_score_adj); al matarlo se registra “Out of memory: Killed process …” - [Assign Memory Resources to Containers and Pods](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/) · Kubernetes · Si un contenedor sigue usando memoria por encima de su límite (limit), se termina y su estado aparece como OOMKilled - [Pushing the Limits of Windows: Virtual Memory](https://learn.microsoft.com/en-us/archive/blogs/markrussinovich/pushing-the-limits-of-windows-virtual-memory) · Microsoft · En Windows, al alcanzar el límite de confirmación (commit limit), fallan las asignaciones que confirman memoria, lo que puede provocar errores en las aplicaciones o fallos del sistema - [Control Group v2](https://docs.kernel.org/admin-guide/cgroup-v2.html) · Linux kernel · oom_kill de memory.events: número de procesos que el OOM killer mató en este cgroup #### so-reclaim · Pausas por recuperación y compactación de memoria · Memory compaction / reclaim stalls (THP) Mientras el SO compacta la memoria para formar páginas grandes (huge pages) o recupera memoria libre, el proceso se detiene. - Por qué → Efecto → En pantalla: Baja la memoria libre, o la función de páginas grandes (THP) ejecuta una compactación de memoria → El hilo que pidió memoria espera hasta que terminan la recuperación y la compactación → Detenciones irregulares del servidor (de varios ms a cientos de ms) - Síntomas: Congelamiento, Tirones / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuanto más tiempo lleva encendido, De vez en cuando, al azar - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Reducir las asignaciones grandes de memoria durante la ejecución (reservar la memoria al arrancar y reutilizarla). - Tareas (Equipo de infraestructura): Configurar las páginas grandes (THP) para que solo se usen donde hacen falta (madvise), subir el umbral de memoria libre (vm.min_free_kbytes, entre otros). - En el gráfico: Picos aleatorios (Tiempo de tick del servidor, PSI de memoria) - Dónde mirar: some y full de /proc/pressure/memory (porcentaje de tiempo detenido esperando memoria) e incremento de compact_stall en /proc/vmstat, junto al tiempo de tick del servidor; revisar la configuración de /sys/kernel/mm/transparent_hugepage/defrag - Se confirma si: En los picos de tick sube el PSI de memoria y aumenta compact_stall. defrag en always - Se descarta si: Si el PSI y compact_stall no cambian, no es esta causa. Si aumenta el uso de swap: “Swap” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Transparent Hugepage Support](https://docs.kernel.org/admin-guide/mm/transhuge.html) · Linux kernel · Con defrag=always, cuando falla una asignación THP, se recupera y compacta memoria en ese mismo momento y el proceso se detiene; con madvise, solo en las regiones que lo piden - [Documentation for /proc/sys/vm/](https://docs.kernel.org/admin-guide/sysctl/vm.html) · Linux kernel · min_free_kbytes: memoria libre mínima que el kernel mantiene en reserva (marca de agua) - [PSI - Pressure Stall Information](https://docs.kernel.org/accounting/psi.html) · Linux kernel · some (porcentaje de tiempo en que algunas tareas estuvieron detenidas esperando memoria) y full (porcentaje de tiempo en que todas estuvieron detenidas) de /proc/pressure/memory #### so-timejump · Salto del reloj del sistema (step de NTP) · Wall-clock jump (NTP step) Si el reloj del servidor se adelanta o se atrasa varios segundos de golpe, los temporizadores que dependen del reloj del sistema se disparan todos a la vez o se detienen. - Por qué → Efecto → En pantalla: La sincronización horaria corrige el reloj con un salto grande de una sola vez → Los temporizadores se disparan en tropel o se detienen, y los timeouts se evalúan mal → Buffs y cooldowns que fallan, desconexiones simultáneas, cámara rápida - Síntomas: Cámara rápida, Desconexión, Acción perdida / rollback / Factores: Detención - A quién: Todo el servidor / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Calcular el tiempo transcurrido, los timeouts y los cooldowns con un reloj monotónico (monotonic clock), que no salta ni retrocede, usar el reloj de pared (wall clock) solo para mostrar y registrar. - Tareas (Equipo de infraestructura): Ajustar el reloj poco a poco (makestep de chrony solo justo después de arrancar), monitorear el estado de la sincronización horaria (desfase del reloj). - Cifras de referencia: ntpd corrige el reloj de una sola vez si la diferencia supera 0.128 segundos; si es menor, lo ajusta poco a poco, a un ritmo que tarda algo más de 30 minutos en eliminar 1 segundo de diferencia. chrony, muy usado hoy, con la configuración recomendada (makestep) solo corrige de golpe unas pocas veces justo después de arrancar, y después ajusta poco a poco. El reloj también salta cuando una máquina virtual se detiene un momento y se reanuda. - En el gráfico: Picos aleatorios (Temporizadores disparados y desconexiones, registro de ajustes del reloj) - Dónde mirar: Registros de ajustes grandes de una sola vez en los logs del servicio de sincronización horaria, cruzados con la hora del problema. chrony deja constancia en syslog cuando el ajuste supera el valor de logchange (1 segundo por defecto) - Se confirma si: Hay un registro de ajuste del reloj a la hora de los fallos de buffs y cooldowns, las desconexiones simultáneas o la cámara rápida, y el tamaño del ajuste se parece a la magnitud del problema - Se descarta si: Si no hay registros de ajuste del reloj, no es esta causa. En máquinas virtuales, revisar también si se detuvo y se reanudó (“Mantenimiento del host en la nube y migración en vivo”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [ntpd - Network Time Protocol (NTP) daemon](https://www.ntp.org/documentation/4.2.8-series/ntpd/) · Network Time Foundation · Si la diferencia supera el umbral de step de 128 ms, se corrige de una vez; si es menor, poco a poco, a 0.5 ms por segundo, así que corregir 1 segundo lleva 2,000 segundos (unos 33 minutos) - [chrony – Frequently Asked Questions](https://chrony-project.org/faq.html) · chrony · Se recomienda permitir el step solo unas pocas veces justo después de arrancar, como makestep 1 3; una máquina virtual que se detuvo y se reanudó puede despertar con la hora desfasada - [clock_gettime(2) — Linux manual page](https://man7.org/linux/man-pages/man2/clock_gettime.2.html) · Linux man-pages · CLOCK_MONOTONIC no se ve afectado por los saltos discontinuos del reloj del sistema y no retrocede - [chrony.conf(5)](https://chrony-project.org/doc/4.6/chrony.conf.html) · chrony · logchange: si el reloj se ajusta más que este valor (1 segundo por defecto), se registra en syslog #### so-cron · Tareas programadas · Cron jobs (log rotation, backup, scans) La compresión de logs, las copias de seguridad y los análisis de seguridad que se ejecutan todos los días a la misma hora ocupan la CPU y el disco. - Por qué → Efecto → En pantalla: Una tarea del SO se ejecuta a una hora fijada → Comparte la CPU y el disco con el servidor del juego → Tirones y cámara lenta a una hora fija, por ejemplo todos los días a las 4 de la madrugada - Síntomas: Tirones, Cámara lenta / Factores: Detención - A quién: Todo el servidor / Cuándo: A intervalos regulares - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Repartir las horas de las tareas, bajarles la prioridad (nice, ionice), separarlas del servidor del juego (ejecutarlas en otro servidor). - En el gráfico: Picos periódicos (Uso de CPU, cola del disco, tiempo de tick del servidor) - Dónde mirar: Horas de ejecución de las tareas programadas con crontab y systemctl list-timers; en los picos de tick, qué procesos usan CPU y disco con pidstat -u -d - Se confirma si: El tick tiene picos todos los días (o cada hora) a la misma hora, y en ese momento el proceso de una tarea programada ocupa la CPU y el disco - Se descarta si: Si los picos no coinciden con una hora fija diaria, no es esta causa. Si se repiten cada pocos segundos o minutos: “Pausa stop-the-world del GC en el servidor”, “Temporizadores que se disparan todos a la vez” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [ionice(1) — Linux manual page](https://man7.org/linux/man-pages/man1/ionice.1.html) · util-linux · Las tareas de la clase idle solo reciben E/S cuando ningún otro programa usa el disco - [systemd.timer(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd.timer.5.html) · systemd · RandomizedDelaySec retrasa al azar la hora de las tareas programadas para evitar que la carga se concentre - [systemctl(1) — Linux manual page](https://man7.org/linux/man-pages/man1/systemctl.1.html) · systemd · list-timers: muestra las unidades timer ordenadas por su próxima ejecución - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -u muestra la CPU y -d la E/S de disco por proceso #### so-os-update · Cambios de rendimiento tras actualizar el SO, el kernel, los drivers o el firmware · Performance regression after OS / kernel / driver / firmware update El código del juego no cambia, pero el servidor se vuelve más lento después de actualizar el SO, el kernel, los drivers o el firmware. Las actualizaciones pueden cambiar valores predeterminados, el planificador, las mitigaciones de vulnerabilidades de la CPU (mitigations) o el comportamiento de los drivers. - Por qué → Efecto → En pantalla: Un parche de seguridad periódico o una imagen de servidor nueva cambia el kernel, los drivers o el firmware → Cambian los valores predeterminados o el planificador, o se activan nuevas mitigaciones: el mismo trabajo consume más tiempo de CPU y cambia el orden en que los hilos reciben CPU → Un servidor que iba bien va siempre un poco más lento desde el día de la actualización: input lag y, cuando se junta mucha gente, tirones y cámara lenta - Síntomas: Input lag, Tirones, Cámara lenta / Factores: Latencia, Detención, Jitter - A quién: Todo el servidor / Cuándo: Siempre, Cuando se junta mucha gente - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Aplicar las actualizaciones primero en algunos servidores y comparar el tiempo de tick, la latencia y el uso de CPU con la versión anterior antes de extenderlas, desplegarlas en un día distinto al de los parches del juego, registrar antes y después de actualizar las versiones del kernel, los drivers y el firmware y los valores sysctl principales, arrancar con el kernel anterior para comprobarlo si surge un problema, decidir si se desactivan las mitigaciones (mitigations=off) sopesando el riesgo de seguridad. - Cifras de referencia: Al cambiar de versión del kernel cambia también el comportamiento predeterminado. Por ejemplo, Linux empezó a pasar del planificador CFS a EEVDF a partir de la 6.6, y el valor predeterminado del límite de la cola de conexiones pendientes (somaxconn) pasó de 128 a 4,096 desde la 5.4. Las mitigaciones de vulnerabilidades de la CPU añaden trabajo, como vaciar búferes internos de la CPU al volver del kernel al programa (al terminar cada llamada al sistema) y en los cambios de contexto y de máquina virtual, así que afectan más a los servidores de red que hacen una llamada al sistema por paquete. Para cerrar del todo algunas vulnerabilidades hay que desactivar SMT (la función que hace que un núcleo funcione como dos hilos), y sin SMT el rendimiento puede caer mucho según la carga de trabajo. El parámetro del kernel mitigations=off desactiva todas estas mitigaciones y recupera el rendimiento, pero deja el sistema expuesto a las vulnerabilidades. - En el gráfico: Salto en escalón (Tiempo de tick del servidor, uso de CPU, latencia con la misma carga) - Dónde mirar: Historial de actualizaciones del gestor de paquetes y hora del reinicio, versión del kernel con uname -r y datos del driver de la NIC con ethtool -i, cruzados con la hora en que subió la latencia. Comparar con mpstat y pidstat un servidor actualizado y otro sin actualizar con la misma carga, y también el estado de las mitigaciones en /sys/devices/system/cpu/vulnerabilities/ - Se confirma si: La latencia y el uso de CPU suben un escalón desde el reinicio tras la actualización y se quedan ahí, y con la misma carga solo están altos los servidores actualizados. Al arrancar con el kernel o el driver anterior, vuelven a la normalidad - Se descarta si: Si los servidores actualizados y los no actualizados van igual de lentos con la misma carga, no es esta causa. Si el mismo día también se desplegó un parche del juego y cambiaron el número o el tamaño de los paquetes por jugador: “Cambio del patrón de tráfico tras un parche” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: El estado de las mitigaciones se consulta en los archivos de /sys/devices/system/cpu/vulnerabilities/. El valor predeterminado (mitigations=auto) aplica las mitigaciones con SMT activado, pero con auto,nosmt se desactiva SMT en las CPU vulnerables, así que, tras actualizar el kernel, el número de núcleos lógicos puede quedar a la mitad. Si se actualiza el SO el mismo día que sale un parche del juego, cuesta distinguir la causa, así que conviene desplegarlos por separado. - Fuentes: - [The kernel’s command-line parameters](https://docs.kernel.org/admin-guide/kernel-parameters.html) · Linux kernel · mitigations=: off desactiva todas las mitigaciones de vulnerabilidades de la CPU y mejora el rendimiento, pero deja el sistema expuesto; el predeterminado, auto, aplica las mitigaciones con SMT activado; auto,nosmt desactiva SMT si hace falta - [MDS - Microarchitectural Data Sampling](https://docs.kernel.org/admin-guide/hw-vuln/mds.html) · Linux kernel · Las mitigaciones vacían búferes de la CPU al volver del kernel al espacio de usuario y al entrar en una máquina virtual; el estado de las vulnerabilidades y mitigaciones se consulta en los archivos de /sys/devices/system/cpu/vulnerabilities/; en muchas CPU, cerrar del todo la vulnerabilidad exige desactivar SMT, y sin SMT el impacto en el rendimiento es grande según la carga de trabajo - [Spectre Side Channels](https://docs.kernel.org/admin-guide/hw-vuln/spectre.html) · Linux kernel · Como mitigación, se vacían los búferes de predicción de saltos en los cambios de contexto y de máquina virtual, y las mitigaciones más fuertes añaden sobrecarga a todos los programas - [EEVDF Scheduler](https://docs.kernel.org/scheduler/sched-eevdf.html) · Linux kernel · Linux empezó a pasar del planificador CFS a EEVDF a partir de la 6.6 - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · El valor predeterminado de somaxconn pasó de 128 a 4,096 desde Linux 5.4 - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Consultar los datos del driver de un dispositivo de red con ethtool -i #### so-conntrack · Tabla conntrack del servidor llena · conntrack table full Cuando la tabla de seguimiento de conexiones (conntrack), donde el firewall de Linux registra todas las conexiones, llega a su límite, se descartan paquetes nuevos. - Por qué → Efecto → En pantalla: Una avalancha de conexiones o conexiones cortas repetidas multiplican las entradas de seguimiento → La tabla se llena y se descartan conexiones nuevas y algunos paquetes → El juego no conecta, y la pérdida de paquetes sin causa aparente provoca teletransporte - Síntomas: No conecta / carga infinita, Teletransporte / Factores: Pérdida de paquetes - A quién: Todo el servidor / Cuándo: Al conectar o tras un mantenimiento, Cuando se junta mucha gente - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: reducir las conexiones cortas (reutilizar conexiones en las llamadas entre servidores). Cliente: si la conexión falla o se corta, reintentar con intervalos crecientes y repartidos al azar. - Tareas (Equipo de infraestructura): Aumentar el tamaño de la tabla (nf_conntrack_max), excluir del seguimiento los puertos del juego (NOTRACK en la tabla raw), alertar sobre el uso. - Cifras de referencia: El límite predeterminado va de unas 60,000 a unas 260,000 entradas según la memoria del servidor. Si se desborda, en el log del kernel aparece “nf_conntrack: table full, dropping packet”. - En el gráfico: Topa con el límite (Entradas de conntrack (nf_conntrack_count)) - Dónde mirar: net.netfilter.nf_conntrack_count (entradas actuales) de sysctl en el mismo gráfico que nf_conntrack_max; buscar “nf_conntrack: table full, dropping packet” en dmesg - Se confirma si: nf_conntrack_count se aplana en el máximo y, desde ese momento, aparece table full en el log del kernel - Se descarta si: Si las entradas quedan muy por debajo del máximo, no es esta causa. El límite de seguimiento de conexiones de la propia instancia de AWS se mira con conntrack_allowance_exceeded (ver “Límite de PPS de la nube superado”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · El valor predeterminado de nf_conntrack_max es igual al número de buckets del hash (nf_conntrack_buckets), que depende del tamaño de la memoria - [net/netfilter/nf_conntrack_core.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_conntrack_core.c?h=v6.12) · Linux kernel · Tamaño predeterminado: 65,536 con más de 1 GB de memoria y 262,144 con más de 4 GB (64 bits); al llenarse, registra “nf_conntrack: table full, dropping packet” y descarta - [iptables-extensions(8) — Linux manual page](https://man7.org/linux/man-pages/man8/iptables-extensions.8.html) · netfilter · Excluir del seguimiento de conexiones con CT --notrack en la tabla raw #### so-ports · Agotamiento de puertos efímeros en conexiones entre servidores · Ephemeral port exhaustion (TIME_WAIT) Si el servidor del juego abre y cierra conexiones cortas con frecuencia hacia la BD u otros servidores, las conexiones cerradas siguen ocupando su puerto un tiempo y no se pueden abrir conexiones nuevas. - Por qué → Efecto → En pantalla: Se abre y se cierra una conexión nueva en cada solicitud → El lado que cierra primero retiene el puerto unos 60 segundos (en Linux) en TIME_WAIT, y se agotan los puertos disponibles → Fallan solicitudes internas: errores al guardar y en otras funciones - Síntomas: Acción perdida / rollback, No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Todo el servidor, Solo una función / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Reutilizar conexiones (pool de conexiones), no abrir y cerrar una conexión nueva en cada solicitud. - Tareas (Equipo de infraestructura): Ampliar el rango de puertos (ip_local_port_range), evaluar la reutilización de TIME_WAIT en las conexiones salientes (tcp_tw_reuse de Linux), vigilar el número de TIME_WAIT. - Cifras de referencia: El rango de puertos predeterminado de Linux (32768–60999) tiene unos 28,000 puertos. Se agota si se abren más de 470 conexiones nuevas por segundo hacia la misma dirección de destino. Windows tiene unos 16,000 puertos por defecto (49152–65535) y un TIME_WAIT más largo, así que se agota antes. - En el gráfico: Topa con el límite (Sockets en TIME_WAIT, fallos de conexiones internas) - Dónde mirar: Sockets en TIME_WAIT por dirección de destino con ss -tan state time-wait; fallos de connect (EADDRNOTAVAIL) en los logs del servidor del juego - Se confirma si: Los TIME_WAIT hacia un mismo destino (la BD, por ejemplo) se aplanan cerca del tamaño del rango de puertos efímeros (unos 28,000 por defecto) y connect falla con EADDRNOTAVAIL - Se descarta si: Si hay pocos TIME_WAIT y solo fallan las conexiones hacia el exterior: “Límites de conexiones y puertos del gateway NAT en la nube” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Los 60 segundos de TIME_WAIT en Linux son un valor fijo del kernel. Reducir tcp_fin_timeout, de nombre parecido, no acorta TIME_WAIT. - Fuentes: - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · ip_local_port_range predeterminado: 32768–60999; tcp_tw_reuse; tcp_fin_timeout es el tiempo que se mantiene el estado FIN_WAIT_2 - [include/net/tcp.h (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · TCP_TIMEWAIT_LEN (60*HZ): TIME_WAIT, de unos 60 segundos, es una constante del kernel - [TCP/IP port exhaustion troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/tcp-ip-port-exhaustion-troubleshooting) · Microsoft · Rango de puertos dinámicos predeterminado de Windows: 49152–65535; una conexión cerrada retiene el puerto en TIME_WAIT 4 minutos por defecto - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · Ver solo los sockets en TIME_WAIT con el filtro de estado state time-wait - [connect(2) — Linux manual page](https://man7.org/linux/man-pages/man2/connect.2.html) · Linux man-pages · EADDRNOTAVAIL: no se puede abrir la conexión porque todos los puertos del rango efímero están en uso ### L8 Sockets y protocolos (causas: 14) #### sk-hol · Bloqueo HOL en TCP · Head-of-line blocking Para mantener el orden, TCP no entrega al juego los paquetes que llegaron después de uno perdido hasta que vuelve a recibir ese paquete. - Por qué → Efecto → En pantalla: Se pierde un paquete → Los paquetes siguientes ya llegaron, pero esperan en el búfer de recepción → Congelamiento y después todo se libera de golpe: cámara rápida - Síntomas: Congelamiento, Cámara rápida / Factores: Pérdida de paquetes, Detención - A quién: Solo yo / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: usar UDP para las posiciones en tiempo real, enviar de forma confiable solo lo imprescindible, repartir el tráfico en varios flujos (streams). Cliente: cambiar el código de red para usar el mismo modelo que el servidor (UDP, canales separados). - Cifras de referencia: Perder un paquete detiene todo como mínimo un tiempo de ida y vuelta más algo de margen; si también se pierde la retransmisión, de cientos de ms a varios segundos. - En el gráfico: Hueco y luego ráfaga (Datos recibidos por conexión, retransmisiones) - Dónde mirar: Captura de paquetes en el servidor (tcpdump, Wireshark) para ver, en la conexión de ese jugador, los paquetes retransmitidos y los huecos antes y después; para todo el servidor, incremento de TcpRetransSegs en nstat -az - Se confirma si: El tramo detenido empieza con la retransmisión de un paquete y, justo después de que llega, los datos acumulados se procesan de golpe (lo recibido se queda en 0 y luego llega todo junto) - Se descarta si: No aplica si el juego se comunica por UDP. Si se detiene sin retransmisiones, revisar el tick del servidor (“Tick que excede su presupuesto”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · TCP es un servicio de flujo de bytes confiable y en orden - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Detecta la pérdida con 3 ACK duplicados y hace una retransmisión rápida; si no, espera al temporizador de retransmisión - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · Backoff que duplica el temporizador de retransmisión cada vez que expira - [net/ipv4/proc.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nombres de contador que muestra nstat: RetransSegs (segmentos retransmitidos) del grupo Tcp #### sk-rto · RTO de TCP y backoff exponencial · RTO and exponential backoff Cada vez que una retransmisión vuelve a fallar, la espera se duplica, así que un corte breve de la conexión se convierte en una detención larga. - Por qué → Efecto → En pantalla: La conexión se corta un momento y las retransmisiones también fallan una tras otra → La espera hasta el siguiente intento se duplica cada vez: 0.3 → 0.6 → 1.2 → 2.4 s (con un ping de 100 ms) → La conexión se cortó 1 segundo, pero el juego se congela más de 2. Si el corte dura más, acaba en desconexión - Síntomas: Congelamiento, Desconexión / Factores: Pérdida de paquetes, Detención - A quién: Solo yo / Cuándo: De vez en cuando, al azar, Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: responder a los heartbeats y cerrar la conexión por su cuenta si no los recibe durante cierto tiempo (adelantar el abandono con TCP_USER_TIMEOUT), retomar la sesión con un token de sesión, usar UDP confiable. Cliente: enviar heartbeats a intervalos cortos y, si dejan de llegar respuestas, reconectar enseguida sin esperar a la retransmisión TCP. - Cifras de referencia: En Linux, el RTO (tiempo de espera antes de retransmitir) tiene como mínimo “ping + 200 ms” y, al establecer la conexión, empieza en 1 segundo. Con la configuración predeterminada (tcp_retries2=15), aunque las retransmisiones sigan fallando, la conexión no se abandona hasta pasados unos 15 minutos. - En el gráfico: Hueco y luego ráfaga (RTO y backoff por conexión, expiraciones del RTO) - Dónde mirar: rto (espera de retransmisión en ms) y backoff (expiraciones seguidas) de la conexión detenida con ss -ti; para todo el servidor, incremento de TcpExtTCPTimeouts (expiraciones del temporizador de retransmisión) en nstat -az - Se confirma si: La conexión detenida tiene un backoff de 1 o más y un rto que ha crecido al orden de segundos, y TCPTimeouts sube a esa hora - Se descarta si: Si las retransmisiones se resuelven con retransmisión rápida y no hay expiraciones del RTO, la detención es corta. En ese caso: “Bloqueo HOL en TCP” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · RTO inicial de 1 segundo; cada vez que el temporizador expira, el RTO se duplica (backoff exponencial) - [net/ipv4/tcp_input.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_input.c?h=v6.12) · Linux kernel · En Linux, RTO = RTT suavizado + variación del RTT, y el mínimo de la variación es tcp_rto_min (200 ms), así que el RTO es al menos RTT + 200 ms - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us predeterminado: 200 ms; RTO inicial de la solicitud de conexión: 1 segundo; con tcp_retries2=15, al menos 924.6 segundos (unos 15 minutos) hasta abandonar - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rto (temporizador de retransmisión, en ms) y backoff (número de backoffs exponenciales) de -i - [net/ipv4/proc.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nombres de contador que muestra nstat: TCPTimeouts del grupo TcpExt - [net/ipv4/tcp_timer.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · Cada vez que expira el temporizador de retransmisión, sube TCPTimeouts, backoff aumenta en uno y el RTO se duplica (hasta el máximo) #### sk-nagle · Algoritmo de Nagle + ACK retardado · Nagle + delayed ACK (TCP_NODELAY off) El algoritmo de Nagle, que junta paquetes pequeños antes de enviarlos, y el ACK retardado, que envía los ACK con retraso, se bloquean mutuamente, y cada mensaje escrito en varias partes se retrasa entre 40 y 200 ms. - Por qué → Efecto → En pantalla: Se escriben mensajes pequeños en varias partes sin activar TCP_NODELAY → El emisor espera el ACK y el receptor lo envía tarde → Input lag constante en todas las acciones aunque el ping de la conexión sea bajo - Síntomas: Input lag / Factores: Latencia - A quién: Todo el servidor, Solo yo / Cuándo: Siempre, Al hacer ciertas acciones - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: activar TCP_NODELAY, juntar los mensajes de un tick y escribirlos de una vez, no depender de desactivar el ACK retardado en el receptor (TCP_QUICKACK de Linux solo dura un momento y en Windows hay que modificar el registro en cada PC), porque el juego no puede controlarlo con seguridad. Cliente: activar TCP_NODELAY, juntar los mensajes de un frame y escribirlos de una vez. - Cifras de referencia: En Linux, el ACK retardado suele ser de 40 ms (hasta 200 ms según la situación). En Windows, las versiones antiguas usaban 200 ms y las actuales, 40 ms (la plantilla predeterminada de Windows Server 2019 usa 40 ms). Como el ACK retardado lo decide el SO del receptor, si el servidor envía los mensajes en partes con Nagle activado, cada mensaje puede retrasarse entre 40 y 200 ms según el sistema que lo recibe. - En el gráfico: Siempre alto (Tiempo de respuesta a las acciones (RTT dentro del juego)) - Dónde mirar: Intervalo entre solicitud y respuesta en una captura de paquetes en el servidor (tcpdump, Wireshark); comprobar si el código del servidor y del cliente activa TCP_NODELAY - Se confirma si: Con un ping bajo, se repiten huecos de unos 40 ms (200 ms en versiones antiguas de Windows) entre paquetes pequeños, y cada hueco termina justo después de llegar el ACK del otro extremo. Desaparecen al activar TCP_NODELAY - Se descarta si: Si el intervalo de respuesta se parece al ping de la conexión, no es esta causa. Si el servidor del juego tarda en generar la respuesta, apunta al procesamiento del servidor (“Acumulación en la cola de mensajes”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · Nagle retiene los datos pequeños mientras haya datos sin ACK; debe poder desactivarse por conexión; el ACK retardado debe ser menor de 0.5 segundos; el problema de que ambos se bloqueen mutuamente - [include/net/tcp.h (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · ACK retardado en Linux: mínimo TCP_DELACK_MIN (HZ/25 = 40 ms), máximo TCP_DELACK_MAX (HZ/5 = 200 ms) - [TCP improvements in the Windows network stack (IETF 98 TCPM)](https://datatracker.ietf.org/meeting/98/materials/slides-98-tcpm-tcp-improvements-in-windows-01) · Microsoft · Cambio del timeout predeterminado del ACK retardado de Windows a 40 ms (anunciado en 2017) - [TCP Templates for Windows Server 2019 – How to tune your Windows Server Transports (Advanced users only 😉)](https://techcommunity.microsoft.com/blog/networkingblog/tcp-templates-for-windows-server-2019-8211-how-to-tune-your-windows-server-trans/339795) · Microsoft · Plantilla de Server 2019: DelayedAckTimeout 40 ms, MaxSynRetransmissions 2, InitialRto 3,000 ms - [Design issues - Sending small data segments over TCP with Winsock](https://learn.microsoft.com/en-us/previous-versions/troubleshoot/windows/win32/data-segment-tcp-winsock) · Microsoft · En el TCP de las versiones antiguas de Windows, al recibir datos se activa un temporizador de ACK retardado de 200 ms y Nagle viene activado por defecto, así que los paquetes pequeños esperan al ACK; se resuelve con TCP_NODELAY #### sk-block-send · Envíos bloqueantes por clientes lentos · Blocking send on a full socket Si el búfer de envío de un jugador con una conexión lenta está lleno y se le envía en modo bloqueante (un envío cuya llamada no vuelve hasta que hay espacio en el búfer), el hilo del servidor se queda esperando a ese único jugador. - Por qué → Efecto → En pantalla: El búfer de envío de un cliente lento está lleno → Como el envío es bloqueante, el hilo del servidor espera hasta que haya espacio en el búfer → Congelamiento o cámara lenta para todos los jugadores que atiende ese hilo - Síntomas: Congelamiento, Cámara lenta / Factores: Detención - A quién: Una zona o un canal, Todo el servidor / Cuándo: De vez en cuando, al azar, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Usar envío no bloqueante, poner un tope a la cola de envío de cada cliente, descartar las actualizaciones viejas. - En el gráfico: Picos aleatorios (Tiempo de tick del servidor, Send-Q por conexión) - Dónde mirar: Conexiones cuyo Send-Q (bytes sin ACK o aún sin enviar) llena el búfer de envío, con ss -tn; en el momento del pico de tick, si el volcado de hilos (pilas) del servidor del juego muestra hilos detenidos en una llamada a send - Se confirma si: Cuando hay una conexión lenta con el Send-Q lleno, el hilo que la atiende está detenido en send y solo se detienen a la vez los jugadores que atiende ese mismo hilo - Se descarta si: Si el hilo detenido espera fuera de send (un lock, una llamada a la BD): “Contención de locks”, “Llamadas síncronas en el hilo del juego” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [send(2) — Linux manual page](https://man7.org/linux/man-pages/man2/send.2.html) · Linux man-pages · Si no hay espacio en el búfer de envío, send() se bloquea; en modo no bloqueante, vuelve enseguida con EAGAIN - [send function (winsock2.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send) · Microsoft · En Winsock, send también se bloquea si no hay espacio en el búfer, salvo en modo no bloqueante - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q y Send-Q de ss: en un socket de escucha, conexiones esperando accept y límite del backlog; en un socket conectado, bytes que la aplicación aún no ha leído y bytes enviados que no han recibido ACK #### sk-slow-client · Política para clientes lentos (slow consumer) · Slow-consumer policy Cuando a un cliente se le siguen acumulando datos pendientes de envío, el servidor descarta las actualizaciones viejas o corta la conexión. - Por qué → Efecto → En pantalla: La conexión del cliente no da abasto con lo que envía el servidor → El servidor descarta las actualizaciones viejas o, si se supera el límite, cierra la conexión → Teletransporte o desconexión solo para ese jugador - Síntomas: Teletransporte, Desconexión / Factores: Pérdida de paquetes - A quién: Solo yo / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Reducir lo que se envía (frecuencia de actualización según la distancia), seguir enviando con menos calidad, reducir lo que se acumula en el kernel (TCP_NOTSENT_LOWAT de Linux). - Cifras de referencia: Con un búfer de envío de 256 KB, en una conexión de 30 KB/s se acumulan más de 8 segundos de datos atrasados. Linux puede incluso agrandar este búfer automáticamente hasta varios MB. - En el gráfico: Alto solo en algunos (Send-Q por conexión, actualizaciones descartadas por cliente) - Dónde mirar: Longitud de la cola de envío, actualizaciones descartadas y motivos de desconexión por cliente que registra el servidor del juego; en el servidor, el Send-Q y la cwnd de esa conexión con ss -tni - Se confirma si: Solo las conexiones de quienes sufren teletransporte o desconexiones tienen el Send-Q lleno todo el tiempo, y el log del juego registra descartes de sus actualizaciones o desconexiones por exceso en la cola de envío - Se descarta si: Si el Send-Q está vacío y aun así hay teletransporte, el problema no está en el envío del servidor. Apunta a la pérdida en la conexión de ese jugador (“Pérdida en el tramo inalámbrico”) o a la interpolación en pantalla - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_wmem: máximo del búfer de envío con ajuste automático, de 64 KB a 4 MB por defecto (según la memoria); limitar los datos aún no enviados con tcp_notsent_lowat o TCP_NOTSENT_LOWAT - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q y Send-Q de ss: en un socket de escucha, conexiones esperando accept y límite del backlog; en un socket conectado, bytes que la aplicación aún no ha leído y bytes enviados que no han recibido ACK #### sk-keepalive · Keepalive con valor predeterminado de 2 horas · TCP keepalive defaults Si el otro extremo desaparece sin enviar una señal de cierre, TCP tarda mucho en detectarlo. El keepalive (la función de TCP que comprueba si una conexión inactiva sigue viva) viene desactivado por defecto y, aunque se active, no empieza a comprobar hasta que la conexión lleva 2 horas inactiva. - Por qué → Efecto → En pantalla: El cliente desaparece sin señal de cierre porque se apaga o se corta su conexión → El servidor da la conexión por viva (keepalive predeterminado: 7,200 segundos; si había datos pendientes de envío, unos 15 minutos hasta abandonar la retransmisión) → Queda un personaje fantasma y, al reconectar, aparece el error “Ya estás conectado” - Síntomas: No conecta / carga infinita, Entidades invisibles / fantasma / Factores: Pérdida de paquetes - A quién: Solo yo / Cuándo: Tras un rato inactivo, Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo), Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Servidor: responder a los heartbeats y cerrar la conexión por su cuenta si no los recibe durante cierto tiempo (ajustar TCP_KEEPIDLE y TCP_USER_TIMEOUT), al reconectar, reemplazar la sesión anterior mediante el token de sesión y retomarla. Cliente: enviar heartbeats a nivel de juego cada pocos segundos o decenas de segundos (como mucho, la mitad del timeout por inactividad más corto), reconectar automáticamente si se corta. - Tareas (Equipo de infraestructura): Bajar los valores predeterminados del kernel (tcp_keepalive_time, entre otros) para los sockets cuyo código no los fija (solo se aplica a los sockets con SO_KEEPALIVE activado). - Cifras de referencia: Por defecto, Linux empieza a comprobar tras 7,200 segundos de inactividad, envía 9 sondas a intervalos de 75 segundos y, si no recibe respuesta, corta la conexión. En total, unas 2 horas y 11 minutos. Windows también espera por defecto 2 horas de inactividad antes de empezar a comprobar. - En el gráfico: Alto solo en algunos (Tiempo desde la última recepción por conexión) - Dónde mirar: lastrcv (ms desde la última recepción) y el temporizador de keepalive (timer:(keepalive,…)) por conexión con ss -tnoi, cruzados con los rechazos “Ya estás conectado” del servidor del juego - Se confirma si: Quedan conexiones ESTABLISHED con un lastrcv de minutos u horas, y la reconexión de esa cuenta se rechaza con “Ya estás conectado” - Se descarta si: Si no hay conexiones inactivas desde hace mucho y aun así sale “Ya estás conectado”, apunta al código de limpieza de sesiones del servidor del juego - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · Tras 7,200 segundos de inactividad, 9 sondas a intervalos de 75 segundos (unos 11 minutos más); solo se aplica a los sockets con SO_KEEPALIVE activado; TCP_KEEPIDLE y TCP_USER_TIMEOUT - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · El keepalive debe venir desactivado por defecto, y el intervalo de inactividad predeterminado debe ser de 2 horas o más - [SO_KEEPALIVE socket option](https://learn.microsoft.com/en-us/windows/win32/winsock/so-keepalive) · Microsoft · Timeout predeterminado del keepalive TCP de Windows: 2 horas - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · lastrcv (ms desde la última recepción) de -i y timer:(keepalive,…) de -o #### sk-fragment · Fragmentación IP de paquetes UDP · IP fragmentation of large UDP Los paquetes UDP que superan la MTU (el tamaño máximo que se puede enviar de una vez) se fragmentan en la capa IP, y basta con perder un fragmento para que se descarte el paquete entero. - Por qué → Efecto → En pantalla: El snapshot de un lugar con mucha gente supera los 1,500 bytes → Se envía en varios fragmentos, y si se pierde uno solo, se descarta todo → Cuanto más grande es el paquete, más se multiplica la tasa de pérdida. Teletransporte solo en lugares concurridos - Síntomas: Teletransporte / Factores: Pérdida de paquetes - A quién: Una zona o un canal, Una región o un ISP / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Dividir los paquetes por cuenta propia en 1,200 bytes o menos, enviar solo los cambios. - Cifras de referencia: En una conexión con un 2% de pérdida, un paquete dividido en 4 fragmentos se pierde alrededor del 8% de las veces. Algunos firewalls y algunos ISP descartan directamente los paquetes fragmentados, y los jugadores afectados no reciben ni un solo paquete grande. - En el gráfico: Sube con la carga (Fragmentaciones IP (IpFragCreates), tamaño del snapshot) - Dónde mirar: En el servidor, incremento de IpFragCreates (fragmentos creados al enviar) en nstat -az; en el receptor, IpReasmFails (reensamblados fallidos). Distribución del tamaño de los paquetes UDP en los logs del servidor del juego o en una captura de paquetes - Se confirma si: IpFragCreates sube en los lugares donde se junta gente, hay paquetes UDP de más de 1,500 bytes y, a esa hora, aumentan los reportes de teletransporte - Se descarta si: Si IpFragCreates no sube, no hay fragmentación en lo que envía el servidor - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Si se pierde un fragmento, no se puede reensamblar y se pierde el paquete entero; las aplicaciones UDP deben evitar la fragmentación IP - [RFC 8900: IP Fragmentation Considered Fragile](https://www.rfc-editor.org/rfc/rfc8900) · IETF · Casos de firewalls y algunas redes que descartan fragmentos IP - [net/ipv4/proc.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nombres de contador que muestra nstat: FragCreates (fragmentos creados) y ReasmFails (reensamblados fallidos) del grupo Ip #### sk-reliable-udp · Configuración de retransmisión del UDP confiable · Reliable-UDP tuning (KCP, ENet…) Si las reglas de retransmisión implementadas sobre UDP son demasiado conservadoras, la recuperación es lenta; si son demasiado agresivas, congestionan todavía más la conexión. - Por qué → Efecto → En pantalla: El intervalo y el número de retransmisiones o el tamaño de la ventana no se ajustan a la conexión → Recuperación lenta, o más congestión por los envíos duplicados → Habilidades que no salen, cámara rápida, más lag cuando hay congestión - Síntomas: Acción perdida / rollback, Cámara rápida / Factores: Pérdida de paquetes, Latencia - A quién: Solo yo / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: retransmitir según el tiempo de ida y vuelta medido, separar los canales por importancia. Cliente: aplicar la misma configuración de retransmisión y canales que el servidor. - En el gráfico: Picos aleatorios (Tasa de retransmisión del UDP confiable, RTT dentro del juego) - Dónde mirar: Registrar en el servidor y en el cliente las estadísticas por conexión que ofrece la biblioteca usada (retransmisiones, tiempo de ida y vuelta estimado, espera de retransmisión) y compararlas con la pérdida real de la conexión de ese jugador (medida con mtr) - Se confirma si: Si la tasa de retransmisión es varias veces mayor que la pérdida real de la conexión, la configuración es demasiado agresiva; si la espera de retransmisión es varias veces el tiempo de ida y vuelta medido, es demasiado conservadora - Se descarta si: Si la tasa de retransmisión se parece a la pérdida de la conexión y la espera se ajusta al tiempo de ida y vuelta, no es un problema de configuración. Revisar la pérdida de la propia conexión - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · La retransmisión puede agravar la congestión, así que debe someterse a control de congestión; el tiempo de ida y vuelta se estima con la media de varias mediciones (EWMA); valor inicial de 1 segundo; reducir la tasa de envío cuando expira el temporizador #### sk-slowstart · Slow start tras inactividad · Slow start after idle Si una conexión TCP pasa un rato inactiva, vuelve a reducir la ventana de congestión (lo que puede enviar de una vez), y cuando de repente tiene que enviar muchos datos, los envía en varias tandas. - Por qué → Efecto → En pantalla: Se envían muchos datos, por ejemplo al entrar en un pueblo, por una conexión que estaba inactiva → Como la ventana de congestión está reducida, el envío se reparte en varios viajes de ida y vuelta → Justo después de entrar, los personajes y NPC de alrededor aparecen varios viajes de ida y vuelta más tarde (se nota más cuanto más lejos está el servidor) - Síntomas: Input lag, Entidades invisibles / fantasma / Factores: Latencia - A quién: Solo yo / Cuándo: Al moverse o cambiar de zona, Tras un rato inactivo - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Reducir los datos que se envían al entrar en una zona (enviar primero lo imprescindible). - Tareas (Equipo de infraestructura): Desactivar tcp_slow_start_after_idle (Linux, ajuste para todo el servidor). - Cifras de referencia: Si la conexión pasa inactiva más tiempo que el RTO, la ventana de congestión empieza a reducirse y, tras una inactividad larga, baja a unos 14 KB (10 paquetes). Entonces 100 KB ya no se pueden enviar de una vez y se reparten en 3 viajes de ida y vuelta. - En el gráfico: Alto solo en algunos (Tiempo de envío justo después de entrar (jugadores con RTT alto)) - Dónde mirar: Valor de sysctl net.ipv4.tcp_slow_start_after_idle; al entrar en una zona tras un rato inactivo, si la cwnd (ventana de congestión) de esa conexión en ss -ti se ha reducido - Se confirma si: El ajuste está en 1 (predeterminado) y, al entrar tras un rato inactivo, la cwnd baja a unos 10 y el envío se reparte en varios viajes de ida y vuelta. Cuanto mayor es el RTT del jugador, más tarde aparecen las entidades, y con 0 el problema desaparece - Se descarta si: Si la cwnd se mantiene grande y aun así aparecen tarde, apunta al procesamiento de entrada del servidor (“Avalancha de spawns al entrar en una zona concurrida”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_slow_start_after_idle activado por defecto; si la conexión pasa inactiva un RTO, reduce la ventana de congestión (método de RFC 2861) - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Si no se han enviado datos durante más tiempo que el RTO, reducir la ventana de congestión a la ventana de reinicio min(IW, cwnd) o menos y aplicar slow start - [RFC 6928: Increasing TCP's Initial Window](https://www.rfc-editor.org/rfc/rfc6928) · IETF · Ventana inicial de 10 segmentos, máximo 14,600 bytes - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · cwnd (ventana de congestión) y ssthresh (umbral de slow start) de -i #### sk-congestion · Caída brusca del ritmo de envío por el control de congestión · Congestion control backoff TCP interpreta la pérdida como señal de congestión y reduce la velocidad de envío entre un 30 y un 50%. Reacciona igual ante la pérdida en el Wi-Fi. - Por qué → Efecto → En pantalla: Con mucho que enviar, hay algo de pérdida en el Wi-Fi o en la conexión → TCP reduce mucho la velocidad de envío y se recupera despacio (CUBIC, el predeterminado en Linux y Windows, la reduce un 30%) → En los lugares con mucha gente las actualizaciones se atrasan: cámara rápida e input lag - Síntomas: Cámara rápida, Input lag / Factores: Latencia, Detención - A quién: Solo yo / Cuándo: Cuando se junta mucha gente - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Reducir lo que se envía (área de interés, solo los cambios), repartir los envíos para no mandarlo todo de golpe. - Tareas (Equipo de infraestructura): Cambiar a un control de congestión como BBR (tcp_congestion_control). - En el gráfico: Diente de sierra (Ventana de congestión (cwnd) y tasa de envío por conexión) - Dónde mirar: Varias tomas con ss -ti de la conexión del jugador con actualizaciones atrasadas: cambios de cwnd y ssthresh, nombre del control de congestión (cubic, bbr) y si se acumula el Send-Q - Se confirma si: Tras una pérdida, la cwnd cae mucho y sube despacio una y otra vez, y mientras está reducida se acumula el Send-Q, coincidiendo con la hora de los reportes de cámara rápida e input lag - Se descarta si: Si la cwnd es holgada y aun así hay atraso, apunta a la ventana del receptor (“Ventana cero (una detención que parece retransmisión)”) o al envío del servidor - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 9438: CUBIC for Fast and Long-Distance Networks](https://www.rfc-editor.org/rfc/rfc9438) · IETF · Ante una pérdida, CUBIC multiplica la ventana por 0.7 (reducción del 30%) y Reno, por 0.5; CUBIC es el predeterminado en Linux, Windows y Apple - [TCP BBR congestion control comes to GCP – your Internet just got faster](https://cloud.google.com/blog/products/networking/tcp-bbr-congestion-control-comes-to-gcp-your-internet-just-got-faster) · Google Cloud · El control de congestión basado en pérdidas reduce mucho la tasa de envío incluso ante pérdidas que no se deben a congestión; BBR decide según la tasa de entrega y el RTT - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · Elegir el algoritmo de control de congestión de las conexiones nuevas con tcp_congestion_control - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · cwnd, ssthresh y nombre del algoritmo de control de congestión de -i - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q y Send-Q de ss: en un socket de escucha, conexiones esperando accept y límite del backlog; en un socket conectado, bytes que la aplicación aún no ha leído y bytes enviados que no han recibido ACK #### sk-linger · Pérdida de los últimos datos por un cierre forzado con RST · SO_LINGER, abrupt RST Si el servidor corta una conexión de forma brusca, se pierden el último aviso o la confirmación de guardado que envió. - Por qué → Efecto → En pantalla: El servidor cierra la conexión con un cierre forzado (RST). Ocurre si SO_LINGER está en 0 segundos o si se cierra sin leer todos los datos recibidos → Se descartan el motivo de la expulsión y los últimos datos que aún se estaban enviando → Mensajes de “Conexión cerrada por un error desconocido” sin motivo aparente - Síntomas: Desconexión / Factores: Pérdida de paquetes - A quién: Solo yo / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Tras enviar el motivo, cerrar primero solo el sentido de envío (shutdown), leer todos los datos recibidos hasta que el otro extremo cierre y entonces cerrar, evitar SO_LINGER a 0 segundos. - En el gráfico: Picos aleatorios (Conexiones terminadas con RST) - Dónde mirar: Incremento de TcpExtTCPAbortOnData (cerrada con RST quedando datos por enviar, SO_LINGER a 0 segundos) y TcpExtTCPAbortOnClose (cerrada quedando datos sin leer) en nstat -az; en una captura de paquetes en el servidor en el momento del corte, si sale un RST donde debería salir un FIN - Se confirma si: A la hora de los reportes de “Conexión cerrada por un error desconocido”, el servidor envía RST y suben AbortOnData y AbortOnClose - Se descarta si: Si el servidor cerró normalmente con FIN y aun así no se ve el motivo, apunta al manejo del cierre en el cliente - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [closesocket function (winsock.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-closesocket) · Microsoft · Con SO_LINGER activado y el tiempo en 0, el cierre se vuelve forzado: la conexión se reinicia al instante y se pierden los datos no enviados - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · Si se cierra quedando datos recibidos sin leer, se envía RST para avisar de la pérdida de datos - [Graceful Shutdown, Linger Options, and Socket Closure](https://learn.microsoft.com/en-us/windows/win32/winsock/graceful-shutdown-linger-options-and-socket-closure-2) · Microsoft · Orden: cerrar primero solo el envío con shutdown y cerrar el socket después de recibir el aviso de cierre del otro extremo - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPAbortOnData: cerrada con RST quedando datos por enviar, por ejemplo con SO_LINGER a 0 segundos; TcpExtTCPAbortOnClose: cerrada quedando datos sin leer, con envío de RST #### sk-blocking-io · Modelo de E/S bloqueante · Blocking I/O model En un modelo en el que el hilo no puede hacer nada más mientras espera a un socket, todo se vuelve más lento a medida que aumentan los jugadores. - Por qué → Efecto → En pantalla: Se espera la lectura y la escritura conexión por conexión → El retraso de una conexión se contagia a las demás conexiones del mismo hilo → Cuantos más jugadores conectados, más cámara lenta e input lag para todos - Síntomas: Cámara lenta, Input lag / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente, Horas pico de la noche - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Pasar a E/S asíncrona basada en epoll, IOCP o io_uring. - En el gráfico: Sube con la carga (Tiempo de respuesta, número de hilos) - Dónde mirar: Número de hilos del servidor del juego y cambios de contexto voluntarios por hilo (cswch/s, veces que se detuvo para esperar un recurso) con pidstat -w -t, comparados con el tiempo de respuesta según los jugadores conectados - Se confirma si: Al subir los jugadores conectados, el tiempo de respuesta se dispara, y la mayoría de los hilos, que crecen al ritmo de las conexiones, tienen muchos cambios voluntarios y apenas usan CPU (esperan al socket) - Se descarta si: Si los hilos usan CPU sin parar y sin esperas, es una sobrecarga de cálculo (“Tick que excede su presupuesto”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [epoll(7) — Linux manual page](https://man7.org/linux/man-pages/man7/epoll.7.html) · Linux man-pages · Notificación de eventos de E/S que escala para vigilar muchos fd a la vez - [I/O Completion Ports](https://learn.microsoft.com/en-us/windows/win32/fileio/i-o-completion-ports) · Microsoft · Modelo de Windows que procesa mucha E/S asíncrona con un pool de hilos creado de antemano - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · cswch/s de -w: cambios de contexto voluntarios (el hilo se detiene por sí mismo para esperar un recurso); con -t, por hilo #### sk-reuseport · Reparto desigual con SO_REUSEPORT · SO_REUSEPORT imbalance, stuck worker Cuando varios procesos reciben en el mismo puerto, el kernel asigna cada conexión a un proceso según un hash de la dirección y no cambia esa asignación. Si ese proceso se detiene, solo esperan los jugadores asignados a él. - Por qué → Efecto → En pantalla: El gateway o el servidor de login levanta varios procesos con SO_REUSEPORT → Aunque un proceso se detenga por GC o sobrecarga, las conexiones nuevas y los paquetes UDP asignados a él no pasan a otros procesos → Solo algunos jugadores no consiguen conectar o sufren congelamientos. En los reinicios que cambian el número de procesos, se cortan algunas sesiones UDP - Síntomas: No conecta / carga infinita, Congelamiento, Desconexión / Factores: Detención, Pérdida de paquetes - A quién: Solo yo, Todo el servidor / Cuándo: Al conectar o tras un mantenimiento, De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Evitar a toda costa que el hilo que recibe se detenga, implementar un procedimiento para traspasar las sesiones en los reinicios. - Tareas (Equipo de infraestructura): Vigilar la cola de conexiones pendientes de cada proceso (Recv-Q de ss), exigir el procedimiento de traspaso de sesiones cuando un despliegue cambie el número de procesos. - En el gráfico: Alto solo en algunos (Cola de conexiones pendientes (Recv-Q) por socket de escucha) - Dónde mirar: Recv-Q (conexiones esperando accept) y proceso responsable de cada socket de escucha del mismo puerto con ss -ltnp; comparar el volumen que procesa cada proceso - Se confirma si: De los varios sockets del mismo puerto, solo uno acumula Recv-Q sin parar, y su proceso está detenido o no procesa casi nada - Se descarta si: Si el Recv-Q se acumula por igual en todos los sockets, es una sobrecarga general (“Desbordamiento de la cola de conexiones pendientes (backlog)”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [socket(7) — Linux manual page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux man-pages · Con SO_REUSEPORT, varios sockets hacen bind a la misma dirección y se reparten las conexiones TCP y los paquetes UDP - [net/core/sock_reuseport.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/core/sock_reuseport.c?h=v6.12) · Linux kernel · Sin un programa BPF, el socket responsable se elige repartiendo el valor de hash del paquete según el número de sockets del grupo - [Why does one NGINX worker take all the load?](https://blog.cloudflare.com/the-sad-state-of-linux-socket-balancing/) · Cloudflare · SO_REUSEPORT reparte las colas entre los workers con un hash simple, así que si un worker se bloquea, se detienen todas las conexiones acumuladas en su cola - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q y Send-Q de ss: en un socket de escucha, conexiones esperando accept y límite del backlog; en un socket conectado, bytes que la aplicación aún no ha leído y bytes enviados que no han recibido ACK #### sk-udp-connreset · Error WSAECONNRESET en sockets UDP de Windows · WSAECONNRESET on a Windows UDP socket Cuando un servidor Windows envía UDP a un cliente que ya se fue, vuelve un aviso de “puerto inalcanzable” (ICMP). Ese aviso hace que la siguiente llamada de recepción termine con error, y si el código del servidor lo trata como una avería del propio socket, todos los que usan ese socket se ven afectados. - Por qué → Efecto → En pantalla: Se sigue enviando UDP a la dirección de un cliente que acaba de irse y vuelve un aviso de “puerto inalcanzable” (ICMP) → Windows termina la siguiente llamada de recepción con el error WSAECONNRESET (10054), y el código del servidor deja de recibir o cierra el socket → Congelamiento o desconexión simultánea de todos los que usaban ese socket - Síntomas: Desconexión, Congelamiento / Factores: Pérdida de paquetes, Detención - A quién: Todo el servidor / Cuándo: De vez en cuando, al azar, Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Desactivar SIO_UDP_CONNRESET con WSAIoctl para no recibir este aviso, ante un error de recepción solo registrarlo en el log y seguir recibiendo. - En el gráfico: Desconexión masiva (Número de conexiones, log de errores de recepción) - Dónde mirar: En los logs del servidor del juego, códigos de error de recepción UDP (WSAECONNRESET, 10054) y registros de que el bucle de recepción se detuvo o se cerró el socket; en una captura de paquetes en el servidor, si justo antes llegó un ICMP Port Unreachable - Se confirma si: Justo antes de la desconexión masiva se registra un error de recepción WSAECONNRESET y, antes de eso, llega un ICMP Port Unreachable desde la dirección de un cliente que acababa de irse - Se descarta si: No aplica si el servidor es Linux o si el código desactiva SIO_UDP_CONNRESET - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Winsock IOCTLs](https://learn.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls) · Microsoft · SIO_UDP_CONNRESET activa y desactiva el aviso UDP de “puerto inalcanzable” (PORT_UNREACHABLE) - [recvfrom function (winsock.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom) · Microsoft · En un socket UDP, WSAECONNRESET significa que un envío anterior recibió un ICMP Port Unreachable - [Windows Sockets Error Codes](https://learn.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2) · Microsoft · Número de error de WSAECONNRESET: 10054 ### L9 Proceso del juego en el servidor (causas: 18) #### sp-tick-overrun · Tick que excede su presupuesto · Tick overrun Si el trabajo de un tick supera su presupuesto, el intervalo de tick del servidor se alarga y toda esa zona va más lenta o va a tirones. - Por qué → Efecto → En pantalla: El trabajo de un tick (p. ej., 50 ms) supera su presupuesto → El estado del juego, que debería calcularse 20 veces por segundo, se calcula solo 8 → Cámara lenta en toda la zona (o tirones, según el diseño del servidor), habilidades que responden tarde - Síntomas: Cámara lenta, Input lag, Tirones / Factores: Detención - A quién: Una zona o un canal, Todo el servidor / Cuándo: Cuando se junta mucha gente, Horas pico de la noche - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Reducir los cálculos costosos, repartir el tick entre varios hilos, distribuir a los jugadores (canales), registrar el tiempo de procesamiento del tick como métrica. - Tareas (Equipo de infraestructura): Añadir el tiempo de tick y el uso de CPU por núcleo al monitoreo y las alertas, evaluar CPU e instancias con alto rendimiento por núcleo (frecuencia de reloj). - Cifras de referencia: El presupuesto de un servidor de 20 ticks es de 50 ms; el de uno de 30 ticks, 33 ms, y el de uno de 60 ticks, 16.7 ms. Para aguantar las aglomeraciones repentinas, lo seguro es dejar margen y usar normalmente solo alrededor de la mitad del presupuesto. - En el gráfico: Sube con la carga (Tiempo de tick del servidor, jugadores por zona y canal, CPU del hilo del juego) - Dónde mirar: Tiempo de procesamiento del tick (p99) y número de ticks excedidos que registra el servidor, en el mismo gráfico que los jugadores por zona y canal. Sin métricas de tick, uso de CPU del hilo del juego con pidstat -t 1 - Se confirma si: Cuando se junta gente, el tiempo de tick supera el presupuesto (50 ms a 20 ticks), con el hilo del juego cerca del 100% de CPU mientras tanto - Se descarta si: Ticks excedidos con poca CPU en el hilo del juego: apunta a esperas (pausa del GC, locks, llamadas síncronas). Si la latencia de la cola de ejecución en runqlat de bcc es alta, los hilos no reciben CPU: falta de CPU o exceso de hilos - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Cómo se ve un tick retrasado depende del diseño del servidor. En un servidor que avanza el estado del juego un tiempo fijo por tick (p. ej., 50 ms), el propio tiempo del juego se ralentiza y aparece la cámara lenta. En uno que avanza de una vez todo el tiempo real transcurrido, el ritmo del juego se mantiene, pero los paquetes llegan espaciados y con movimientos grandes, y se ve como tirones y teletransporte. En ambos casos, los inputs responden tarde. Si un solo hilo del juego lleva todo el servidor, se ralentiza el servidor entero; si hay un hilo por zona, solo esa zona. Algunos juegos, como EVE Online, ralentizan a propósito el tiempo del juego hasta 10 veces en las batallas masivas (Time Dilation) para que el cálculo se ponga al día. - Casos reales: eve-hedgp-2014 - Fuentes: - [VALORANT's 128-Tick Servers](https://www.riotgames.com/en/news/valorants-128-tick-servers) · Riot Games · Un servidor de 128 ticks debe terminar cada frame en 7.8125 ms; medir el tiempo de frame del servidor por subsistema y repartir el presupuesto entre ellos - [HED-GP Technical Retrospective: What a HED-ache](https://www.eveonline.com/news/view/what-a-hed-ache) · CCP Games · En sobrecarga, EVE Online ralentiza el tiempo del juego con Time Dilation hasta un mínimo del 10% (10 veces más lento); en condiciones normales, la CPU de los nodos está por debajo del 80% - [Handling variation in time](https://docs.unity3d.com/Manual/time-handling-variations.html) · Unity · Cuando una simulación de paso fijo se atrasa, ejecuta seguidos los pasos para ponerse al día y descarta el tiempo que supera el límite, así que el tiempo del juego corre más despacio que el real - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -t muestra también las estadísticas por hilo del proceso (uso de CPU, entre otras) - [Demonstrations of runqlat, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/runqlat_example.txt) · IO Visor · Muestra como histograma la latencia de la cola de ejecución del planificador (el tiempo que una tarea espera hasta recibir CPU) #### sp-aoi · Explosión del cálculo de visibilidad (AOI, N²) · Area-of-interest explosion Si se compara a todos con todos para saber quién puede ver a quién, cuando el número de jugadores se multiplica por 10, el cálculo se multiplica por 100. - Por qué → Efecto → En pantalla: Se compara la distancia entre todos los personajes, o, aun dividiendo el mapa en una cuadrícula, cientos de jugadores se juntan cerca de una misma celda → Con 100 jugadores, unas 10,000 comparaciones; con 1,000, alrededor de 1 millón → En lugares abarrotados, como un world boss o un asedio, el tick se dispara: cámara lenta y tirones - Síntomas: Cámara lenta, Tirones / Factores: Detención - A quién: Una zona o un canal, Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Dividir el mapa en cuadrículas o sectores y comparar solo lo cercano, actualizar con menos frecuencia lo que está lejos, poner un tope a los jugadores que ve cada uno. - Cifras de referencia: Si cada par de jugadores cuesta 0.1 µs (una diezmillonésima de segundo) entre la comparación de distancia y la actualización de las listas de visibles y no visibles, con 1,000 jugadores (cerca de 1 millón de pares) un tick tarda 100 ms. Es el doble del presupuesto de 20 ticks (50 ms). - En el gráfico: Sube con la carga (Tiempo de tick del servidor, jugadores reunidos en un mismo lugar) - Dónde mirar: Jugadores y tiempo de tick por zona y canal en el mismo gráfico, y el tiempo del tick dedicado al cálculo de visibilidad, medido aparte. Si no se mide aparte, peso de CPU por función del proceso del juego con perf top -p - Se confirma si: Cuando se duplican los jugadores reunidos en un lugar, el tiempo de tick casi se cuadruplica, y las funciones de visibilidad y distancia se llevan la mayor parte del tiempo de CPU - Se descarta si: Si el tiempo de tick crece en proporción a los jugadores o pesan mucho las funciones de envío y serialización, apunta a “Explosión de broadcast” o a “Costo de serialización y compresión” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Comparing Interest Management Algorithms for Massively Multiplayer Games](https://www.sable.mcgill.ca/~clump/papers/boulanger-06-comparing.pdf) · ACM · Artículo de NetGames 2006 (versión pública de los autores). Medir la distancia de todos los pares no escala al aumentar los jugadores; con una cuadrícula de celdas cuadradas, solo se revisan las 9 celdas de alrededor - [Replication Graph in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/replication-graph-in-unreal-engine) · Epic Games · El método básico, que evalúa todas las conexiones para cada actor, es un cuello de botella de CPU en el servidor con muchos jugadores y actores; los MMORPG y juegos similares dividen el mundo en una cuadrícula y reutilizan las listas de cada celda - [perf-top(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-top.1.html) · perf · Muestra en tiempo real el peso de uso de CPU por función (símbolo) de un proceso (-p) o hilo (-t) en ejecución #### sp-broadcast · Explosión de broadcast · Broadcast fan-out (N×N) Si el movimiento de un jugador se envía a todos los que lo ven, las actualizaciones que hay que enviar crecen con el cuadrado del número de jugadores reunidos. - Por qué → Efecto → En pantalla: Los cambios de un jugador se envían a todos los que pueden verlo → Si 1,000 jugadores se ven entre sí, hay 1 millón de actualizaciones por tick → La cola de envío y el ancho de banda se saturan: latencia y pérdida (input lag, cámara rápida, teletransporte) - Síntomas: Input lag, Teletransporte, Cámara rápida / Factores: Latencia, Pérdida de paquetes - A quién: Una zona o un canal, Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Bajar la frecuencia de actualización según la distancia y la importancia (los enemigos cercanos en cada tick, los jugadores lejanos unas pocas veces por segundo), poner un tope a lo que se envía a cada jugador y llenarlo empezando por lo importante, agrupar varias actualizaciones en un paquete, poner un tope a los jugadores mostrados. - Tareas (Equipo de infraestructura): Comparar el ancho de banda de envío y los paquetes por segundo de cada servidor con los límites de red de la NIC y de la instancia y alertar, comprobar que hay margen antes de los eventos masivos. - Cifras de referencia: 1,000 jugadores × 1,000 jugadores × 20 ticks = 20 millones por segundo. Con 40 bytes cada una, unos 6.4 Gbps para todo el servidor y unos 6.4 Mbps por cada jugador que recibe. Si se limita a 150 el número de jugadores visibles, en total queda en 1 Gbps aproximadamente, y alrededor de 1 Mbps por jugador. - En el gráfico: Sube con la carga (Paquetes y bytes enviados por el servidor, jugadores reunidos en un mismo lugar) - Dónde mirar: txpck/s y txkB/s (paquetes y KB enviados por segundo por la NIC del servidor) de sar -n DEV 1 junto al gráfico de jugadores. En instancias de nube, los contadores de límite superado de ethtool -S (en ENA de AWS, bw_out_allowance_exceeded y pps_allowance_exceeded) - Se confirma si: Al aumentar los jugadores reunidos, los paquetes y bytes enviados crecen más rápido que los jugadores (casi al cuadrado), y desde que tocan el límite suben los contadores de límite superado o los descartes de envío - Se descarta si: Si el volumen enviado no cambia y solo crece el tiempo de tick, apunta al cálculo de visibilidad o a la lógica del juego - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Casos reales: eve-hedgp-2014 - Fuentes: - [HED-GP Technical Retrospective: What a HED-ache](https://www.eveonline.com/news/view/what-a-hed-ache) · CCP Games · El envío O(n²), en el que n jugadores deben ver lo que hace cada uno de los n, es el límite inevitable de las grandes batallas de flotas - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Cuando se satura el ancho de banda de la conexión, se asigna una prioridad a cada actor (distancia, línea de visión, tiempo desde el último envío) y se reparte el ancho de banda empezando por lo importante - [Detailed Actor Replication Flow in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/detailed-actor-replication-flow-in-unreal-engine) · Epic Games · NetUpdateFrequency fija la frecuencia de actualización de cada actor; se envía por orden de prioridad y, si la conexión se satura, el resto se aplaza al siguiente tick - [sar(1) — Linux manual page](https://man7.org/linux/man-pages/man1/sar.1.html) · sysstat · rxpck/s y txpck/s (paquetes recibidos y enviados por segundo) y rxkB/s y txkB/s (KB recibidos y enviados por segundo) de sar -n DEV - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · Paquetes encolados o descartados por bw_out_allowance_exceeded (límite de ancho de banda de envío superado) y pps_allowance_exceeded (límite de PPS superado) #### sp-hotzone · Sobrecarga de una zona de un solo hilo (hotspot) · Single-threaded hot zone En un diseño con un hilo por zona, si la gente se concentra en un lugar, solo ese núcleo llega al 100%. - Por qué → Efecto → En pantalla: Un solo hilo lleva una zona (canal) → Cuando la gente se concentra en un lugar, solo ese núcleo se satura y los demás están desocupados → Solo esa zona tiene lag; las demás van bien - Síntomas: Cámara lenta, Input lag / Factores: Detención - A quién: Una zona o un canal / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Distribuir entre canales, paralelizar dentro de la zona, poner un tope de jugadores. - Tareas (Equipo de infraestructura): Añadir el uso de CPU por núcleo al monitoreo y las alertas (en la media de todo el servidor, la saturación de un núcleo pasa desapercibida). - Cifras de referencia: En un servidor de 16 núcleos, aunque un núcleo esté al 100%, el uso de CPU de todo el servidor aparece en torno al 6%. Solo se detecta mirando el uso por núcleo. - En el gráfico: Sube con la carga (Uso de CPU por núcleo, CPU por hilo) - Dónde mirar: Uso por núcleo con mpstat -P ALL 1 y CPU por hilo del proceso del juego con pidstat -t 1, comparados con los jugadores de la zona que lleva el hilo más ocupado - Se confirma si: La CPU de todo el servidor es baja, pero un solo hilo (un núcleo) está pegado cerca del 100%, y a esa hora hay mucha gente en la zona que lleva ese hilo - Se descarta si: Si varios núcleos están altos por igual, es una sobrecarga de todo el servidor. Si solo es alto el %soft (procesamiento de recepción) de un núcleo, apunta a “Interrupciones de la NIC concentradas en un solo núcleo” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Que las demás zonas vayan bien solo es cierto cuando cada zona ejecuta su propio tick. Si los hilos de varias zonas se esperan entre sí en cada tick para pasar juntos al siguiente, la zona más ocupada retrasa el tick de todo el servidor. - Casos reales: eve-hedgp-2014 - Fuentes: - [Time Dilation – How’s That Going?](https://www.eveonline.com/news/view/time-dilation-hows-that-going) · CCP Games · La Time Dilation de EVE Online funciona por nodo, así que también se ralentizan sistemas solares lejanos alojados en el mismo nodo; las grandes batallas se procesan en nodos reforzados que solo alojan 4 sistemas solares - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · Muestra por separado el uso de cada procesador y la media global (-P ALL); %soft es el porcentaje de tiempo dedicado a procesar interrupciones de software - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -t muestra también las estadísticas por hilo del proceso (uso de CPU, entre otras) #### sp-lock · Contención de locks · Lock contention Si varios hilos esperan un mismo lock para escribir los mismos datos, por más hilos que se añadan, solo se ejecuta uno a la vez. - Por qué → Efecto → En pantalla: Varios hilos usan a la vez datos compartidos, como la casa de subastas o el almacén del gremio → Los demás esperan hasta que termina el hilo que tiene el lock → Solo una función va lenta y, en los casos graves, se retrasa todo el tick - Síntomas: Input lag, Congelamiento / Factores: Detención - A quién: Solo una función, Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Dividir los locks en piezas más pequeñas, reducir el trabajo dentro del lock, usar un modelo basado en mensajes (asignar un hilo responsable a cada dato y que los demás hilos solo le envíen solicitudes por mensaje). - Cifras de referencia: Si el trabajo dentro del lock es el 20% del total, por más hilos que se añadan, el rendimiento se queda como máximo en 5 veces el de un solo hilo; si es el 40%, en 2.5 veces. - En el gráfico: Sube con la carga (Tiempo de procesamiento de solicitudes, CPU y cambios de contexto por hilo) - Dónde mirar: Cambios de contexto voluntarios por hilo (cswch/s, veces que se detuvo para esperar un recurso) con pidstat -w -t 1; dónde esperan los hilos fuera de la CPU (tiempo de espera por pila de llamadas) con offcputime -p de bcc. En .NET, el número de contenciones de lock en dotnet-counters (dotnet.monitor.lock_contentions desde .NET 9; Monitor Lock Contention Count en la 8 y anteriores) - Se confirma si: Al aumentar la carga, el uso de CPU sigue bajo pero el tiempo de procesamiento aumenta, la mayor parte de la espera se concentra en pilas de llamadas que intentan adquirir un lock y el número de contenciones sube a la par - Se descarta si: Si la CPU está al tope, es un problema de cálculo (“Tick que excede su presupuesto”, “Sobrecarga de una zona de un solo hilo (hotspot)”). Si esperan en llamadas a la BD o a archivos, apunta a “Llamadas síncronas en el hilo del juego” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Ocurre en diseños en los que varios hilos modifican juntos los datos del juego. Los diseños en los que cada zona o función tiene un solo hilo y todo se comunica por mensajes casi no tienen locks; a cambio, hay que vigilar que el trabajo no se concentre en un hilo (“Sobrecarga de una zona de un solo hilo (hotspot)”). Si el hilo del juego espera un lock que retiene una operación de guardado lenta, se detiene todo ese tick. - Casos reales: roblox-2021 - Fuentes: - [Amdahl's Law in the Multicore Era](https://research.cs.wisc.edu/multifacet/papers/ieeecomputer08_amdahl_multicore.pdf) · IEEE · Artículo de IEEE Computer 2008 (versión pública de los autores). Si la fracción que no se puede paralelizar es 1−f, por más núcleos que se añadan, la aceleración no supera 1/(1−f) (ley de Amdahl) - [Request scheduling](https://learn.microsoft.com/en-us/dotnet/orleans/grains/request-scheduling) · Microsoft · Los grains (actores) de Orleans usan un modelo de ejecución de un solo hilo que procesa cada solicitud de principio a fin, así que el estado no se modifica en paralelo; si se esperan respuestas mutuamente, puede haber deadlock - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · cswch/s de -w: número de cambios de contexto voluntarios por detenerse a esperar un recurso; con -t, por hilo - [Demonstrations of offcputime, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/offcputime_example.txt) · IO Visor · Suma, por pila de llamadas, el tiempo que los hilos pasan detenidos fuera de la CPU (off-CPU); -p indica el proceso - [Well-known EventCounters in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/available-counters) · Microsoft · Monitor Lock Contention Count (monitor-lock-contention-count): veces que hubo contención al intentar adquirir un monitor lock - [.NET runtime metrics](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics-runtime) · .NET · dotnet.monitor.lock_contentions desde .NET 9: veces que hubo contención al intentar adquirir un monitor lock desde el inicio del proceso #### sp-deadlock · Deadlock · Deadlock Si dos hilos esperan cada uno el lock que tiene el otro, se quedan detenidos para siempre. - Por qué → Efecto → En pantalla: El hilo A tiene el lock 1 y espera el lock 2; B tiene el lock 2 y espera el lock 1 → Los dos se quedan detenidos para siempre, y los hilos relacionados también se detienen uno tras otro → Todo el servidor se detiene y, cuando el watchdog lo reinicia, se desconecta a todos los jugadores - Síntomas: Congelamiento, Desconexión / Factores: Detención - A quién: Todo el servidor, Solo una función / Cuándo: De vez en cuando, al azar, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Definir un orden fijo para adquirir los locks, usar locks con timeout, tener un watchdog y guardar un volcado de hilos en el momento de la detención. - En el gráfico: Desconexión masiva (Número de conexiones, volumen enviado por el servidor) - Dónde mirar: Pilas de llamadas de todos los hilos durante la detención. En la JVM, jstack (detecta y marca los deadlocks automáticamente); en .NET, dotnet-stack; en servidores nativos, thread apply all bt de gdb, o generar un archivo core con gcore, reiniciar y analizarlo después - Se confirma si: Dos o más hilos están detenidos con pilas que esperan el lock que tiene el otro, y mientras tanto el uso de CPU del proceso está cerca de 0 - Se descarta si: Si durante la detención un hilo gira al 100% de CPU, es un bucle infinito. Si los hilos esperan respuestas de la BD o de servicios externos, apunta a llamadas síncronas o a “Agotamiento del pool de hilos” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Runtime locking correctness validator](https://docs.kernel.org/locking/lockdep-design.html) · Linux kernel · Adquirir dos locks en orden inverso provoca una espera circular y un deadlock (lock inversion deadlock); el kernel de Linux comprueba el orden de los locks y avisa de antemano - [Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/workloads/pods/probes/) · Kubernetes · Detectar con una sonda de liveness un deadlock (el proceso se ejecuta pero no avanza) y reiniciar el contenedor - [Diagnostic Tools (Java SE 21 Troubleshooting Guide)](https://docs.oracle.com/en/java/javase/21/troubleshoot/diagnostic-tools.html) · Oracle · jstack imprime las pilas de todos los hilos de una JVM en ejecución y también detecta y marca los deadlocks (Found one Java-level deadlock) - [dotnet-stack diagnostic tool - .NET CLI](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-stack) · Microsoft · Captura e imprime las pilas administradas de todos los hilos de un proceso .NET - [Threads (Debugging with GDB)](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Threads.html) · GNU Project · Ejecutar el mismo comando en todos los hilos con thread apply all (bt: imprimir la pila de llamadas) - [gcore(1) — Linux manual page](https://man7.org/linux/man-pages/man1/gcore.1.html) · gdb · Genera un archivo core del programa en ejecución, y el programa sigue ejecutándose después #### sp-sync-call · Llamadas síncronas en el hilo del juego · Synchronous DB / file I/O on the game loop Si durante un tick se espera la respuesta de la BD o una escritura en archivo, todo el avance del juego en el servidor se detiene ese tiempo. - Por qué → Efecto → En pantalla: Dentro del tick se esperan consultas y guardados en la BD, escrituras de logs o llamadas a API externas → Si la BD tarda 100 ms, el tick también se detiene 100 ms → Cada vez que la BD o el disco van lentos, toda la zona abierta sufre un tirón - Síntomas: Congelamiento, Tirones / Factores: Detención - A quién: Una zona o un canal, Todo el servidor / Cuándo: Al hacer ciertas acciones, De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Pasar a asíncrono todo el trabajo lento (consultas y guardados en la BD, escritura de logs, llamadas a API externas) y aplicar el resultado en el tick siguiente (si solo se pone un timeout, el tick sigue detenido mientras espera). - Cifras de referencia: Incluso un viaje de ida y vuelta de 0.5 ms a una BD del mismo centro de datos, repetido 100 veces en un tick, suma 50 ms. Eso consume por sí solo todo el presupuesto de 20 ticks. - En el gráfico: Picos aleatorios (Tiempo de tick del servidor, latencia de las consultas a la BD) - Dónde mirar: Gráfico de tiempo de tick junto a la latencia de las consultas a la BD (slow query log, entre otros) y la latencia del disco, en el mismo eje de tiempo. Sin métricas de tick, dónde espera el hilo del juego con offcputime -p de bcc - Se confirma si: Los picos de tick coinciden con los picos de latencia de la BD o de los archivos, y el tiempo de espera del hilo del juego se concentra en las pilas de llamadas que reciben respuestas de la BD o escriben archivos - Se descarta si: Si la latencia de la BD y del disco está tranquila pero hay picos de tick, apunta a pausas del GC o a contención de locks - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Designs, Lessons and Advice from Building Large Distributed Systems](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Keynote de LADIS 2009 (Jeff Dean). Ida y vuelta dentro del mismo centro de datos: unos 0.5 ms (500,000 ns) - [ASP.NET Core Best Practices](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/best-practices) · Microsoft · Llamar de forma asíncrona al acceso a datos, la E/S y las operaciones largas; las llamadas síncronas bloqueantes provocan agotamiento del pool de hilos y respuestas lentas - [Demonstrations of offcputime, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/offcputime_example.txt) · IO Visor · Suma, por pila de llamadas, el tiempo que los hilos pasan detenidos fuera de la CPU (off-CPU); -p indica el proceso #### sp-queue · Acumulación en la cola de mensajes · Mailbox / job queue backlog Si las solicitudes llegan más rápido de lo que se procesan y se acumulan en la cola, las últimas se procesan varios segundos después o se descartan. - Por qué → Efecto → En pantalla: Las solicitudes llegan más rápido de lo que se procesan → La cola se alarga y, al superar el límite, se descarta lo que sobra → Habilidades e intercambios que responden tarde o se pierden - Síntomas: Input lag, Acción perdida / rollback / Factores: Latencia, Pérdida de paquetes - A quién: Una zona o un canal, Solo una función / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Monitorear la longitud de la cola, aplicar una política que descarte primero las solicitudes viejas, paralelizar el procesamiento. - En el gráfico: Topa con el límite (Longitud de la cola y antigüedad del mensaje más viejo, procesados por segundo) - Dónde mirar: Longitud de cada cola, antigüedad del mensaje más viejo, y entradas, procesados y descartes por segundo que registra el servidor. Sin métricas en el código, Recv-Q del socket del juego con ss (o netstat), es decir, lo que el kernel ya recibió y el proceso aún no ha leído - Se confirma si: Mientras entra más de lo que se procesa, el número de procesados se estanca en un valor y no dejan de crecer la longitud y la antigüedad de la cola ni los descartes - Se descarta si: Si la cola es corta y la antigüedad baja pero la respuesta tarda, apunta a la latencia de la conexión o al retraso del propio tick - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Casos reales: eve-hedgp-2014 - Fuentes: - [Avoiding insurmountable queue backlogs](https://d1.awsstatic.com/builderslibrary/pdfs/avoiding-insurmountable-queue-backlogs.pdf) · AWS · Amazon Builders' Library. Vigilar la acumulación por la antigüedad de los mensajes en espera; en sistemas en tiempo real, procesar primero los datos nuevos (cerca de LIFO) y, a veces, descartar los mensajes viejos - [Site Reliability Engineering, Chapter 22: Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/) · Google · Si las solicitudes llegan más rápido de lo que se procesan, la cola se llena y aumenta la latencia; con LIFO o CoDel (frente al FIFO habitual) se quitan las solicitudes viejas que ya no sirven - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · Herramienta que muestra estadísticas de sockets (información parecida a la de netstat); -p muestra el proceso que usa cada socket - [netstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/netstat.8.html) · net-tools · Recv-Q: en un socket conectado, bytes que el programa de usuario aún no ha recogido #### sp-timer-burst · Temporizadores que se disparan todos a la vez · Synchronized timers Si la reaparición de todos los monstruos, el fin de todos los buffs y las recompensas a la hora en punto caen en el mismo tick, ese tick pesa decenas de veces más. - Por qué → Efecto → En pantalla: Los temporizadores de reaparición, expiración, recompensas y guardado automático coinciden a la misma hora → Ese tick tiene decenas de veces más trabajo que de costumbre → Un tirón cada vez que llega la hora fijada - Síntomas: Congelamiento, Tirones / Factores: Detención - A quién: Una zona o un canal, Todo el servidor / Cuándo: A intervalos regulares - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Desplazar un poco al azar la hora de los temporizadores, repartir el procesamiento entre varios ticks. - En el gráfico: Picos periódicos (Tiempo de tick del servidor) - Dónde mirar: Intervalo entre los momentos de los picos de tick (a la hora en punto, cada 5 minutos, etc.), contrastado con la lista de temporizadores de reaparición, fin de buffs, recompensas y guardado automático que se ejecutan a esa hora - Se confirma si: El tick tiene picos siempre a la misma hora o con el mismo intervalo, y a esa hora se disparan de golpe tareas de temporizadores del juego - Se descarta si: Si hay periodicidad pero coincide con las pausas del log del GC o con la hora de los cron o las copias de seguridad del servidor, apunta a “Pausa stop-the-world del GC en el servidor” o a “Tareas programadas” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Timeouts, retries, and backoff with jitter](https://d1.awsstatic.com/builderslibrary/pdfs/timeouts-retries-and-backoff-with-jitter.pdf) · AWS · Amazon Builders' Library. Añadir jitter a todos los temporizadores, tareas periódicas y tareas diferidas para dispersar la carga que coincide en el tiempo; caso de solicitudes con periodo de 1 minuto de muchos servidores que se concentraban en los primeros segundos de cada minuto #### sp-pathfinding · Avalancha de pathfinding · Pathfinding storms Si cientos de monstruos persiguen a la vez a los jugadores calculando rutas, se consume mucha CPU. - Por qué → Efecto → En pantalla: Muchos monstruos persiguen a la vez al agruparlos para cazar o con spawns masivos → Cada monstruo calcula su ruta (pathfinding) → Cámara lenta solo en esa zona de caza - Síntomas: Cámara lenta / Factores: Detención - A quién: Una zona o un canal / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cachear rutas, poner un tope a los cálculos, repartirlos entre varios ticks. - En el gráfico: Sube con la carga (Tiempo de tick del servidor, monstruos por zona) - Dónde mirar: Monstruos persiguiendo a jugadores y tiempo de tick por zona. Si no se cuentan aparte, peso de CPU por función del proceso del juego con perf top -p - Se confirma si: El tiempo de tick sube al agrupar monstruos o con spawns masivos, y las funciones de pathfinding (búsqueda de rutas) se llevan gran parte del tiempo de CPU - Se descarta si: Si el tick sube cuando hay pocos monstruos y muchos jugadores, apunta al cálculo de visibilidad o al broadcast - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [AI.NavMesh.pathfindingIterationsPerFrame](https://docs.unity3d.com/ScriptReference/AI.NavMesh-pathfindingIterationsPerFrame.html) · Unity · Procesar el pathfinding solo un número fijo de nodos por frame, repartiéndolo entre varios frames; el juego sigue fluido incluso con rutas largas o muchas solicitudes a la vez - [perf-top(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-top.1.html) · perf · Muestra en tiempo real el peso de uso de CPU por función (símbolo) de un proceso en ejecución (-p) #### sp-serialize · Costo de serialización y compresión · Serialization / compression cost Convertir a bytes y comprimir los datos que se van a enviar también consume CPU, y con mucha gente este costo se dispara. - Por qué → Efecto → En pantalla: En cada actualización, se convierten estructuras a bytes y se comprimen → El costo crece con el cuadrado del número de jugadores → El envío se retrasa: input lag - Síntomas: Input lag / Factores: Detención, Latencia - A quién: Una zona o un canal / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Reutilizar para varios jugadores un paquete ya generado, usar formatos ligeros. - En el gráfico: Sube con la carga (Uso de CPU del servidor, CPU del hilo que genera los paquetes) - Dónde mirar: Con perf top -p, peso de las funciones de serialización, compresión y cifrado (incluidas las de bibliotecas como zlib, LZ4 u OpenSSL) en el tiempo de CPU del proceso del juego, comparando momentos con pocos jugadores y con aglomeración - Se confirma si: Cuanto más se junta la gente, más pesan las funciones de serialización, compresión y cifrado, y la CPU del hilo que genera los paquetes es la primera en saturarse - Se descarta si: Si estas funciones pesan poco, apunta al cálculo de visibilidad o a la lógica del juego - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Si la conexión cifra los paquetes (TLS, DTLS, etc.), cifrar y descifrar también consume CPU. El cifrado se hace por conexión, así que, aunque un paquete generado se reutilice para varios jugadores, el costo de cifrado se paga una vez por destinatario. Los cifrados simétricos como AES-GCM son tan rápidos que un núcleo procesa varios GB por segundo y normalmente pesan poco, pero su velocidad varía mucho según el tamaño de la unidad que se cifra de una vez (registro), así que, con muchos paquetes pequeños como en un juego, el costo por byte aumenta. En el handshake, que se hace una vez por conexión, el servidor firma con la clave del certificado y calcula el intercambio de claves (ECDHE). Un núcleo hace entre unas 1,100 (RSA 2048) y 18,000 (ECDSA P-256) firmas por segundo, y unos 9,000 intercambios de claves, así que la carga se nota cuando se concentran los inicios de sesión. - Fuentes: - [Introduction to Iris in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/introduction-to-iris-in-unreal-engine) · Epic Games · Mantener una sola copia cuantizada del estado a replicar reduce el trabajo costoso, que se comparte entre varias conexiones - [VALORANT's 128-Tick Servers](https://www.riotgames.com/en/news/valorants-128-tick-servers) · Riot Games · Comparar en cada frame las variables replicadas de cada cliente y agrupar los valores cambiados es lento porque lee memoria dispersa, y consume mucha CPU del servidor - [How "expensive" is crypto anyway?](https://blog.cloudflare.com/how-expensive-is-crypto-anyway/) · Cloudflare · Mediciones de BoringSSL: AES-128-GCM a unos 3.7 GB por segundo (varía mucho según el tamaño del registro); por núcleo y segundo, 1,120 firmas RSA 2048, 18,477 firmas ECDSA P-256 y 9,394 ECDHE P-256; en los servidores edge de Cloudflare, la biblioteca TLS consumía alrededor del 1.8% de la CPU - [perf-top(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-top.1.html) · perf · Muestra en tiempo real el peso de uso de CPU por función (símbolo) de un proceso en ejecución (-p) #### sp-crash · Crash del servidor · Server process crash Si el proceso del servidor muere por un error no controlado, todos los jugadores de ese servidor se desconectan a la vez. - Por qué → Efecto → En pantalla: Errores fatales como referencias a objetos que no existen (referencia nula), datos incorrectos o falta de memoria → Termina el proceso del servidor (o de la zona) → Desconexión simultánea de todos; el progreso desde el último guardado puede sufrir rollback - Síntomas: Desconexión, Acción perdida / rollback / Factores: Detención - A quién: Una zona o un canal, Todo el servidor / Cuándo: De vez en cuando, al azar, Al hacer ciertas acciones - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Analizar los crash dumps y corregir la causa, guardar con frecuencia. - Tareas (Equipo de infraestructura): Reiniciar automáticamente el proceso, preparar un entorno que recoja y conserve los crash dumps, alertar en cuanto el servidor se caiga. - En el gráfico: Desconexión masiva (Número de conexiones, reinicios del proceso) - Dónde mirar: Registros de core dump en coredumpctl list (hora, PID, señal de terminación) y registros de terminaciones anómalas y reinicios del gestor de servicios (systemd). En servidores Windows, los archivos de volcado que deja WER - Se confirma si: A la hora en que las conexiones caen de golpe casi a 0 hay una terminación anómala del proceso del servidor del juego y un core dump - Se descarta si: Si el proceso sigue vivo pero las conexiones se cortaron, apunta a los equipos de red o a los timeouts por inactividad. Si hay un registro de reinicio por el watchdog tras una detención larga, apunta a un bucle infinito o a un deadlock - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Collecting User-Mode Dumps](https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps) · Microsoft · Configurar Windows Error Reporting (WER) para recopilar en local volcados completos o minivolcados cuando un programa en modo usuario hace crash - [systemd.service(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd.service.5.html) · systemd · Restart=on-failure reinicia automáticamente el servicio tras una terminación anómala, una terminación por señal (incluidos los core dumps) o un timeout del watchdog; recomendado para servicios de larga duración - [coredumpctl(1) — Linux manual page](https://man7.org/linux/man-pages/man1/coredumpctl.1.html) · systemd · Consultar con list los core dumps guardados por systemd-coredump; muestra la hora del crash, el PID y la señal que lo provocó #### sp-threadpool · Agotamiento del pool de hilos · Thread pool starvation Si todos los hilos de trabajo que procesan tareas quedan atados a trabajos lentos, las solicitudes nuevas esperan indefinidamente. - Por qué → Efecto → En pantalla: Los hilos de trabajo quedan atados esperando respuestas de API externas o de la BD → No quedan hilos libres para asignar a las solicitudes nuevas → Carga infinita en funciones concretas, como el inicio de sesión o la tienda - Síntomas: No conecta / carga infinita, Input lag, Congelamiento / Factores: Detención - A quién: Solo una función, Todo el servidor / Cuándo: Cuando se junta mucha gente, Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Poner timeouts a las llamadas lentas, separar pools de hilos por función, pasar a asíncrono. - En el gráfico: Topa con el límite (Hilos del pool y longitud de su cola, tiempo de procesamiento de solicitudes) - Dónde mirar: En .NET, número de hilos del pool y longitud de la cola en dotnet-counters monitor (dotnet.thread_pool.thread.count y dotnet.thread_pool.queue.length desde .NET 9; ThreadPool Thread Count y ThreadPool Queue Length en la 8 y anteriores), y dónde esperan los hilos de trabajo con dotnet-stack. En la JVM y en servidores nativos, lo mismo con un volcado de hilos - Se confirma si: El uso de CPU está muy por debajo del 100%, pero el número de hilos crece despacio sin parar o se queda en el tope, la cola se acumula y la mayoría de los workers esperan la respuesta de la misma llamada externa (BD, HTTP) - Se descarta si: Si la cola está vacía y aun así va lento, el lento es el propio destino de las llamadas: apunta a “Fallo en cascada” o a “Dependencia de servicios externos” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Si la recepción de paquetes y la lógica del juego comparten el mismo pool de hilos de trabajo, en cuanto unas pocas tareas lentas ocupan todos los workers, se detiene el procesamiento de paquetes de todo el servidor. - Casos reales: riot-euw-2021 - Fuentes: - [Debug ThreadPool Starvation](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-threadpool-starvation) · Microsoft · Si no quedan hilos en el pool y las tareas nuevas esperan, las respuestas se vuelven lentas; la causa es código bloqueante que retiene hilos. En dotnet-counters, si la CPU está muy por debajo del 100% y dotnet.thread_pool.thread.count crece despacio sin parar, es señal de agotamiento (dotnet.thread_pool.queue.length también suele ser grande); con dotnet-stack se ve dónde esperan los hilos - [Avoiding insurmountable queue backlogs](https://d1.awsstatic.com/builderslibrary/pdfs/avoiding-insurmountable-queue-backlogs.pdf) · AWS · Concurrencia = tasa de llegada × latencia (ley de Little). Con 100 solicitudes por segundo, si la latencia pasa de 100 ms a 10 segundos, los hilos necesarios pasan de 10 a 1,000 y el pool se agota - [Bulkhead Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead) · Microsoft Azure · Si cada destino de llamadas tiene su propio pool de conexiones e hilos, el fallo de un destino solo bloquea ese pool - [.NET runtime metrics](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics-runtime) · .NET · dotnet.thread_pool.thread.count (hilos del pool) y dotnet.thread_pool.queue.length (tareas en espera) existen desde .NET 9 - [Well-known EventCounters in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/available-counters) · Microsoft · ThreadPool Thread Count (threadpool-thread-count) y ThreadPool Queue Length (threadpool-queue-length) en .NET 8 y anteriores #### sp-infinite-loop · Bucles infinitos y lógica desbocada · Infinite loop / runaway logic Si por un bug un tick no termina nunca, el servidor se detiene y el watchdog lo reinicia a la fuerza. - Por qué → Efecto → En pantalla: Un bucle que no termina por una condición errónea, o una recursión desbocada → El tick no termina y el servidor se detiene → Congelamiento y después desconexión de todos los jugadores - Síntomas: Congelamiento, Desconexión / Factores: Detención - A quién: Una zona o un canal, Todo el servidor / Cuándo: Al hacer ciertas acciones, De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Poner un tope a las iteraciones, tener un watchdog, hacer pruebas que reproduzcan las entradas problemáticas. - En el gráfico: Desconexión masiva (Número de conexiones, CPU por hilo) - Dónde mirar: CPU por hilo durante la detención con pidstat -t 1, y en qué función gira el hilo que está al 100% con perf top -t (ID del hilo) o gdb. Si ya se reinició, registros de timeout del watchdog (WatchdogSec de systemd, fallos de la sonda de liveness de Kubernetes) - Se confirma si: Mientras el servidor está detenido, un hilo del juego está pegado al 100% de CPU y su pila sigue girando dentro de la misma función o bucle - Se descarta si: Si la CPU está cerca de 0 durante la detención, apunta a un deadlock o a la espera de una respuesta externa - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [systemd.service(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd.service.5.html) · systemd · WatchdogSec=: si el servicio no envía la señal de que sigue vivo (WATCHDOG=1) en el tiempo fijado, se considera fallido y se termina; se reinicia automáticamente según el ajuste Restart= - [Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/workloads/pods/probes/) · Kubernetes · Detectar con una sonda de liveness un proceso que se ejecuta pero no avanza y reiniciarlo; por defecto, se comprueba cada 10 segundos y se reinicia tras 3 fallos seguidos - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -t muestra también las estadísticas por hilo del proceso (uso de CPU, entre otras) - [perf-top(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-top.1.html) · perf · Muestra en tiempo real el peso de uso de CPU por función (símbolo) de un hilo (-t) o proceso (-p) en ejecución #### sp-hot-entity · Combate concentrado en un solo objetivo (world boss) · Hot entity / combat event fan-out Cuando cientos de jugadores golpean a la vez a un mismo jefe, el cálculo de ese único jefe se concentra en un punto y la información de cada golpe se envía a todos los que lo ven. - Por qué → Efecto → En pantalla: Cientos de jugadores usan sin parar habilidades, buffs y debuffs sobre un mismo jefe → Los cálculos de vida, lista de aggro y debuffs del jefe se concentran en un punto, y por cada golpe se envían paquetes de números de daño y efectos a todos los que lo ven → Las habilidades entran tarde y los números de daño aparecen de golpe; cámara lenta solo alrededor del jefe - Síntomas: Input lag, Cámara rápida, Cámara lenta / Factores: Detención, Latencia - A quién: Una zona o un canal / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Agrupar u omitir los números de daño y los efectos de otros jugadores, poner un tope a los debuffs sobre un mismo objetivo, repartir el procesamiento de golpes entre varios ticks. - Cifras de referencia: Si 800 jugadores golpean 2 veces por segundo, son 1,600 golpes por segundo. Avisar de todos ellos a los 800 que lo ven supone 1.28 millones de mensajes por segundo. - En el gráfico: Sube con la carga (Tiempo de tick del servidor, mensajes enviados) - Dónde mirar: Tiempo de tick y paquetes enviados durante la pelea contra el jefe, junto a los jugadores que hay alrededor del jefe y, si es posible, eventos por segundo (golpes, buffs, debuffs) por objetivo - Se confirma si: Al aumentar los jugadores alrededor del jefe, el tiempo de tick y el volumen enviado se disparan, y el jefe tiene decenas de veces más eventos por segundo que cualquier otro objetivo - Se descarta si: Si con solo juntarse en un lugar, haya jefe o no, todo va igual de lento, apunta al cálculo de visibilidad o a “Explosión de broadcast” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [HED-GP Technical Retrospective: What a HED-ache](https://www.eveonline.com/news/view/what-a-hed-ache) · CCP Games · Incluso un solo ataque debe comunicarse a todos los clientes que lo ven, lo que genera una carga O(n²) de n jugadores avisando a n, y los ataques con drones, que generan muchos mensajes, hacen crecer esta carga aún más rápido #### sp-spawn-burst · Avalancha de spawns al entrar en una zona concurrida · Spawn burst when entering a crowd Al teletransportarse a un pueblo lleno de gente, el servidor tiene que enviar de golpe la apariencia, el equipamiento y el estado de los cientos de jugadores que ahora son visibles. - Por qué → Efecto → En pantalla: El jugador aparece de repente en un lugar concurrido al teletransportarse, al conectarse o al cambiar de canal → Se genera y se envía de una vez la información completa de cientos de jugadores, y tu PC también la carga de una vez → Una pausa breve justo al llegar; los personajes aparecen tarde, uno a uno, y los inputs responden tarde - Síntomas: Congelamiento, Input lag, Cámara rápida / Factores: Detención, Latencia - A quién: Solo yo, Una zona o un canal / Cuándo: Al moverse o cambiar de zona, Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: enviar por orden de cercanía y en varios ticks, cachear la información de apariencia. Cliente: recibir los datos por adelantado durante la pantalla de carga, crear los personajes recibidos repartidos en varios frames. - Cifras de referencia: Si la información de apariencia, equipamiento y buffs de un jugador ocupa 300 bytes, 500 jugadores son unos 150 KB. De golpe llega decenas de veces lo que se envía normalmente en un tick (unos pocos KB). - En el gráfico: Avalancha tras la apertura (Bytes enviados por conexión, tiempo de frame del cliente) - Dónde mirar: Bytes y paquetes enviados a esa conexión durante los primeros segundos tras llegar a un lugar concurrido (logs del servidor) y tiempo de frame del cliente (net graph, logs del cliente) - Se confirma si: Justo al llegar, lo enviado a esa conexión se dispara a decenas de veces lo normal de un tick y luego baja, y en el mismo momento hay un pico en el tiempo de frame del cliente - Se descarta si: Si se detiene igual al moverse a un lugar poco concurrido, apunta a “Cambio de zona (traspaso entre servidores)” o a la carga en el cliente - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Detailed Actor Replication Flow in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/detailed-actor-replication-flow-in-unreal-engine) · Epic Games · Al abrir por primera vez el canal de un actor se envía también información como la posición y la rotación iniciales, y si la conexión se satura, los actores restantes se aplazan al siguiente tick - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Se asigna prioridad según la distancia y la dirección de la mirada, y se envían primero los actores cercanos y visibles #### sp-entity-buildup · Acumulación de entidades (objetos e invocaciones sin limpiar) · Entity / timer buildup over uptime Si los objetos tirados en el suelo, las invocaciones y los temporizadores terminados que deberían desaparecer no se limpian y se acumulan, el trabajo de cada tick crece cuanto más tiempo lleva encendido el servidor. - Por qué → Efecto → En pantalla: Los objetos del suelo, las invocaciones, los temporizadores vencidos y los datos de grupos vacíos no se borran a tiempo → Las listas que se recorren en cada tick se alargan día a día → Justo después del mantenimiento todo va bien, pero al cabo de unos días ese servidor o esa zona va cada vez más pesado - Síntomas: Cámara lenta, Tirones, Input lag / Factores: Detención - A quién: Todo el servidor, Una zona o un canal / Cuándo: Cuanto más tiempo lleva encendido - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Registrar como métrica el número de entidades por zona y seguir su tendencia, dar a cada entidad una vida útil y un tope de cantidad, limpiar periódicamente. - Cifras de referencia: En un servidor que recorre todas las entidades una vez por tick, si el número de entidades se duplica, el tiempo de tick de esa parte también se duplica. - En el gráfico: Diente de sierra (Entidades por zona, tiempo de tick del servidor) - Dónde mirar: Entidades por zona y servidor (objetos del suelo, invocaciones, temporizadores) y tiempo de tick en un periodo más largo que el ciclo de mantenimiento (varias semanas) - Se confirma si: El número de entidades y el tiempo de tick empiezan bajos tras el mantenimiento, suben día a día y caen de golpe en cada mantenimiento o reinicio, una y otra vez, mientras la memoria sobra - Se descarta si: Si el tick no cambia y solo sube la memoria sin parar, apunta a “Fuga de memoria” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Como la fuga de memoria, empeora cuanto más tiempo lleva encendido el servidor, con una diferencia: la memoria sobra y solo crece el tiempo de tick. Si el gráfico del número de entidades tiene forma de diente de sierra al ritmo de los mantenimientos, es este caso. - Fuentes: - [Actor Ticking in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-ticking-in-unreal-engine) · Epic Games · Si no se fija un intervalo, los actores y componentes ejecutan su tick una vez por frame, y se puede desactivar el tick si no hace falta - [AActor::SetLifeSpan](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/AActor/SetLifeSpan) · Epic Games · Si se fija una vida útil a un actor, se destruye automáticamente al expirar #### sp-patch-traffic · Cambio del patrón de tráfico tras un parche · Patch changes traffic pattern Si nuevo contenido, efectos o campos sincronizados aumentan el tamaño y la frecuencia de los paquetes, un servidor que iba bien empieza a chocar tras el parche con los límites de MTU, ancho de banda o número de paquetes. - Por qué → Efecto → En pantalla: El parche añade efectos de habilidades, campos sincronizados o datos de objetos, y los paquetes se vuelven más grandes o más frecuentes → Los paquetes grandes superan la MTU y se fragmentan, y el volumen añadido choca con el ancho de banda, el límite de PPS de la nube o el búfer de envío → Desde el parche, teletransporte, habilidades que no salen e input lag en los lugares concurridos. La pérdida aumenta aunque no se haya cambiado nada en la infraestructura - Síntomas: Teletransporte, Acción perdida / rollback, Input lag / Factores: Pérdida de paquetes, Latencia - A quién: Todo el servidor, Una zona o un canal, Una región o un ISP / Cuándo: Cuando se junta mucha gente, Horas pico de la noche, Siempre - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura), Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Dividir los paquetes por cuenta propia en 1,200 bytes o menos, enviar solo los cambios de los nuevos campos sincronizados y bajar su frecuencia según la distancia y la importancia, comparar antes del despliegue, en un servidor de pruebas, los paquetes y bytes por segundo por jugador y el tamaño del paquete más grande con la build anterior, registrar la versión de la build en las métricas de tráfico. - Tareas (Equipo de infraestructura): Servidores/SO: marcar la hora del despliegue en los gráficos y comparar antes y después los paquetes y bytes por segundo por jugador y el tamaño medio de paquete, alertar con los contadores de límite superado de la instancia, pasar a una instancia mayor si hace falta. Red: revisar los límites de procesamiento de los firewalls, balanceadores de carga y dispositivos de protección DDoS, y si bloquean fragmentos. - Cifras de referencia: Lo seguro para paquetes UDP es 1,200 bytes o menos; la MTU de una ruta por internet suele ser de 1,500 bytes, y menor al pasar por túneles (1,476 bytes en un túnel GRE). Los paquetes que superan la MTU de la ruta se fragmentan o se descartan, y en un paquete fragmentado basta con perder un fragmento para perderlo entero. Si los paquetes por segundo de cada jugador suben un 20%, los de todo el servidor también suben un 20%, y una instancia que trabajaba cerca del límite lo supera enseguida. - En el gráfico: Salto en escalón (Paquetes y bytes por segundo por jugador, tamaño medio de paquete) - Dónde mirar: Paquetes y bytes por segundo de la NIC del servidor (rxpck/s, txpck/s, rxkB/s y txkB/s de sar -n DEV; en EC2, NetworkPacketsOut y NetworkOut) divididos por los jugadores conectados a la vez, comparando antes y después de la hora del despliegue. Tamaño medio de paquete = bytes ÷ paquetes; la distribución de tamaños, con las estadísticas Packet Lengths de Wireshark sobre una captura de paquetes - Se confirma si: Desde justo después del despliegue, los paquetes y bytes por jugador o el tamaño medio de paquete suben un escalón y se quedan ahí, y desde esa misma hora aumentan los fragmentos creados por el servidor (fragcrt/s de sar -n IP) o los contadores de límite superado de la instancia (pps_allowance_exceeded y bw_out_allowance_exceeded de ENA de AWS) - Se descarta si: Si el patrón de tráfico es igual antes y después del despliegue y solo aumentaron la latencia y la pérdida, revisar los cambios de infraestructura de esa misma hora (configuración, rutas, dispositivos, actualizaciones del SO o del kernel) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Cuando llega un reporte de que “antes del parche iba bien”, esta es la causa del lado del juego que hay que revisar primero, junto con los cambios de infraestructura. Aunque las notas del parche no mencionen cambios de red, un solo efecto o campo sincronizado nuevo se multiplica por cientos de jugadores en un lugar concurrido. Dónde choca en realidad el tráfico añadido se trata en “Fragmentación IP de paquetes UDP”, “Límite de PPS de la nube superado”, “Saturación del ancho de banda de la NIC”, “Búferes de socket del kernel insuficientes” y “Límite de procesamiento superado en dispositivos intermedios (firewall, IPS, protección DDoS)”. Esta entrada cubre el caso en que el punto de partida que llevó a ese límite es un parche del juego, así que, antes de subir el límite, hay que reducir el tráfico que añadió el parche. Si a la misma hora también se actualizaron el SO o el kernel, se distingue de “Cambios de rendimiento tras actualizar el SO, el kernel, los drivers o el firmware” comprobando si cambió el tráfico por jugador. - Fuentes: - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Las aplicaciones UDP no deberían enviar (SHOULD NOT) datagramas que superen la MTU de la ruta; si se pierde un fragmento, se pierde el paquete fragmentado entero, y algunos NAT y firewalls descartan todos los fragmentos - [RFC 8899: Packetization Layer Path MTU Discovery for Datagram Transports](https://www.rfc-editor.org/rfc/rfc8899) · IETF · Se recomiendan 1,200 bytes como tamaño seguro básico (BASE_PLPMTU) para transportes de datagramas como UDP - [Maximum transmission unit and maximum segment size](https://developers.cloudflare.com/magic-transit/reference/mtu-mss/) · Cloudflare · MTU de ruta por internet: 1,500; al pasar por un túnel GRE: 1,476 - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · pps_allowance_exceeded y bw_out_allowance_exceeded: paquetes encolados o descartados por superar los límites de PPS y de ancho de banda de envío de la instancia - [sar(1) — Linux manual page](https://man7.org/linux/man-pages/man1/sar.1.html) · sysstat · rxpck/s y txpck/s (paquetes por segundo) y rxkB/s y txkB/s (KB por segundo) de sar -n DEV; fragcrt/s (fragmentos IP creados por segundo, ipFragCreates) de sar -n IP - [CloudWatch metrics that are available for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · NetworkPacketsOut (paquetes enviados por la instancia por todas sus interfaces de red) y NetworkOut (bytes enviados) - [8.7. Packet Lengths](https://www.wireshark.org/docs/wsug_html_chunked/ChStatPacketLengths.html) · Wireshark · Muestra los paquetes capturados agrupados por rangos de longitud, con su número, media, mínimo y máximo ### L10 Memoria (causas: 9) #### mem-gc · Pausa stop-the-world del GC en el servidor · Stop-the-world GC pause Un servidor en Java o C# detiene todos sus hilos para recolectar la basura (stop-the-world), y mientras tanto todo el servidor queda detenido. - Por qué → Efecto → En pantalla: El heap se llena y arranca el GC → Se detienen todos los hilos del juego mientras se recolecta (cuantos más datos vivos, más tarda) → Congelamiento simultáneo en todo el servidor y después cámara rápida - Síntomas: Congelamiento, Cámara rápida / Factores: Detención - A quién: Todo el servidor / Cuándo: A intervalos regulares, Cuanto más tiempo lleva encendido - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Elegir de forma explícita en las opciones de arranque un GC de pausas cortas (ZGC, Shenandoah o G1 con un objetivo de pausa más bajo), reducir las asignaciones, ajustar el tamaño del heap. - Tareas (Equipo de infraestructura): Elegir instancias con memoria suficiente para un heap holgado, asignar a los contenedores al menos 2 CPU y unos 1.8 GB de memoria (con menos, JDK 26 y anteriores eligen Serial GC por defecto), monitorear el tiempo de pausa del GC. - Cifras de referencia: Un Minor GC, que solo recolecta los objetos nuevos (generación joven), tarda de unos pocos a decenas de ms. Un Full GC, que recolecta todo un heap con varios GB de datos vivos, puede superar 1 segundo. ZGC se queda por debajo de 1 ms casi sin importar el tamaño del heap, y Shenandoah también tiene pausas cortas porque no crecen con el tamaño del heap. - En el gráfico: Picos periódicos (Tiempo de tick del servidor, tiempo de pausa del GC) - Dónde mirar: Activar el log del GC y superponer la hora y la duración de cada pausa al gráfico del tiempo de tick del servidor. En Java, las líneas Pause de la opción de arranque -Xlog:gc* (-XX:+PrintGCDetails en JDK 8 y anteriores); en .NET, la métrica de pausa del GC de dotnet-counters (dotnet.gc.pause.time desde .NET 9; % Time in GC since last GC en .NET 8 y anteriores); en Go, la línea que GODEBUG=gctrace=1 escribe en cada GC - Se confirma si: Los picos de tick coinciden con las pausas del GC y duran más o menos lo mismo que ellas. Todas las zonas y canales del servidor tienen el pico en el mismo instante - Se descarta si: Si hay picos de tick sin pausas largas en el log del GC, apunta a otra causa (locks, llamadas síncronas, escrituras en disco). Si el pico es en una sola zona, más probable: GC del motor de scripts (mem-script-gc) o carga de esa zona - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: En Java, G1 tiene por defecto un objetivo de 200 ms por pausa, lo que equivale a 4 ticks en un servidor de 20 ticks. Si un contenedor recibe menos de 2 CPU o menos de unos 1.8 GB de memoria, Java (JDK 26 y anteriores) elige como GC por defecto Serial GC, que recolecta con un solo hilo, y las pausas se alargan mucho. Los servidores en C# (.NET) suelen activar el GC de servidor y el GC en segundo plano, pero las recolecciones de las generaciones 0 y 1 (Gen0 y Gen1), donde están los objetos nuevos, y el Full GC con compactación siguen deteniendo todos los hilos. En Go las pausas suelen durar menos de 1 ms, pero si hay muchas asignaciones, quien pide memoria tiene que asumir parte del trabajo del GC y el tick se ralentiza. Con cualquier GC, si se asigna más rápido de lo que se recolecta, al final el hilo del juego se detiene: G1 pasa a un Full GC y ZGC detiene el hilo que pidió memoria hasta que termina la recolección. - Casos reales: riot-euw-2021 - Fuentes: - [Garbage-First (G1) Garbage Collector](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-first-g1-garbage-collector1.html) · Oracle · Objetivo de pausa de G1 de 200 ms por defecto (MaxGCPauseMillis); si la memoria se agota durante la recolección, pasa a un Full GC que detiene y compacta todo el heap - [JEP 523: Make G1 the Default Garbage Collector in All Environments](https://openjdk.org/jeps/523) · OpenJDK · Hasta ahora, con 1 CPU o menos de 1,792 MB de memoria se elegía Serial GC por defecto; desde JDK 27, G1 es el predeterminado en cualquier entorno - [JEP 439: Generational ZGC](https://openjdk.org/jeps/439) · OpenJDK · Pausas de ZGC de 1 ms o menos e independientes del tamaño del heap; pausas de G1 de varios ms a varios segundos. Si se asigna más rápido de lo que se libera, hay riesgo de detenciones por asignación (allocation stall) - [JEP 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)](https://openjdk.org/jeps/189) · OpenJDK · Las pausas de Shenandoah duran más o menos lo mismo con un heap de 200 MB que con uno de 200 GB - [Background garbage collection](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/background-gc) · .NET · El GC en segundo plano solo se aplica a las recolecciones de la generación 2; las de las generaciones 0 y 1 (GC en primer plano) detienen todos los hilos administrados - [A Guide to the Go Garbage Collector](https://go.dev/doc/gc-guide) · Go · El GC de Go hace la mayor parte de su trabajo de forma concurrente y solo tiene pausas totales breves; si hay muchas asignaciones, las goroutines asumen parte del trabajo del GC (assist) y eso genera latencia - [JEP 271: Unified GC Logging](https://openjdk.org/jeps/271) · OpenJDK · Desde JDK 9, el log del GC se reimplementó con el logging unificado (-Xlog); -Xlog:gc escribe una línea por GC, como el antiguo -XX:+PrintGC - [The java Command](https://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html) · Oracle · Tabla de equivalencias entre las antiguas opciones de log del GC y -Xlog: -XX:+PrintGCDetails pasa a ser -Xlog:gc* - [dotnet-counters diagnostic tool](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters) · .NET · Desde .NET 9 se muestra con los medidores de System.Runtime (dotnet.gc.pause.time, entre otros); en .NET 8 y anteriores, con los antiguos EventCounter (% Time in GC since last GC, entre otros) - [runtime package](https://pkg.go.dev/runtime) · Go · GODEBUG=gctrace=1: una línea por GC con el tiempo de reloj de pared de cada fase, el tamaño del heap al inicio y al final del GC y el heap objetivo #### mem-script-gc · Pausa del GC en el motor de scripts · Scripting VM GC (Lua, etc.) Aunque el servidor esté escrito en C++, si las misiones, la IA y las habilidades se ejecutan en scripts como Lua, la zona se detiene mientras corre el GC del motor de scripts. - Por qué → Efecto → En pantalla: En cada zona, el motor de scripts ejecuta misiones, IA y eventos, y crea una gran cantidad de objetos temporales → Cuando el GC del motor de scripts recolecta mucho de una vez, el tick de esa zona se detiene → Tirones periódicos solo en ciertas zonas o durante ciertos eventos - Síntomas: Tirones, Congelamiento / Factores: Detención - A quién: Una zona o un canal / Cuándo: Cuando se junta mucha gente, A intervalos regulares - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Configurar el GC incremental o generacional, avanzar el GC un poco en cada tick, reducir los objetos temporales de los scripts. - Cifras de referencia: Si el heap de scripts crece hasta cientos de MB, una recolección hecha de golpe (con la recolección incremental desactivada, o una recolección completa en modo generacional) puede tardar de decenas a cientos de ms. - En el gráfico: Picos periódicos (Tiempo de tick por zona, memoria del motor de scripts) - Dónde mirar: Registrar en cada tick el tiempo de tick de cada zona y el uso de memoria de su motor de scripts (en Lua, collectgarbage("count")), y superponerlos en un mismo gráfico - Se confirma si: Los momentos en que la memoria de scripts cae de golpe (una recolección hecha de una vez) coinciden con los picos de tick de esa zona, y las demás zonas están bien - Se descarta si: Si hay picos sin cambios en la memoria de scripts, apunta a la carga o a locks de esa zona. Si todas las zonas del servidor tienen picos a la vez: GC del servidor (mem-gc) o swap (mem-swap) - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Lua 5.4 Reference Manual](https://www.lua.org/manual/5.4/manual.html) · Lua.org · El modo incremental divide la recolección en pasos pequeños intercalados con la ejecución (con pasos grandes, se detiene todo); la recolección major del modo generacional recorre todos los objetos y lo detiene todo; collectgarbage("count") devuelve la memoria total que usa Lua (KB) #### mem-alloc · Avalancha de asignaciones · Allocation storms Si durante un evento se crean muchísimos objetos temporales, el GC se ejecuta mucho más a menudo que de costumbre. - Por qué → Efecto → En pantalla: Explosión de objetos temporales por los drops de objetos, los logs de combate y las recompensas de eventos → El GC se ejecuta varias veces más a menudo, y los objetos que no llegan a descartarse a tiempo pasan a la generación vieja (Old), lo que también adelanta el Full GC → Tirones periódicos solo durante los eventos - Síntomas: Tirones, Congelamiento / Factores: Detención - A quién: Todo el servidor, Una zona o un canal / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Usar pools de objetos y búferes reutilizables, perfilar las asignaciones. - En el gráfico: Sube con la carga (Número de GC, velocidad de asignación) - Dónde mirar: Contar los GC por minuto en el log del GC (Java -Xlog:gc, Go GODEBUG=gctrace=1); en .NET, la cantidad asignada y el número de GC en dotnet-counters (dotnet.gc.heap.total_allocated y dotnet.gc.collections desde .NET 9; Allocation Rate y Gen 0 GC Count en .NET 8 y anteriores). Todo superpuesto a los jugadores conectados y a la hora de los eventos - Se confirma si: Al empezar un evento, la velocidad de asignación y el número de GC suben más deprisa que el número de jugadores, y las pausas cortas se vuelven frecuentes. Al terminar el evento todo vuelve a la normalidad - Se descarta si: Si el número de GC no cambia pero cada pausa dura más, han aumentado los datos vivos (mem-gc-thrash, mem-leak) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Garbage Collector Implementation](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-collector-implementation.html) · Oracle · Cuando la generación joven (Young) se llena hay un minor GC, y parte de los objetos supervivientes pasa a la generación vieja (Old); cuando la vieja se llena, se recolecta todo el heap (mucho más lento que un minor); -Xlog:gc escribe una línea por GC - [A Guide to the Go Garbage Collector](https://go.dev/doc/gc-guide) · Go · Cuanto mayor es la velocidad de asignación, más frecuentes son los ciclos de GC; GODEBUG=gctrace=1 imprime la traza del GC - [dotnet-counters diagnostic tool](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters) · .NET · Desde .NET 9 se muestra como dotnet.gc.heap.total_allocated y dotnet.gc.collections; en .NET 8 y anteriores, como Allocation Rate y Gen 0 GC Count #### mem-leak · Fuga de memoria · Memory leak La memoria que no se libera se acumula poco a poco y, al cabo de unos días, termina en un GC excesivo, swap o un cierre forzado. - Por qué → Efecto → En pantalla: No se libera la información de los personajes que ya se desconectaron ni los manejadores de eventos (event handlers) → La memoria libre baja a lo largo de varios días → Va bien justo después del mantenimiento, cada día hay más lag y al final el servidor se cae - Síntomas: Cámara lenta, Congelamiento, Desconexión / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuanto más tiempo lleva encendido, Horas pico de la noche - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Analizar volcados del heap (heap dumps), hacer pruebas de carga de larga duración. - Tareas (Equipo de infraestructura): Monitorear la tendencia del uso de memoria por proceso y configurar alertas. - En el gráfico: Subida gradual (Memoria del proceso (RSS), heap justo después del GC) - Dónde mirar: Memoria del proceso del servidor del juego (RSS de pidstat -r) a lo largo de varios días; en servidores con GC, el heap que queda justo después del GC. En Java, el valor posterior al GC de los dos usos (antes y después) que aparecen en las líneas de -Xlog:gc; en .NET, el tamaño del heap tras el GC en dotnet-counters (dotnet.gc.last_collection.heap.size desde .NET 9; GC Heap Size en .NET 8 y anteriores) - Se confirma si: El heap que queda justo después del GC (la línea base) sube cada día desde el reinicio y no baja ni siquiera de madrugada, cuando hay pocos jugadores - Se descarta si: Si la línea base del heap es plana y solo sube el RSS, apunta a fragmentación (mem-fragment) o a memoria nativa. Si sube y baja con el número de jugadores, es uso normal - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Si el servidor se reinicia cada semana en el mantenimiento programado, la fuga queda oculta y puede pasar mucho tiempo sin detectarse. Es habitual que aparezca de repente cuando se aplaza un mantenimiento o cuando un evento aumenta el número de jugadores. - Fuentes: - [Troubleshoot Memory Leaks](https://docs.oracle.com/en/java/javase/25/troubleshoot/troubleshooting-memory-leaks.html) · Oracle · Si la ejecución se vuelve cada vez más lenta, hay que sospechar de una fuga; al final la memoria se agota y el proceso termina de forma anómala. El dato clave para analizar una fuga es el volcado del heap - [Debug a memory leak in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-memory-leak) · .NET · Aunque haya GC, si se siguen referenciando objetos innecesarios hay fuga, con pérdida de rendimiento y OutOfMemoryException. Revisar la tendencia de la memoria y analizar volcados - [Garbage Collector Implementation](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-collector-implementation.html) · Oracle · Las líneas de -Xlog:gc tienen el formato “uso antes del GC->uso después del GC (tamaño del heap)” - [dotnet-counters diagnostic tool](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters) · .NET · Desde .NET 9 se muestra como dotnet.gc.last_collection.heap.size; en .NET 8 y anteriores, como GC Heap Size - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -r: RSS por proceso (memoria realmente cargada en la RAM) y fallos de página #### mem-gc-thrash · Thrashing del GC (heap casi lleno) · GC thrashing (heap nearly full) Cuando los datos vivos se acercan al límite del heap, el GC casi no encuentra nada que liberar y se repite sin parar. - Por qué → Efecto → En pantalla: Por el aumento de jugadores en un evento o por una fuga, los datos vivos llenan el heap casi hasta el límite → El GC apenas libera memoria y enseguida lanza otro Full GC; el GC se lleva la mayor parte de la CPU → Todo el servidor alterna cámara lenta y congelamientos durante varios minutos y acaba cerrándose por falta de memoria - Síntomas: Cámara lenta, Congelamiento, Desconexión / Factores: Detención - A quién: Todo el servidor / Cuándo: Horas pico de la noche, Cuando se junta mucha gente, Cuanto más tiempo lleva encendido - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Configurar el heap con holgura respecto a los datos vivos en el pico (normalmente el doble o más), reducir los datos que se referencian durante mucho tiempo y las fugas. - Tareas (Equipo de infraestructura): Configurar alertas sobre el porcentaje de tiempo en GC, reiniciar cuanto antes sin intentar aguantar, usar instancias con memoria de sobra para poder ampliar el heap. - Cifras de referencia: Si el GC consume más del 10% del tiempo de ejecución, normalmente se considera una señal de alarma. Algunos GC de Java lanzan un error de falta de memoria si dedican el 98% del tiempo al GC y apenas liberan memoria. - En el gráfico: Topa con el límite (Heap justo después del GC, porcentaje de tiempo en GC) - Dónde mirar: Cuánto se acerca al heap máximo el heap que queda justo después del GC y qué porcentaje del tiempo se dedica al GC. En Java, “después del GC (tamaño del heap)” en las líneas de -Xlog:gc y la frecuencia de las líneas Pause Full; en .NET, dotnet-counters (% Time in GC since last GC en .NET 8 y anteriores; incremento de dotnet.gc.pause.time desde .NET 9); en Go, el intervalo entre líneas de GODEBUG=gctrace=1 - Se confirma si: Incluso justo después del GC el heap sigue cerca del máximo, los Full GC se suceden uno tras otro y el porcentaje de tiempo en GC sube mucho más de lo normal (normalmente por encima del 10%). Mientras tanto, el tick de todo el servidor se ralentiza - Se descarta si: Si después del GC queda margen en el heap pero las pausas son largas, apunta al tipo o la configuración del GC (mem-gc) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [The Parallel Collector](https://docs.oracle.com/en/java/javase/25/gctuning/parallel-collector1.html) · Oracle · El Parallel GC lanza OutOfMemoryError si dedica más del 98% del tiempo total al GC y recupera menos del 2% del heap - [Garbage-First Garbage Collector Tuning](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-first-garbage-collector-tuning.html) · Oracle · Por defecto (GCTimeRatio=12), G1 dimensiona el heap para que el GC ocupe alrededor del 8% del tiempo total o menos; los Full GC causados por una ocupación del heap demasiado alta aparecen en el log como Pause Full (G1 Compaction Pause) - [A Guide to the Go Garbage Collector](https://go.dev/doc/gc-guide) · Go · Con el valor predeterminado GOGC=100, el heap objetivo es aproximadamente el doble del heap vivo; al chocar con el límite de memoria, el GC se ejecuta sin parar (thrashing); GODEBUG=gctrace=1 imprime la traza del GC - [Garbage Collector Implementation](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-collector-implementation.html) · Oracle · Las líneas de -Xlog:gc muestran el tipo de GC (Pause Young, Pause Full), “uso antes del GC->uso después del GC (tamaño del heap)” y el tiempo de pausa - [dotnet-counters diagnostic tool](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters) · .NET · Desde .NET 9 se muestra como dotnet.gc.pause.time; en .NET 8 y anteriores, como % Time in GC since last GC #### mem-swap · Swap · Swapping Cuando falta memoria y el SO envía una parte al disco, cada vez que se usa esa memoria hay que esperar a un disco más de 1,000 veces más lento. - Por qué → Efecto → En pantalla: La memoria usada supera la RAM física → El SO envía una parte al disco y la vuelve a leer cuando hace falta → El tick se dispara a cientos de ms y todos los jugadores del servidor sufren cámara lenta y congelamientos - Síntomas: Cámara lenta, Congelamiento / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuanto más tiempo lleva encendido, Horas pico de la noche - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Poner un tope al uso de memoria del proceso (tamaño del heap, entre otros) y revisar si hay fugas. - Tareas (Equipo de infraestructura): Configurar los servidores del juego para que no usen swap, responder con alertas de memoria, reservar RAM de sobra por encima del uso en el pico (sin swap, el proceso se cierra a la fuerza por OOM en cuanto falta memoria). - Cifras de referencia: Leer de la RAM tarda unos 100 ns; volver a leer de un SSD, unos 100 µs (1,000 veces más); de un disco en la nube al otro lado de la red, alrededor de 1 ms (10,000 veces), y de un HDD, 10 ms (100,000 veces). - En el gráfico: Subida gradual (Uso de swap, entradas y salidas de swap (swap in/out)) - Dónde mirar: Columnas si y so de vmstat 1 (cantidad leída del swap y enviada al swap por segundo), some y full de /proc/pressure/memory (porcentaje de tiempo detenido esperando memoria) y majflt/s de pidstat -r del proceso del servidor del juego (fallos de página que obligaron a leer del disco), superpuestos al tiempo de tick - Se confirma si: A la hora del lag, la columna si es mayor que 0, y majflt/s del servidor del juego y el valor full de memory suben a la vez - Se descarta si: Si las columnas si y so están en 0 y la presión de memoria (PSI) también está cerca de 0, la causa no es el swap. Si no hay swap pero suben majflt/s y el PSI, la memoria está agotada y se están volviendo a leer páginas de código: lo primero es liberar memoria - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Un servidor con GC recorre todo el heap al recolectar, así que, aunque solo una parte del heap esté en swap, un solo GC puede pasar a durar de varios segundos a decenas de segundos. Si se desactiva el swap, el proceso pasa directamente al cierre forzado (OOM) sin la etapa de lentitud por swap, por eso primero hay que asegurar memoria libre de sobra. Incluso sin swap, cuando la memoria está casi agotada el SO llega a descargar de la memoria las páginas de código del ejecutable para volver a leerlas después, y todo el servidor puede ir muy lento durante un buen rato antes del cierre forzado. - Fuentes: - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · “Numbers Everyone Should Know”: referencia a memoria principal 100 ns, búsqueda en disco 10 ms (datos de 2009) - [Documentation for /proc/sys/vm/](https://docs.kernel.org/admin-guide/sysctl/vm.html) · Linux kernel · swappiness: costo relativo del swap frente a la recuperación de páginas de archivo; el swap es E/S aleatoria y por eso es caro - [Concepts overview](https://docs.kernel.org/admin-guide/mm/concepts.html) · Linux kernel · Se recuperan las páginas de la caché de páginas que tienen su original en disco y las páginas que se pueden enviar al swap; si aun así no basta, el OOM killer mata un proceso - [Solidigm™ D7-P5520 and D7-P5620 Product Brief](https://www.solidigm.com/products/data-center/product-briefs/d7-p5520-p5620-product-brief.html) · Solidigm · Latencia del 99.99% (four-nines latency) de un SSD NVMe para servidores: 130 µs. Respalda que una lectura de SSD ronda los 100 µs - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · La latencia del disco estándar de la nube (gp3) es de unos pocos milisegundos (menos de 10 ms) - [vmstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/vmstat.8.html) · procps-ng · si: memoria leída del swap por segundo; so: memoria enviada al swap por segundo - [PSI - Pressure Stall Information](https://docs.kernel.org/accounting/psi.html) · Linux kernel · some (porcentaje de tiempo en que algunas tareas estuvieron detenidas) y full (porcentaje de tiempo en que todas las tareas estuvieron detenidas a la vez) de /proc/pressure/memory - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -r: majflt/s (fallos que obligaron a leer páginas del disco) #### mem-cache-miss · Fallo de caché · CPU cache misses Si los datos están dispersos por la memoria, la CPU tiene que ir cada vez hasta la RAM, que es lenta, y esperar. - Por qué → Efecto → En pantalla: Objetos dispersos y enlazados por punteros, a los que se accede sin orden → Como no están en la caché de la CPU, se leen de la RAM cada vez (alrededor de 100 veces más lento) → El mismo trabajo cuesta varias veces más tiempo de tick; en casos graves, cámara lenta - Síntomas: Cámara lenta / Factores: Detención - A quién: Todo el servidor / Cuándo: Siempre, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Colocar de forma contigua los datos que se usan juntos a menudo (diseño orientado a datos). - En el gráfico: Siempre alto (Tiempo de tick, uso de CPU) - Dónde mirar: Medir con perf stat -d -p PID sobre el proceso del servidor del juego las instrucciones por ciclo (insn per cycle) y los fallos de caché L1 y LLC, junto con el tiempo de tick y el uso de CPU - Se confirma si: La CPU está ocupada todo el tiempo, pero insn per cycle es bajo y hay muchos fallos de LLC. Se confirma si, en una build con otra disposición de los datos, el tiempo de tick con el mismo número de jugadores baja mucho - Se descarta si: Si el uso de CPU es bajo pero el tick va lento, apunta a esperas fuera de la CPU, como locks o E/S - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Caché L1 0.5 ns, caché L2 7 ns, memoria principal 100 ns (datos de 2009): ir hasta la RAM es uno o dos órdenes de magnitud más lento que la caché - [perf-stat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-stat.1.html) · perf · -p cuenta los eventos de hardware de un proceso en ejecución y muestra insn per cycle; -d añade los eventos de la caché de datos L1 y LLC #### mem-fragment · Fragmentación de memoria · Heap fragmentation Si al asignar y liberar memoria una y otra vez el espacio libre queda partido en trozos pequeños, el proceso ocupa mucha más memoria de la que realmente usa. - Por qué → Efecto → En pantalla: Varios hilos asignan y liberan durante mucho tiempo bloques de memoria de tamaños muy distintos → El espacio libre queda disperso en trozos pequeños que no se pueden devolver al SO, y el uso sigue creciendo como si fuera una fuga → Cuanto más tiempo lleva encendido, más lento va por el swap y la falta de memoria, hasta que se cierra a la fuerza - Síntomas: Cámara lenta, Desconexión / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuanto más tiempo lleva encendido - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Usar pools de memoria por tamaño y asignadores resistentes a la fragmentación (jemalloc, mimalloc, etc.). - En el gráfico: Subida gradual (Memoria del proceso (RSS)) - Dónde mirar: Levantar dos servidores con la misma build y, solo en uno, reducir el número de arenas de glibc con la variable de entorno MALLOC_ARENA_MAX o cambiar a otro asignador como jemalloc; comparar durante varios días el RSS de pidstat -r - Se confirma si: Con un número parecido de jugadores y entidades, solo en el servidor modificado el RSS deja de crecer o baja mucho - Se descarta si: Si sube igual después de cambiar de asignador: memoria que no se libera (mem-leak) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Tiene el mismo aspecto que una fuga, pero el análisis del heap no muestra ningún punto de fuga. El asignador predeterminado de Linux (glibc) lo sufre especialmente en servidores con muchos hilos, y a veces basta con cambiar de asignador para reducir mucho el uso de memoria. - Fuentes: - [mallopt(3) — Linux manual page](https://man7.org/linux/man-pages/man3/mallopt.3.html) · Linux man-pages · Para reducir la contención entre hilos, glibc malloc crea arenas hasta un múltiplo del número de CPU, y cuantas más arenas, más memoria usa (se limita con M_ARENA_MAX, también configurable con la variable de entorno MALLOC_ARENA_MAX) - [jemalloc memory allocator](https://jemalloc.net/) · jemalloc · Implementación de malloc de propósito general centrada en evitar la fragmentación y escalar con la concurrencia - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -r: RSS por proceso (memoria realmente cargada en la RAM) #### mem-numa · Acceso a memoria NUMA remota · Remote NUMA access En un servidor con dos CPU, el acceso a memoria se vuelve más lento cuando un hilo usa la memoria conectada a la otra CPU. - Por qué → Efecto → En pantalla: El hilo y su memoria quedan en sockets de CPU distintos → El acceso a memoria se vuelve más lento (1.5–2 veces, según el hardware) → Diferencias de rendimiento entre procesos en servidores con las mismas especificaciones - Síntomas: Cámara lenta / Factores: Detención - A quién: Todo el servidor / Cuándo: Siempre - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Fijar el proceso y su memoria a un mismo socket (numactl) y, en servidores con dos sockets, repartir los procesos del servidor del juego entre ambos. - En el gráfico: Alto solo en algunos (Tiempo de tick por proceso, memoria por nodo) - Dónde mirar: En qué nodo NUMA está la memoria del proceso del servidor del juego (numastat -p PID) y si aumentan numa_miss y other_node en numastat; compararlo con el nodo de la CPU en la que corre ese proceso - Se confirma si: Solo en los procesos lentos la mayor parte de la memoria está en un nodo distinto al de la CPU en la que corren, y la diferencia desaparece al relanzarlos con la CPU y la memoria fijadas a un mismo nodo con numactl - Se descarta si: Si va lento aunque la distribución por nodos sea igual que la de un proceso rápido, apunta a otra causa (vecino ruidoso, throttling de CPU, la carga de ese proceso) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [What is NUMA?](https://docs.kernel.org/mm/numa.html) · Linux kernel · La memoria de la misma celda es más rápida y tiene más ancho de banda; el acceso a la memoria de otra celda (remota) es más lento - [numactl(8) — Linux manual page](https://man7.org/linux/man-pages/man8/numactl.8.html) · numactl · --cpunodebind y --membind fijan la CPU y la memoria de un proceso a un nodo NUMA concreto - [numastat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/numastat.8.html) · numactl · Contadores numa_miss (asignación en un nodo distinto del deseado) y other_node (asignación en este nodo de un proceso que corre en otro nodo); -p muestra la memoria por nodo de un proceso ### L11 Disco (causas: 9) #### dk-sync-log · Escritura síncrona de logs · Synchronous logging Si el hilo del juego espera a que el disco termine cada línea de log, cuando el disco está ocupado el juego también se detiene. - Por qué → Efecto → En pantalla: Los logs de combate e intercambios se escriben directamente en archivo desde el hilo del juego → Si se exige escritura garantizada (fsync) o se llena el búfer de escritura del SO (caché de páginas), cada escritura tarda decenas de ms cuando el disco está ocupado → Tirones en los combates que generan muchos logs - Síntomas: Tirones, Congelamiento / Factores: Detención - A quién: Una zona o un canal, Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Pasar a logging asíncrono (búfer en memoria + hilo aparte), reducir el volumen de logs, no hacer fsync en el hilo del juego. - Tareas (Equipo de infraestructura): Ejecutar la rotación y compresión de logs con baja prioridad de E/S, poner los logs en un disco distinto del de los datos, monitorear la latencia de escritura en disco. - En el gráfico: Picos aleatorios (Tiempo de tick del servidor, latencia de escritura en disco) - Dónde mirar: w_await y aqu-sz de iostat -x 1 superpuestos al tiempo de tick; buscar con perf trace -p PID --duration 10 las llamadas write y fsync del servidor del juego que tardan más de 10 ms y el hilo que las hace - Se confirma si: En los picos de tick, las llamadas write y fsync del hilo del juego tardan decenas de ms y en ese momento también se dispara la latencia de escritura en disco. A menudo coincide con la rotación o la compresión de logs - Se descarta si: Si el hilo del juego no tiene llamadas al sistema largas y aun así hay picos de tick, apunta a otra causa (GC, locks, tick excedido). Si solo tarda el hilo dedicado a los logs, el juego no se ve afectado - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Normalmente el SO recibe primero las escrituras en memoria (caché de páginas) y las pasa al disco más tarde, así que una línea de log casi siempre termina al instante. Las detenciones aparecen cuando se exige escritura garantizada con fsync, cuando las escrituras pendientes superan el límite y el SO bloquea la llamada de escritura, o cuando se rota o se comprime el archivo de log. Por eso todo va bien la mayor parte del tiempo y los picos solo aparecen cuando el disco está ocupado. - Fuentes: - [fsync(2) — Linux manual page](https://man7.org/linux/man-pages/man2/fsync.2.html) · Linux man-pages · fsync envía los datos modificados hasta el disco (incluida su caché) y bloquea hasta que el dispositivo confirma que terminó - [Documentation for /proc/sys/vm/](https://docs.kernel.org/admin-guide/sysctl/vm.html) · Linux kernel · Cuando las escrituras pendientes (dirty) alcanzan dirty_ratio, el propio proceso que escribe tiene que encargarse de escribir en disco - [ionice(1) — Linux manual page](https://man7.org/linux/man-pages/man1/ionice.1.html) · util-linux · Las tareas con prioridad de E/S idle solo reciben tiempo de disco cuando ningún otro programa lo está usando - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: w_await (tiempo medio de servicio de las solicitudes de escritura, incluida la espera en la cola) y aqu-sz (longitud media de la cola, antes llamada avgqu-sz) - [perf-trace(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-trace.1.html) · perf · -p traza las llamadas al sistema de un proceso en ejecución; --duration muestra solo las que tardan más de los ms indicados #### dk-fsync · Avalancha de fsync · fsync storms Pedir que los datos se escriban en disco “con garantía” cuesta, según el disco, de 0.1 ms a decenas de ms por llamada, y si se acumulan las solicitudes, la cola se alarga. - Por qué → Efecto → En pantalla: Los guardados periódicos y las avalanchas de cierres de sesión concentran solicitudes de escritura garantizada → La cola del disco se alarga → Lag en cada guardado, retrasos al cerrar sesión o cambiar de canal - Síntomas: Tirones, Input lag / Factores: Detención, Latencia - A quién: Todo el servidor / Cuándo: A intervalos regulares, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura), Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Agrupar los guardados (varios guardados con un solo fsync), repartir los guardados en el tiempo. - Tareas (Equipo de infraestructura): Servidores/SO: usar SSD para servidores con protección contra cortes de energía, monitorear la longitud de la cola del disco y la latencia de fsync. Servidores de BD: si los guardados van a la BD, poner también el disco de logs de la BD en ese tipo de SSD, monitorear la latencia de commit. - Cifras de referencia: El tiempo por llamada depende del hardware, pero a grandes rasgos: SSD para servidores (con protección contra cortes de energía), 0.1 ms; SSD normal, de 1 a varios ms; disco en la nube, 1–2 ms; HDD, 10 ms o más. Si un solo hilo espera las llamadas de una en una, un HDD no llega ni a 100 por segundo. - En el gráfico: Picos periódicos (Longitud de la cola del disco, latencia de flush y de escritura) - Dónde mirar: f/s y f_await de iostat -x 1 (número de flushes que procesó el disco y cuánto tardaron), y w/s, aqu-sz y w_await, superpuestos a la hora de los guardados periódicos y de los cierres de sesión. Las versiones antiguas de sysstat muestran aqu-sz como avgqu-sz. En discos en la nube, VolumeQueueLength y VolumeAvgWriteLatency de EBS - Se confirma si: En cada guardado y en cada avalancha de cierres de sesión, el número de flushes y la longitud de la cola se disparan a la vez, y w_await y f_await multiplican varias veces su valor normal. En esos momentos los guardados y los cambios de canal van lentos - Se descarta si: Si la cola se dispara a horas sin relación con guardados ni cierres de sesión, apunta a copias de seguridad o compresión (dk-backup) o al límite de IOPS (dk-iops). Si el número de flushes no cambia pero todo va más lento, más probable: créditos de ráfaga agotados (dk-burst) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [fsync(2) — Linux manual page](https://man7.org/linux/man-pages/man2/fsync.2.html) · Linux man-pages · fsync vacía también la caché del disco y bloquea hasta que el dispositivo confirma que terminó - [Reliability (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-reliability.html) · PostgreSQL · Los discos SATA normales y muchos SSD tienen una caché de escritura que se pierde con un corte de energía; para tener escritura garantizada hace falta una caché con batería o con protección contra cortes de energía - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · Latencia del disco estándar de la nube (gp3) de unos pocos milisegundos (menos de 10 ms); io2 Block Express, menos de 500 µs de media con E/S de 16 KiB - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Una búsqueda en HDD: 10 ms - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: f/s y f_await (número de solicitudes de flush que procesó el disco y su tiempo medio), w/s, w_await, aqu-sz (antes llamada avgqu-sz) - [Amazon CloudWatch metrics for Amazon EBS](https://docs.aws.amazon.com/ebs/latest/userguide/using_cloudwatch_ebs.html) · AWS · VolumeQueueLength (número de solicitudes que esperan a completarse), VolumeAvgWriteLatency (latencia media de escritura por minuto, instancias Nitro) #### dk-burst · Agotamiento de los créditos de ráfaga del disco en la nube · Burst credit depletion Algunos discos en la nube y las instancias pequeñas tienen créditos de ráfaga para rendir por encima de su nivel base durante un rato; si la actividad intensa se alarga y los créditos se agotan, la velocidad cae de golpe. - Por qué → Efecto → En pantalla: Uso prolongado por encima del rendimiento base → Se agotan los créditos de ráfaga y el rendimiento cae de golpe al nivel base → Cada noche, el lag empieza al cabo de unas horas - Síntomas: Tirones, Cámara lenta, Input lag / Factores: Detención, Latencia - A quién: Todo el servidor / Cuándo: Horas pico de la noche, Cuanto más tiempo lleva encendido - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Servidores/SO: usar discos con rendimiento garantizado (gp3 o con IOPS aprovisionadas), poner alertas sobre el saldo de créditos, revisar también el límite de ráfaga del ancho de banda de disco de la instancia y los créditos de CPU. Servidores de BD: pasar también a rendimiento garantizado los discos de la BD, incluidas las BD gestionadas, y poner alertas sobre el saldo de créditos. - Cifras de referencia: Un disco gp2 de 100 GB de AWS da normalmente 300 IOPS y 3,000 IOPS en ráfaga, y con los créditos llenos aguanta unos 30 minutos. gp3 da siempre 3,000, sin créditos. Los Premium SSD pequeños de Azure también hacen ráfagas de hasta 30 minutos con créditos. - En el gráfico: Topa con el límite (IOPS, saldo de créditos de ráfaga) - Dónde mirar: BurstBalance de EBS en CloudWatch (gp2, st1, sc1), EBSIOBalance% y EBSByteBalance% de la instancia (algunas instancias con capacidad de ráfaga) y CPUCreditBalance de las instancias de rendimiento ampliable (burstable). En Azure, métricas de uso de créditos de ráfaga como Data Disk Used Burst IO Credits Percentage - Se confirma si: Desde que el saldo cae cerca de 0, las IOPS (VolumeReadOps, VolumeWriteOps) se quedan planas en el rendimiento base, y VolumeQueueLength y el lag aumentan a la vez. Empieza después de varias horas de pico - Se descarta si: Si todos los saldos están holgados y aun así las IOPS se quedan planas, apunta al límite fijo del volumen o de la instancia (dk-iops) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Aunque el disco esté bien, las máquinas virtuales pequeñas tienen un límite de ráfaga en el propio ancho de banda de disco de la instancia (por ejemplo, al menos 30 minutos al día), y el gráfico tiene la misma forma. Los servidores económicos que usan créditos de CPU también bajan al rendimiento base cuando se les acaban los créditos. - Fuentes: - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · Rendimiento base de gp2: 3 IOPS por GiB (mínimo 100); ráfagas de hasta 3,000 IOPS con créditos de E/S, con 5.4 millones de créditos para al menos 30 minutos. gp3 da siempre 3,000 IOPS, sin ráfagas - [Managed disk bursting](https://learn.microsoft.com/en-us/azure/virtual-machines/disk-bursting) · Microsoft Azure · Los Premium SSD P20 y menores hacen ráfagas basadas en créditos; con los créditos llenos, 30 minutos a la velocidad máxima de ráfaga - [Amazon EBS-optimized instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html) · AWS · Algunas instancias mantienen el rendimiento máximo de EBS solo 30 minutos una vez cada 24 horas y luego vuelven al rendimiento base - [Standard mode for burstable performance instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances-standard-mode.html) · AWS · En modo estándar, cuando una instancia de rendimiento ampliable se queda sin créditos de CPU, su uso de CPU baja al nivel base (de forma gradual, sin caída brusca) - [Amazon CloudWatch metrics for Amazon EBS](https://docs.aws.amazon.com/ebs/latest/userguide/using_cloudwatch_ebs.html) · AWS · BurstBalance: saldo (%) de créditos de E/S de gp2 y de créditos de throughput de st1 y sc1; VolumeReadOps, VolumeWriteOps, VolumeQueueLength - [CloudWatch metrics that are available for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · EBSIOBalance% y EBSByteBalance%: saldo de créditos de EBS de algunas instancias que hacen ráfagas de 30 minutos una vez cada 24 horas; CPUCreditBalance: saldo de créditos de CPU de las instancias de rendimiento ampliable - [Disk metrics](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-metrics) · Microsoft Azure · Porcentaje de uso de créditos de ráfaga de discos y VM, como Data Disk Used Burst IO Credits Percentage (cada 5 minutos) #### dk-iops · Límite de IOPS y saturación de la cola · IOPS limit / queue saturation Cuando se supera el número de solicitudes por segundo que el disco puede procesar, la cola se alarga y la latencia se dispara. - Por qué → Efecto → En pantalla: Las solicitudes de lectura y escritura se acercan a la capacidad del disco → La cola se alarga (normalmente se dispara por encima del 90% de utilización) → Guardados y cargas lentos; con llamadas síncronas, congelamiento - Síntomas: Input lag, Congelamiento / Factores: Latencia, Detención - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente, Horas pico de la noche - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo), Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Agrupar solicitudes, cachear los datos que se leen a menudo, hacer la E/S asíncrona para que el hilo del juego no espere al disco. - Tareas (Equipo de infraestructura): Servidores/SO: usar discos más rápidos, revisar los límites de ancho de banda e IOPS de disco de cada tipo de instancia, poner alertas sobre la utilización y la cola del disco, copiar archivos grandes en horas tranquilas. Servidores de BD: poner también alertas sobre la utilización de IOPS y throughput de los discos de la BD, revisar el límite de disco del tamaño de instancia de la BD. - Cifras de referencia: HDD, unas 150 IOPS; SSD SATA, decenas de miles; NVMe, cientos de miles. El disco estándar de la nube (AWS gp3) da 3,000 IOPS y 125 MiB por segundo; si una copia de archivos grandes llena el límite de transferencia por segundo, que es independiente de las IOPS, hasta las escrituras pequeñas se retrasan. - En el gráfico: Topa con el límite (IOPS, longitud de la cola del disco) - Dónde mirar: r/s y w/s, rkB/s y wkB/s, aqu-sz, y r_await y w_await de iostat -x 1. En la nube, VolumeReadOps, VolumeWriteOps y VolumeQueueLength de EBS, los indicadores de límite superado VolumeIOPSExceededCheck y VolumeThroughputExceededCheck y, del lado de la instancia, InstanceEBSIOPSExceededCheck e InstanceEBSThroughputExceededCheck - Se confirma si: Las solicitudes por segundo o el volumen de transferencia se quedan planos en el valor del límite, y aqu-sz y await se disparan a la vez. En la nube, las métricas de límite superado valen 1 - Se descarta si: Aunque %util esté en 100%, si await es bajo puede que aún quede margen. En SSD y RAID, que procesan solicitudes en paralelo, %util no indica el límite. Si no se llega al límite y solo await es alto, apunta a la latencia del propio disco (dk-hdd) o a fsync (dk-fsync) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: En la nube, además del límite del disco, cada tamaño de servidor (tipo de instancia) tiene su propio límite de ancho de banda e IOPS de disco. Aunque se conecte un disco caro, si el servidor es pequeño, el cuello de botella será el límite de la instancia. - Fuentes: - [Exos X18 Data Sheet](https://www.seagate.com/www-content/datasheets/pdfs/exos-x18-mango-DS2045-1N-2007US-en_US.pdf) · Seagate · 170 IOPS en lectura aleatoria 4K de un HDD para servidores de 7,200 rpm (QD16) - [D3-S4520 SSD](https://www.solidigm.com/products/data-center/d3/s4520.html) · Solidigm · SSD SATA para servidores: hasta 92K/48K IOPS en lectura/escritura aleatoria de 4 KB - [Solidigm™ D7-P5520 and D7-P5620 Product Brief](https://www.solidigm.com/products/data-center/product-briefs/d7-p5520-p5620-product-brief.html) · Solidigm · SSD NVMe para servidores: 1,000K/200K IOPS en lectura/escritura aleatoria - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · Rendimiento base de gp3: 3,000 IOPS y 125 MiB/s, dos límites distintos que se pueden ampliar por separado - [Amazon EBS-optimized instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html) · AWS · Cada tipo de instancia tiene sus propios límites base y máximos de ancho de banda, throughput e IOPS de EBS - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: r/s y w/s, rkB/s y wkB/s, aqu-sz (antes llamada avgqu-sz), r_await y w_await, %util. En RAID y SSD modernos, que procesan solicitudes en paralelo, %util no refleja el límite de rendimiento - [Amazon CloudWatch metrics for Amazon EBS](https://docs.aws.amazon.com/ebs/latest/userguide/using_cloudwatch_ebs.html) · AWS · VolumeIOPSExceededCheck y VolumeThroughputExceededCheck: 1 si se intentó superar el límite de IOPS o de throughput del volumen (instancias Nitro); VolumeQueueLength - [CloudWatch metrics that are available for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · InstanceEBSIOPSExceededCheck e InstanceEBSThroughputExceededCheck: 1 si se intentó superar el límite de IOPS o de throughput de EBS de la instancia #### dk-full · Disco lleno · Disk full Si los logs y los volcados se acumulan hasta llenar el disco, las escrituras fallan y, si no hay nada previsto, el servidor se cae. - Por qué → Efecto → En pantalla: Logs, volcados y archivos temporales se acumulan hasta el 100% → Fallan las escrituras. Sin manejo de errores, crash; con manejo de errores, fallos al guardar → Desconexión, rollback del progreso - Síntomas: Desconexión, Acción perdida / rollback / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuanto más tiempo lleva encendido - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Infraestructura de BD (Equipo de infraestructura), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Manejar los fallos de escritura con reintento del guardado y alerta (sin llegar al crash), reducir los logs y volcados innecesarios. - Tareas (Equipo de infraestructura): Servidores/SO: rotar los logs, poner alertas de espacio en disco, separar los discos de logs y de datos. Servidores de BD: vigilar que los logs de transacciones de la BD (WAL, binlog) no se acumulen por una replicación detenida o por copias de seguridad del log que no se hicieron. - En el gráfico: Subida gradual (Porcentaje de uso del disco) - Dónde mirar: Porcentaje de uso de df -h y de inodos de df -i; buscar errores ENOSPC en los logs del servidor y de la BD. En la BD: en PostgreSQL, slots de pg_replication_slots con active en false; en MySQL, el número y el tamaño de los archivos de SHOW BINARY LOGS; en SQL Server, log_reuse_wait_desc de sys.databases; en RDS, FreeStorageSpace - Se confirma si: El porcentaje de uso sube de forma constante durante varios días y llega al 100% a la misma hora que los crashes o los fallos al guardar, y en los logs queda ENOSPC - Se descarta si: Si hay espacio de sobra pero las escrituras fallan, apunta a otra causa (permisos, límite de tamaño de archivo) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Los logs de transacciones de la BD (WAL, binlog, etc.) no se borran y siguen acumulándose si una réplica se detiene o falta una copia de seguridad del log. Si ese disco se llena, todas las escrituras de la BD se detienen y los guardados y los intercambios fallan todos a la vez. - Fuentes: - [write(2) — Linux manual page](https://man7.org/linux/man-pages/man2/write.2.html) · Linux man-pages · Si no queda espacio en el dispositivo, la escritura falla con el error ENOSPC - [Monitoring Disk Usage (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/diskusage.html) · PostgreSQL · Si el disco del WAL se llena, el servidor de BD puede detenerse con un PANIC - [Log-Shipping Standby Servers (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/warm-standby.html) · PostgreSQL · Un slot de replicación no borra el WAL hasta que la réplica lo recibe, por lo que puede llenar el espacio de pg_wal (se limita con max_slot_wal_keep_size) - [Troubleshoot a full transaction log (SQL Server Error 9002)](https://learn.microsoft.com/en-us/sql/relational-databases/logs/troubleshoot-a-full-transaction-log-sql-server-error-9002) · Microsoft SQL Server · Con el log lleno, la BD solo admite lecturas y no se puede modificar; las causas habituales que impiden truncar el log son copias de seguridad del log que faltan, retraso de replicación y transacciones largas; qué lo impide se ve en log_reuse_wait_desc de sys.databases - [df(1) — Linux manual page](https://man7.org/linux/man-pages/man1/df.1.html) · coreutils · Uso por sistema de archivos; -i cambia la medida de bloques a inodos - [pg_replication_slots (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/view-pg-replication-slots.html) · PostgreSQL · active: si el slot está transmitiendo ahora (streaming); wal_status: si el WAL retenido por el slot ha superado max_wal_size - [SHOW BINARY LOGS Statement](https://dev.mysql.com/doc/refman/8.4/en/show-binary-logs.html) · MySQL · Lista de archivos de log binario del servidor y su tamaño (File_size) - [Amazon CloudWatch metrics for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html) · AWS · FreeStorageSpace: espacio de almacenamiento libre de la instancia de BD #### dk-backup · Copias de seguridad, compresión y escaneos · Backup / compression / scans Cuando una copia de seguridad de madrugada, la compresión de logs o un escaneo de seguridad acaparan el disco, las lecturas y escrituras del servidor del juego se retrasan. - Por qué → Efecto → En pantalla: Empieza una tarea programada de copia de seguridad o compresión → Ocupa la mayor parte del ancho de banda y de las IOPS del disco → Lag todos los días a la misma hora - Síntomas: Tirones, Input lag / Factores: Detención, Latencia - A quién: Todo el servidor / Cuándo: A intervalos regulares - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Servidores/SO: bajar la prioridad de E/S de las tareas de copia de seguridad, compresión y escaneo, repartir sus horarios. Servidores de BD: hacer las copias de seguridad desde una réplica. - En el gráfico: Picos periódicos (Utilización del disco, tiempo de espera del disco) - Dónde mirar: Superponer día a día %util, await y aqu-sz del historial de los últimos días con sar -d (archivos diarios de /var/log/sa; sadc tiene que recoger también los datos de disco con -S DISK); a esa hora, buscar con pidstat -d 1 el proceso con más kB_rd/s y kB_wr/s y cotejarlo con los horarios de cron y de los timers de systemd - Se confirma si: Todos los días a la misma hora se disparan await y %util, y en ese momento un proceso de copia de seguridad, compresión o escaneo acapara la mayor parte de las lecturas y escrituras en disco - Se descarta si: Si la hora de los picos cambia cada día, es poco probable que sea una tarea programada. Si a esa hora la mayor parte de la E/S es del propio servidor del juego, apunta a guardados o logs (dk-fsync, dk-sync-log) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [ionice(1) — Linux manual page](https://man7.org/linux/man-pages/man1/ionice.1.html) · util-linux · Las tareas en la clase idle solo reciben tiempo de disco cuando ningún otro programa lo está usando - [Using Replication for Backups](https://dev.mysql.com/doc/refman/8.4/en/replication-solutions-backups.html) · MySQL · Detener una réplica para hacer la copia de seguridad no afecta al funcionamiento de la BD principal - [sar(1) — Linux manual page](https://man7.org/linux/man-pages/man1/sar.1.html) · sysstat · -d: await, aqu-sz y %util por dispositivo de los archivos de historial diarios (por defecto en /var/log/sa); los datos de disco hay que recogerlos con la opción -S DISK de sadc - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -d: kB_rd/s y kB_wr/s por proceso (lectura y escritura en disco por segundo) #### dk-lazy-load · Carga diferida (lazy loading) en el servidor · Lazy loading on the server Si el servidor lee del disco los datos de una mazmorra o un mapa la primera vez que se los piden, el juego se detiene para todos durante ese tick. - Por qué → Efecto → En pantalla: Alguien entra por primera vez en una mazmorra o una zona → El servidor lee los datos del disco desde el hilo del juego → Congelamiento breve para todos los jugadores de ese servidor - Síntomas: Congelamiento / Factores: Detención - A quién: Una zona o un canal, Todo el servidor / Cuándo: Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Precargar los datos al arrancar el servidor, cargar de forma asíncrona. - Tareas (Equipo de infraestructura): En servidores recién creados desde una instantánea, precalentar el disco antes de ponerlos en servicio (leer todos los bloques una vez) o usar la restauración rápida de instantáneas. - En el gráfico: Picos aleatorios (Tiempo de tick del servidor, lecturas de disco) - Dónde mirar: Cruzar la hora de las detenciones con los registros de primera entrada a mazmorras o zonas del log del servidor del juego; en ese momento, revisar las lecturas de disco del servidor del juego (kB_rd/s de pidstat -d) y las llamadas read y open lentas con perf trace --duration. En servidores en la nube recién levantados, comparar VolumeAvgReadLatency de EBS con el de los servidores antiguos - Se confirma si: Solo se detiene la primera vez que alguien entra; al entrar por segunda vez en el mismo sitio, no. Durante la detención, el hilo del juego está esperando una lectura de archivo - Se descarta si: Si se detiene igual en zonas ya cargadas, apunta a otra causa (tick excedido, GC) - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: En la nube, un servidor recién creado desde una instantánea (copia del disco) tiene que descargar del almacenamiento remoto cada bloque la primera vez que lo lee, y va mucho más lento de lo normal. Si la primera entrada tarda mucho más solo en los servidores recién levantados por el autoescalado, hay que sospechar de esta causa. - Fuentes: - [Initialize Amazon EBS volumes](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-initialize.html) · AWS · Los volúmenes creados desde una instantánea tienen más latencia y menos rendimiento mientras descargan los bloques desde S3; se inicializan de antemano leyendo todos los bloques con dd o fio - [Amazon EBS fast snapshot restore](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-fast-snapshot-restore.html) · AWS · La restauración rápida de instantáneas entrega volúmenes ya inicializados desde su creación y elimina la latencia del primer acceso - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -d: kB_rd/s por proceso (lectura de disco por segundo) - [perf-trace(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-trace.1.html) · perf · --duration muestra solo las llamadas al sistema que tardan más de los ms indicados - [Amazon CloudWatch metrics for Amazon EBS](https://docs.aws.amazon.com/ebs/latest/userguide/using_cloudwatch_ebs.html) · AWS · VolumeAvgReadLatency: latencia media de lectura por minuto (instancias Nitro) #### dk-coredump · Escritura de core dumps · Core dump writing Cuando el servidor se cae, escribe en disco varios GB de memoria, y eso puede retrasar el reinicio varios minutos. - Por qué → Efecto → En pantalla: Un crash del servidor escribe toda su memoria en un archivo → No se puede reiniciar mientras se escriben varios GB → Desconexión por la caída del servidor y, después, no se puede conectar durante un buen rato - Síntomas: No conecta / carga infinita / Factores: Detención - A quién: Todo el servidor / Cuándo: De vez en cuando, al azar - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Valorar volcados pequeños que solo incluyan la memoria necesaria (minidumps), corregir la causa del crash. - Tareas (Equipo de infraestructura): Limitar el tamaño del volcado (configuración de core dump del SO), usar discos rápidos, separar el reinicio del volcado (comprimir y subir el volcado aparte, después del reinicio). - En el gráfico: Desconexión masiva (Número de conexiones, hora de reinicio del servidor) - Dónde mirar: Poner lado a lado la hora del crash, el tamaño del archivo core (coredumpctl list e info, o el archivo en la ruta que indica core_pattern), la hora en que terminó de escribirse y la hora en que el servicio volvió a arrancar, y revisar wkB/s de iostat -x durante ese intervalo - Se confirma si: Tras el crash, la escritura en disco se mantiene cerca del límite mientras se escribe un archivo core de varios GB, y el reinicio solo empieza cuando termina la escritura - Se descarta si: Si el core dump está desactivado o terminó siendo pequeño y aun así el reinicio tarda, apunta al proceso de arranque del servidor, como la carga de mapas o la caché fría de la BD (db-cold-cache) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [core(5) — Linux manual page](https://man7.org/linux/man-pages/man5/core.5.html) · Linux man-pages · RLIMIT_CORE limita el tamaño del archivo core, coredump_filter elige qué regiones de memoria incluir, y el core dump se puede canalizar (pipe) a un programa para procesarlo aparte - [Minidump Files](https://learn.microsoft.com/en-us/windows/win32/debug/minidump-files) · Microsoft · Un minidump solo guarda la parte útil de la información del volcado del crash, así que es rápido de generar y pequeño - [coredumpctl(1) — Linux manual page](https://man7.org/linux/man-pages/man1/coredumpctl.1.html) · systemd · list: lista de core dumps registrados en el journal (TIME es la hora del crash que notificó el kernel); info: detalles de cada volcado y el tamaño escrito en disco - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: wkB/s (escritura en disco por segundo) #### dk-hdd · Latencia de búsqueda (seek) en HDD · HDD seek latency En un HDD el cabezal tiene que moverse sobre el plato (búsqueda, seek), así que cada lectura o escritura de datos dispersos tarda cerca de 10 ms. - Por qué → Efecto → En pantalla: Servidores antiguos o almacenamiento económico con HDD → Unos 10 ms por cada lectura o escritura dispersa → Guardados y cargas lentos en general - Síntomas: Input lag / Factores: Latencia - A quién: Todo el servidor / Cuándo: Siempre - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Infraestructura de BD (Equipo de infraestructura), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Diseñar para escrituras secuenciales. - Tareas (Equipo de infraestructura): Servidores/SO: cambiar a SSD (empezando por los discos de guardado con muchas lecturas y escrituras dispersas). Servidores de BD: cambiar primero a SSD los discos de la BD con más lecturas y escrituras dispersas. - En el gráfico: Siempre alto (Latencia de lectura y escritura en disco (r_await, w_await)) - Dónde mirar: Comprobar con lsblk -d -o NAME,ROTA si es un disco rotacional (HDD) y revisar r/s y w/s, y r_await y w_await de iostat -x 1. En servidores virtuales, comprobar el tipo de disco en las especificaciones de la nube o del almacenamiento - Se confirma si: Es un disco rotacional y, con solo entre decenas y algo más de cien solicitudes por segundo, r_await y w_await están siempre entre varios ms y decenas de ms - Se descarta si: Si es SSD y la latencia es alta, apunta a la cola saturada (dk-iops) o a créditos de ráfaga agotados (dk-burst) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Una búsqueda en disco: 10 ms; leer 1 MB secuencial del disco: 20 ms - [Exos X18 Data Sheet](https://www.seagate.com/www-content/datasheets/pdfs/exos-x18-mango-DS2045-1N-2007US-en_US.pdf) · Seagate · HDD de 7,200 rpm: latencia rotacional media de 4.16 ms, 170 IOPS en lectura aleatoria 4K - [lsblk(8) — Linux manual page](https://man7.org/linux/man-pages/man8/lsblk.8.html) · util-linux · -o elige las columnas de salida; las columnas de topología del dispositivo incluyen ROTA (si es rotacional) - [ABI stable symbols](https://docs.kernel.org/admin-guide/abi-stable.html) · Linux kernel · /sys/block/(disco)/queue/rotational: indica si el dispositivo es rotacional o no rotacional - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: r/s y w/s, r_await y w_await (tiempo medio de servicio por solicitud, incluida la espera en la cola) ### L12 Base de datos (causas: 16) #### db-no-index · Consultas sin índice · Missing index / full table scan Sin índice, encontrar las filas que cumplen una condición obliga a leer la tabla entera (escaneo completo). - Por qué → Efecto → En pantalla: Un despliegue con una función nueva añade búsquedas por condiciones sin índice → Se escanean millones de filas y cada consulta tarda de cientos de ms a varios segundos → El buzón y el historial de intercambios tardan en cargar, y como las conexiones quedan ocupadas, otras solicitudes también esperan - Síntomas: Input lag, No conecta / carga infinita / Factores: Latencia, Detención - A quién: Solo una función, Todo el servidor / Cuándo: Al hacer ciertas acciones - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Revisar el plan de ejecución de las consultas nuevas antes del despliegue, añadir índices, comprobar que también las consultas que modifican datos (UPDATE, DELETE) usan índice. - Tareas (Equipo de infraestructura): Vigilar el log de consultas lentas, localizar las consultas con escaneo completo y compartirlas con el equipo de desarrollo, crear los índices en producción con el método online, que bloquea poco tiempo. - Cifras de referencia: Con índice tarda unos pocos ms; sin él, se vuelve más lenta en proporción al tamaño de los datos, y en tablas grandes puede ser de cientos a decenas de miles de veces más lenta. - En el gráfico: Salto en escalón (Latencia de las consultas a la BD, filas leídas) - Dónde mirar: En MySQL, Rows_examined y Rows_sent del slow query log (con log_queries_not_using_indexes activado también registra las consultas que no usan índice), SUM_NO_INDEX_USED y SUM_ROWS_EXAMINED de events_statements_summary_by_digest en performance_schema, y ejecutar EXPLAIN. En PostgreSQL, seq_scan y seq_tup_read de pg_stat_user_tables, y ejecutar EXPLAIN - Se confirma si: Una consulta que apareció tras el despliegue lee miles de veces más filas (Rows_examined) de las que devuelve (Rows_sent), y EXPLAIN muestra un escaneo completo de la tabla (type ALL en MySQL, Seq Scan en PostgreSQL). El seq_tup_read de una tabla grande crece bruscamente desde la hora del despliegue - Se descarta si: Si usa índice y aun así va lenta, apunta a esperas por bloqueos (db-hot-row, db-ddl-lock) o a un cambio del plan de ejecución (db-plan-flip). Un escaneo completo de una tabla pequeña puede ser normal - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: El problema va más allá de las lecturas lentas. Según la BD, una consulta que modifica datos sin índice (UPDATE, DELETE) bloquea también las filas que escanea, y puede llegar a frenar los guardados de jugadores que no tienen nada que ver. - Fuentes: - [How MySQL Uses Indexes](https://dev.mysql.com/doc/refman/8.4/en/mysql-indexes.html) · MySQL · Sin índice, se lee toda la tabla desde la primera fila, y cuanto mayor es la tabla, mayor es el costo - [Locks Set by Different SQL Statements in InnoDB](https://dev.mysql.com/doc/refman/8.4/en/innodb-locks-set.html) · MySQL · Si no hay un índice adecuado y se escanea toda la tabla, se bloquean todas las filas, y hasta las inserciones de otros usuarios quedan bloqueadas - [The Slow Query Log](https://dev.mysql.com/doc/refman/8.4/en/slow-query-log.html) · MySQL · Registra las consultas que superan long_query_time (10 s por defecto); también puede registrar aparte las que no usan índice - [CREATE INDEX (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/sql-createindex.html) · PostgreSQL · Con CONCURRENTLY, el índice se crea sin bloquear las escrituras; la creación normal bloquea las escrituras hasta que termina - [Statement Summary Tables](https://dev.mysql.com/doc/refman/8.4/en/performance-schema-statement-summary-tables.html) · MySQL · events_statements_summary_by_digest: SUM_NO_INDEX_USED (veces que se ejecutó sin índice) y SUM_ROWS_EXAMINED por cada forma de consulta - [EXPLAIN Output Format](https://dev.mysql.com/doc/refman/8.4/en/explain-output.html) · MySQL · type ALL indica un escaneo completo de la tabla, que normalmente se evita añadiendo un índice - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · seq_scan (número de escaneos secuenciales) y seq_tup_read (filas leídas con escaneos secuenciales) de pg_stat_user_tables - [Using EXPLAIN (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/using-explain.html) · PostgreSQL · Seq Scan: plan de ejecución que lee todas las filas de la tabla una tras otra #### db-hot-row · Contención de bloqueos en una fila caliente · Hot row lock contention Si todos intentan modificar la misma fila (el almacén del gremio, un objeto popular de la casa de subastas, un contador global del servidor), el bloqueo solo lo consigue uno cada vez. - Por qué → Efecto → En pantalla: Un evento o un objeto popular concentra las modificaciones en la misma fila → Las solicitudes esperan hasta conseguir el bloqueo → Intercambios fallidos, “Inténtalo de nuevo más tarde”, timeouts - Síntomas: Acción perdida / rollback, Input lag / Factores: Detención, Latencia - A quién: Solo una función / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Dividir la fila (contadores fragmentados), acortar las transacciones, acumular los cambios en memoria y aplicarlos de una vez. - Tareas (Equipo de infraestructura): Monitorear el tiempo y el número de esperas por bloqueo de fila para localizar las filas con más contención y compartirlas. - Cifras de referencia: Si cada solicitud retiene el bloqueo 10 ms, esa fila solo se puede modificar como máximo 100 veces por segundo. Si dentro de la transacción hay idas y vueltas a otros servidores, la cifra baja todavía más. - En el gráfico: Sube con la carga (Número y tiempo de esperas por bloqueo de fila) - Dónde mirar: En MySQL, el incremento de Innodb_row_lock_waits e Innodb_row_lock_time, Innodb_row_lock_current_waits, y sys.innodb_lock_waits para ver quién espera a quién. En PostgreSQL, las sesiones de pg_stat_activity con wait_event_type Lock y las solicitudes de pg_locks con granted en false; con log_lock_waits activado (desactivado por defecto), los bloqueos con esperas largas quedan en el log - Se confirma si: Las esperas por bloqueo crecen con fuerza al ritmo de los eventos y del número de jugadores, y la mayoría de las solicitudes en espera apuntan a la misma fila (la misma clave) de la misma tabla - Se descarta si: Si las esperas están repartidas por igual entre muchas tablas y filas, apunta a saturación de disco o CPU. Si una sesión retiene un bloqueo mucho tiempo sin soltarlo: transacciones abiertas durante mucho tiempo (db-long-tx) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [InnoDB Locking](https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html) · MySQL · Cuando una transacción bloquea una fila (registro de índice), las demás transacciones no pueden modificarla y esperan - [How to Minimize and Handle Deadlocks](https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlocks-handling.html) · MySQL · Recomendación de mantener las transacciones pequeñas y cortas, y de hacer commit justo después de los cambios relacionados para reducir los conflictos - [Server Status Variables](https://dev.mysql.com/doc/refman/8.4/en/server-status-variables.html) · MySQL · Innodb_row_lock_waits e Innodb_row_lock_time dan el número y el tiempo de las esperas por bloqueo de fila; Innodb_row_lock_current_waits, cuántas hay en este momento - [The innodb_lock_waits and x$innodb_lock_waits Views](https://dev.mysql.com/doc/refman/8.4/en/sys-innodb-lock-waits.html) · MySQL · La consulta que espera (waiting_query), la sesión que bloquea (blocking_pid) y el tiempo de espera (wait_age) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · wait_event_type de pg_stat_activity: si es Lock, la sesión está esperando un bloqueo pesado (heavyweight lock) - [pg_locks (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/view-pg-locks.html) · PostgreSQL · Si granted es false, ese proceso está esperando para conseguir el bloqueo - [Error Reporting and Logging (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-logging.html) · PostgreSQL · log_lock_waits: registra en el log las esperas por bloqueo que superan deadlock_timeout; desactivado por defecto #### db-deadlock · Deadlock en la BD · Database deadlock Si dos transacciones (operaciones de BD que se procesan como un solo bloque) esperan cada una la fila que bloqueó la otra, la BD cancela una de ellas a la fuerza. - Por qué → Efecto → En pantalla: El intercambio A bloquea en el orden objeto→moneda y el B en el orden moneda→objeto → La BD detecta el deadlock y hace rollback de una de las dos → Intercambios y fabricaciones que fallan de vez en cuando, objetos que se revierten - Síntomas: Acción perdida / rollback, Input lag / Factores: Pérdida de paquetes, Detención - A quién: Solo una función / Cuándo: Cuando se junta mucha gente, Al hacer ciertas acciones - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Unificar el orden de los bloqueos, acortar las transacciones, reintentar automáticamente si fallan. - Tareas (Equipo de infraestructura): Mantener activada la detección de deadlocks, recoger los registros de deadlocks y compartirlos, reducir el límite de espera de bloqueo (50 segundos por defecto) en los servidores MySQL con la detección desactivada. - Cifras de referencia: El tiempo hasta detectarlo es casi inmediato en MySQL (InnoDB), de 1 segundo por defecto en PostgreSQL y de hasta unos 5 segundos en SQL Server. Mientras tanto, las dos solicitudes están detenidas. En un servidor MySQL con la detección desactivada por tener muchísimas solicitudes simultáneas, la espera llega hasta el límite de espera de bloqueo (50 segundos por defecto). - En el gráfico: Picos aleatorios (Número de deadlocks, número de intercambios fallidos) - Dónde mirar: En MySQL, LATEST DETECTED DEADLOCK de SHOW ENGINE INNODB STATUS (solo el más reciente), todos los deadlocks que quedan en el log de errores con innodb_print_all_deadlocks activado y lock_deadlocks de INFORMATION_SCHEMA.INNODB_METRICS. En PostgreSQL, deadlocks de pg_stat_database; en SQL Server, xml_deadlock_report de la sesión system_health, activa por defecto. Códigos de error en el servidor del juego: MySQL 1213, PostgreSQL 40P01, SQL Server 1205 - Se confirma si: Cuando fallan los intercambios o las fabricaciones, el número de deadlocks sube, y las dos transacciones registradas bloquean las mismas tablas en orden inverso - Se descarta si: Si fallan pero el número de deadlocks no cambia, apunta a un límite de espera de bloqueo superado (error 1205 de MySQL) o a una fila caliente (db-hot-row) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [InnoDB Startup Options and System Variables](https://dev.mysql.com/doc/refman/8.4/en/innodb-parameters.html) · MySQL · Con la detección activada (por defecto), InnoDB detecta los deadlocks al instante y hace rollback; innodb_lock_wait_timeout es de 50 s por defecto - [Deadlock Detection](https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlock-detection.html) · MySQL · Con concurrencia muy alta, la propia detección puede volverse lenta, y a veces se desactiva para dejarlo en manos del límite de espera de bloqueo - [Lock Management (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-locks.html) · PostgreSQL · deadlock_timeout es de 1 s por defecto: solo después de esperar un bloqueo ese tiempo se comprueba si hay deadlock - [Deadlocks guide](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-deadlocks-guide) · Microsoft SQL Server · Intervalo de detección de deadlocks de 5 s por defecto, que baja hasta 100 ms si los deadlocks son frecuentes; la sesión system_health, activa por defecto, recoge xml_deadlock_report; la transacción elegida como víctima recibe el error 1205 - [How to Minimize and Handle Deadlocks](https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlocks-handling.html) · MySQL · Modificar siempre varias filas o tablas en el mismo orden, reintentar si falla, registrar todos los deadlocks con innodb_print_all_deadlocks - [InnoDB Standard Monitor and Lock Monitor Output](https://dev.mysql.com/doc/refman/8.4/en/innodb-standard-monitor.html) · MySQL · LATEST DETECTED DEADLOCK: las dos transacciones del deadlock más reciente, los bloqueos que tenían y los que esperaban, y la que recibió el rollback - [InnoDB INFORMATION_SCHEMA Metrics Table](https://dev.mysql.com/doc/refman/8.4/en/innodb-information-schema-metrics-table.html) · MySQL · Contador lock_deadlocks de INNODB_METRICS (activado por defecto) - [Server Error Message Reference](https://dev.mysql.com/doc/mysql-errors/8.4/en/server-error-reference.html) · MySQL · 1213 ER_LOCK_DEADLOCK (deadlock), 1205 ER_LOCK_WAIT_TIMEOUT (límite de espera de bloqueo superado) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · deadlocks de pg_stat_database: número de deadlocks detectados en esta BD - [PostgreSQL Error Codes (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/errcodes-appendix.html) · PostgreSQL · 40P01 deadlock_detected #### db-pool · Agotamiento del pool de conexiones · Connection pool exhaustion El número de conexiones abiertas con la BD es fijo, así que si las consultas lentas ocupan las conexiones, las demás solicitudes esperan. - Por qué → Efecto → En pantalla: Todas las conexiones están ocupadas por consultas lentas o por una avalancha de solicitudes → Las solicitudes nuevas esperan a que se libere una conexión → Carga infinita al iniciar sesión, guardados lentos, timeouts - Síntomas: No conecta / carga infinita, Input lag / Factores: Detención, Latencia - A quién: Todo el servidor, Solo una función / Cuándo: Al conectar o tras un mantenimiento, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Eliminar las consultas lentas, ajustar el tamaño del pool y el timeout de espera (sin agrandar el pool sin más), separar pools por función. - Tareas (Equipo de infraestructura): Revisar el máximo de conexiones de la BD y el margen de CPU e IOPS, comprobar antes de añadir servidores o de autoescalar que el número de servidores × el tamaño del pool no supera el máximo de conexiones, añadir al monitoreo las métricas de espera de conexión y de espera por bloqueos. - Cifras de referencia: El número de conexiones necesarias se calcula a ojo como “solicitudes por segundo × tiempo que cada una retiene la conexión”. Con 2,000 solicitudes por segundo y 5 ms cada una, hay de media 10 conexiones siempre ocupadas. Para los picos se suele dejar el doble o el triple. Si las consultas se ralentizan a 150 ms, la misma carga necesita 300 conexiones. - En el gráfico: Topa con el límite (Conexiones a la BD en uso, tiempo de espera de conexión) - Dónde mirar: Contar desde la BD el estado de las conexiones de cada servidor del juego. En MySQL, Host, Command (las conexiones inactivas aparecen como Sleep) y Time de SHOW PROCESSLIST, Threads_connected y Threads_running, y el número de conexiones rechazadas Connection_errors_max_connections. En PostgreSQL, agrupar pg_stat_activity por client_addr y state. Si la biblioteca de pool de conexiones del servidor del juego publica el número de esperas y el tiempo de espera, revisarlos también - Se confirma si: Todas las conexiones de un servidor del juego, tantas como el tamaño del pool, están ejecutando consultas, no queda ninguna inactiva y, mientras tanto, los inicios de sesión y los guardados esperan. O el total de conexiones de la BD llega a max_connections y se rechazan las conexiones nuevas - Se descarta si: Si hay conexiones inactivas de sobra y aun así va lento, apunta a la latencia de las propias consultas (db-no-index, db-hot-row) o a la saturación de recursos de la BD - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Agrandar el pool sin más solo aumenta el uso de CPU de la BD y la contención de bloqueos, y todo se vuelve lento a la vez. Además, si el número de servidores × el tamaño del pool supera el máximo de conexiones de la BD, los servidores añadidos o reiniciados ni siquiera pueden conectarse. Es habitual justo después de un autoescalado o de un mantenimiento. - Fuentes: - [Number Of Database Connections](https://wiki.postgresql.org/wiki/Number_Of_Database_Connections) · PostgreSQL · Una vez agotados los recursos de la BD, añadir conexiones reduce el throughput; ajustar las conexiones activas a los recursos y dejar el resto en cola mejora tanto la latencia como el throughput - [Too many connections](https://dev.mysql.com/doc/refman/8.4/en/too-many-connections.html) · MySQL · Cuando se usan todas las max_connections, las conexiones nuevas se rechazan con el error Too many connections - [Connections and Authentication (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-connection.html) · PostgreSQL · max_connections: límite de conexiones simultáneas, normalmente 100 por defecto - [SHOW PROCESSLIST Statement](https://dev.mysql.com/doc/refman/8.4/en/show-processlist.html) · MySQL · Host (dirección del cliente), Command (Sleep para las sesiones inactivas), Time, State - [Server Status Variables](https://dev.mysql.com/doc/refman/8.4/en/server-status-variables.html) · MySQL · Threads_connected y Threads_running, Connection_errors_max_connections (conexiones rechazadas por llegar a max_connections) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · pg_stat_activity: client_addr y state (active, idle, idle in transaction, etc.) de cada conexión #### db-replica-lag · Retraso de replicación · Replication lag Si se escribe en la BD principal y se lee de una réplica, cuando la réplica va con retraso no se ve lo que se acaba de escribir. - Por qué → Efecto → En pantalla: Las escrituras se concentran en la BD principal y la réplica se queda varios segundos atrás → Al leer de la réplica lo que se acaba de guardar, todavía no está → El objeto recién comprado no aparece, el mercado muestra precios antiguos, bugs de entregas duplicadas - Síntomas: Acción perdida / rollback / Factores: Latencia - A quién: Solo una función / Cuándo: Cuando se junta mucha gente, Horas pico de la noche - Responsable principal: Infraestructura de BD (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Leer de la BD principal los datos recién escritos, comprobar y hacer la entrega en una sola transacción en la BD principal (bloquear duplicados con una clave única o un UPDATE condicional). - Tareas (Equipo de infraestructura): Configurar alertas de retraso de replicación, dar a las réplicas un tamaño igual o mayor que el de la BD principal y activar la replicación en paralelo, ejecutar los borrados masivos en tandas pequeñas, controlar las consultas de agregación largas en las réplicas. - En el gráfico: Sube con la carga (Retraso de replicación (segundos)) - Dónde mirar: En MySQL, Seconds_Behind_Source de SHOW REPLICA STATUS en la réplica (SHOW SLAVE STATUS en versiones anteriores a 8.0.22). En PostgreSQL, write_lag, flush_lag y replay_lag de pg_stat_replication en el servidor principal; en RDS, ReplicaLag - Se confirma si: A la hora de los reportes de “no aparece”, el retraso es de varios segundos o más, y al volver a mirar cuando se recupera, todo está bien. El retraso crece con las avalanchas de escrituras, los borrados masivos o las consultas de agregación largas en la réplica - Se descarta si: Si el retraso está cerca de 0 y aun así no aparece, apunta a la caché o a la sincronización del servidor del juego - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Puede quedarse atrás aunque no haya muchas escrituras. Un único borrado masivo que tardó 10 minutos en la BD principal vuelve a ejecutarse en la réplica y la retrasa ese mismo tiempo, y las consultas de agregación largas en la réplica también le impiden ponerse al día. - Fuentes: - [SHOW REPLICA STATUS Statement](https://dev.mysql.com/doc/refman/8.4/en/show-replica-status.html) · MySQL · Seconds_Behind_Source: diferencia respecto a la hora en que se registró en la BD principal el evento que la réplica está aplicando ahora (retraso de replicación) - [Replica Server Options and Variables](https://dev.mysql.com/doc/refman/8.4/en/replication-options-replica.html) · MySQL · replica_parallel_workers: varios hilos aplican transacciones en paralelo (4 por defecto; con 0, un solo hilo en orden) - [Log-Shipping Standby Servers (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/warm-standby.html) · PostgreSQL · La replicación en streaming es asíncrona por defecto, así que hay un retraso entre el commit y su aplicación en la réplica (normalmente menos de 1 s si la réplica puede seguir el ritmo) - [MySQL 8.0 Reference Manual: SHOW REPLICA STATUS Statement](https://dev.mysql.com/doc/refman/8.0/en/show-replica-status.html) · MySQL · Desde 8.0.22, SHOW REPLICA STATUS sustituye a SHOW SLAVE STATUS; las versiones anteriores usan SHOW SLAVE STATUS - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · write_lag, flush_lag y replay_lag de pg_stat_replication: tiempo desde que el servidor principal escribe el WAL hasta que la réplica avisa de que lo escribió, lo pasó a disco y lo aplicó - [Amazon CloudWatch metrics for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html) · AWS · ReplicaLag: tiempo (en segundos) que la réplica de lectura va por detrás del origen #### db-checkpoint · Checkpoint y volcado del log · Checkpoint / log flush stalls Cuando la BD vuelca de golpe al disco, de forma periódica, los cambios que tiene en memoria, las consultas se ralentizan. - Por qué → Efecto → En pantalla: Los cambios se acumulan y se escriben en disco periódicamente → En ese momento el disco está muy ocupado y las consultas se retrasan → Guardados y cargas que se vuelven lentos periódicamente - Síntomas: Input lag, Tirones / Factores: Latencia - A quién: Todo el servidor, Solo una función / Cuándo: A intervalos regulares - Responsable principal: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Repartir los checkpoints en partes pequeñas y uniformes, dimensionar con holgura el log de transacciones (redo log, WAL), usar discos rápidos. - En el gráfico: Picos periódicos (Latencia de las consultas a la BD, volumen de escritura en disco) - Dónde mirar: En PostgreSQL, la hora de cada checkpoint y los búferes escritos en el log de log_checkpoints (activado por defecto en las versiones recientes), el número de checkpoints (num_timed y num_requested de pg_stat_checkpointer desde la versión 17; checkpoints_timed y checkpoints_req de pg_stat_bgwriter en la 16 y anteriores) y los avisos de checkpoint_warning. En MySQL, la diferencia entre Log sequence number y Last checkpoint at en la sección LOG de SHOW ENGINE INNODB STATUS. Superponer también el volumen y la latencia de escritura en disco del servidor - Se confirma si: Los picos de latencia de las consultas coinciden con la hora de los checkpoints, y en ese momento se disparan el volumen y la latencia de escritura en disco. En PostgreSQL, si hay muchos más checkpoints solicitados (num_requested) que checkpoints por tiempo (num_timed), el WAL llega a menudo a max_wal_size y los checkpoints se adelantan - Se descarta si: Si los picos siguen un ciclo sin relación con la hora de los checkpoints, apunta a copias de seguridad o procesos batch (dk-backup, db-batch) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Si el log de transacciones que guarda el registro de cambios (el redo log de MySQL, el WAL de PostgreSQL) es demasiado pequeño, cada vez que se llena la BD tiene que hacer un checkpoint de golpe y con prisa, y el throughput de escritura cae mucho durante unos instantes. - Fuentes: - [WAL Configuration (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-configuration.html) · PostgreSQL · Por defecto se hace un checkpoint cada 5 minutos o cada 1 GB de WAL (max_wal_size), y es costoso porque escribe todas las páginas sucias. checkpoint_completion_target reparte las escrituras para evitar avalanchas de E/S. Si el intervalo entre checkpoints es menor que checkpoint_warning, se escribe en el log un aviso para aumentar max_wal_size - [Configuring Buffer Pool Flushing](https://dev.mysql.com/doc/refman/8.4/en/innodb-buffer-pool-flushing.html) · MySQL · Cuando el redo log se llena, un checkpoint urgente (sharp) reduce el throughput durante un momento; el flushing adaptativo reparte las escrituras de forma uniforme - [Error Reporting and Logging (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-logging.html) · PostgreSQL · log_checkpoints: registra en el log los búferes escritos y el tiempo de cada checkpoint; activado por defecto - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · num_timed (checkpoints hechos al cumplirse el tiempo) y num_requested (checkpoints solicitados) de pg_stat_checkpointer - [PostgreSQL 17 Release Notes](https://www.postgresql.org/docs/release/17.0/) · PostgreSQL · Nueva vista pg_stat_checkpointer, a la que pasan desde pg_stat_bgwriter las columnas relacionadas con los checkpoints - [The Cumulative Statistics System (PostgreSQL 16 Documentation)](https://www.postgresql.org/docs/16/monitoring-stats.html) · PostgreSQL · Hasta la versión 16, checkpoints_timed y checkpoints_req de pg_stat_bgwriter - [InnoDB Standard Monitor and Lock Monitor Output](https://dev.mysql.com/doc/refman/8.4/en/innodb-standard-monitor.html) · MySQL · Sección LOG: número de secuencia del log actual y posición del último checkpoint #### db-cold-cache · Caché fría (justo después de reiniciar) · Cold buffer pool after restart Al reiniciar la BD, su caché en memoria está vacía, y durante un tiempo todas las consultas leen del disco. - Por qué → Efecto → En pantalla: La BD se reinicia por un mantenimiento → Los datos que se usaban a menudo ya no están en memoria y se leen del disco → Justo después del mantenimiento, el inicio de sesión y las cargas van lentos durante un rato - Síntomas: No conecta / carga infinita, Input lag / Factores: Latencia - A quién: Todo el servidor / Cuándo: Al conectar o tras un mantenimiento - Responsable principal: Infraestructura de BD (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Abrir de forma gradual (aumentar por etapas el número de jugadores que inician sesión con una cola de inicio de sesión). - Tareas (Equipo de infraestructura): Precalentar la caché tras el reinicio (warm-up; revisar la configuración de guardado y restauración del buffer pool) y, en las BD restauradas desde una instantánea, leer también el disco por adelantado. - En el gráfico: Avalancha tras la apertura (Lecturas de disco, tasa de aciertos de la caché de búferes) - Dónde mirar: En MySQL, la proporción entre Innodb_buffer_pool_reads (lecturas que no estaban en el buffer pool y se hicieron desde disco) e Innodb_buffer_pool_read_requests, y el progreso del precalentamiento en Innodb_buffer_pool_load_status. En PostgreSQL, blks_read y blks_hit de pg_stat_database. Revisar también las lecturas de disco del servidor de BD - Se confirma si: Justo después del reinicio, las lecturas de disco se disparan y la tasa de aciertos cae; luego ambas se normalizan con el tiempo, y durante ese intervalo el inicio de sesión y las cargas van lentos - Se descarta si: Si la tasa de aciertos es la normal pero va lento justo después del mantenimiento, apunta a una avalancha de inicios de sesión y consultas N+1 (db-login-storm) o al pool de conexiones (db-pool) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: MySQL guarda la lista de páginas del buffer pool al apagarse y vuelve a cargarlas en segundo plano al arrancar, pero llenarlo del todo lleva tiempo. Si en la nube la BD se restauró desde una instantánea (copia del disco), el propio disco también va lento con cada bloque que se lee por primera vez, y el efecto dura más. - Casos reales: roblox-2021 - Fuentes: - [Saving and Restoring the Buffer Pool State](https://dev.mysql.com/doc/refman/8.4/en/innodb-preload-buffer-pool.html) · MySQL · Para acortar el precalentamiento tras un reinicio, al apagarse guarda la lista de páginas usadas recientemente (25% por defecto) y al arrancar las vuelve a leer; ambas opciones están activadas por defecto - [pg_prewarm — preload relation data into buffer caches](https://www.postgresql.org/docs/current/pgprewarm.html) · PostgreSQL · Guarda periódicamente el contenido de los búferes compartidos y lo vuelve a cargar tras el reinicio (autoprewarm) - [Initialize Amazon EBS volumes](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-initialize.html) · AWS · Los volúmenes creados desde una instantánea tienen más latencia y menos rendimiento hasta que se descargan todos los bloques - [Server Status Variables](https://dev.mysql.com/doc/refman/8.4/en/server-status-variables.html) · MySQL · Innodb_buffer_pool_reads (lecturas lógicas que no estaban en el buffer pool y se leyeron directamente del disco), Innodb_buffer_pool_read_requests, Innodb_buffer_pool_load_status (progreso del precalentamiento) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · blks_read (bloques leídos del disco) y blks_hit (bloques encontrados en la caché de búferes) de pg_stat_database #### db-login-storm · Avalancha de inicios de sesión y consultas N+1 · Login storm, N+1 queries Si cargar un personaje requiere decenas de consultas separadas, decenas de miles de inicios de sesión simultáneos se convierten en millones de consultas. - Por qué → Efecto → En pantalla: Al cargar un personaje se consultan por separado los objetos, las habilidades y las misiones → Justo después del mantenimiento, los inicios de sesión simultáneos disparan el número de consultas → Carga infinita al iniciar sesión, e incluso los guardados de quienes ya están jugando se retrasan - Síntomas: No conecta / carga infinita, Input lag / Factores: Detención, Latencia - A quién: Todo el servidor / Cuándo: Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Agrupar las consultas en una sola, usar una cola de inicio de sesión y caché, revisar cuántas consultas genera la carga diferida del ORM. - Tareas (Equipo de infraestructura): Sacar y compartir el ranking de las consultas más llamadas, monitorear el número de consultas y de conexiones durante los inicios de sesión justo después del mantenimiento. - En el gráfico: Avalancha tras la apertura (Consultas por segundo de la BD, número de inicios de sesión) - Dónde mirar: Superponer los inicios de sesión justo después del mantenimiento y las consultas por segundo de la BD (en MySQL, el incremento de Questions) y calcular las consultas por cada inicio de sesión. Las consultas más llamadas se sacan con COUNT_STAR de events_statements_summary_by_digest en MySQL y con calls de pg_stat_statements en PostgreSQL - Se confirma si: Cada inicio de sesión genera decenas de consultas, y las más frecuentes son consultas cortas con la misma forma que buscan por un único ID de personaje. Si las consultas por inicio de sesión aumentaron tras un parche, ese parche es el punto de partida - Se descarta si: Si hay pocas consultas por inicio de sesión pero cada una es lenta, apunta a caché fría (db-cold-cache) o a índices (db-no-index) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: La carga diferida (lazy loading) de un ORM (biblioteca que genera automáticamente las consultas a la BD) crea este tipo de consultas sin que los desarrolladores lo noten. En el servidor de desarrollo, con unos pocos personajes, no se nota; aparece por primera vez con los inicios de sesión simultáneos en producción. - Fuentes: - [Efficient Querying](https://learn.microsoft.com/en-us/ef/core/performance/efficient-querying) · .NET · La carga diferida de un ORM genera el problema N+1, que envía una consulta adicional por cada elemento y degrada mucho el rendimiento; se recomienda cargar todo de una vez (eager loading) - [pg_stat_statements — track statistics of SQL planning and execution](https://www.postgresql.org/docs/current/pgstatstatements.html) · PostgreSQL · Recoge el número de ejecuciones (calls) y el tiempo total de cada sentencia para sacar el ranking de las consultas más llamadas - [Performance Schema Statement Digests and Sampling](https://dev.mysql.com/doc/refman/8.4/en/performance-schema-statement-digests.html) · MySQL · events_statements_summary_by_digest agrupa las consultas con la misma forma y suma ejecuciones y tiempo - [Statement Summary Tables](https://dev.mysql.com/doc/refman/8.4/en/performance-schema-statement-summary-tables.html) · MySQL · COUNT_STAR (número de ejecuciones) y SUM_TIMER_WAIT (tiempo total) de las tablas de resumen - [Server Status Variables](https://dev.mysql.com/doc/refman/8.4/en/server-status-variables.html) · MySQL · Questions: número de sentencias enviadas por los clientes #### db-batch · Procesos batch masivos · Batch jobs during service Calcular rankings, enviar correo del juego en masa o limpiar datos antiguos con el servicio en marcha acapara bloqueos y disco. - Por qué → Efecto → En pantalla: Se lanzan tareas masivas en horario de servicio → Bloqueos de rangos amplios, disco y CPU ocupados → Fallos en intercambios y guardados a ciertas horas, cargas lentas - Síntomas: Input lag, Acción perdida / rollback / Factores: Latencia, Detención - A quién: Solo una función, Todo el servidor / Cuándo: A intervalos regulares - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Dividir el trabajo en lotes pequeños y avanzar poco a poco, hacer las agregaciones en una réplica. - Tareas (Equipo de infraestructura): Ofrecer una réplica para agregaciones, programar los procesos batch en horas tranquilas, vigilar el escalado de bloqueos y las esperas por gap locks. - En el gráfico: Picos periódicos (Latencia de las consultas a la BD, esperas por bloqueo) - Dónde mirar: Buscar las consultas largas que se ejecutaban a la hora del lag: en MySQL, el slow query log; en PostgreSQL, query_start y query de pg_stat_activity; y cotejarlas con las métricas de espera por bloqueo de esa hora y con el calendario de procesos batch (cron, programador de eventos de la BD). En SQL Server, registrar el escalado de bloqueos con el evento extendido lock_escalation - Se confirma si: Siempre a la misma hora se ejecutan UPDATE, DELETE o consultas de agregación masivas, y mientras tanto suben a la vez las esperas por bloqueo y la utilización del disco - Se descarta si: Si a esa hora no hay consultas largas, apunta a un checkpoint (db-checkpoint) o a una copia de seguridad del servidor (dk-backup) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: SQL Server convierte los bloqueos de fila en un bloqueo de tabla cuando una sola sentencia retiene más de unos 5,000 (escalado de bloqueos). En ese momento se detienen todas las solicitudes que usan esa tabla. MySQL, con la configuración por defecto, también bloquea los huecos entre filas (gap lock) cuando se modifica con una condición de rango, y eso impide insertar filas nuevas. - Fuentes: - [Transaction Locking and Row Versioning Guide](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-transaction-locking-and-row-versioning-guide) · Microsoft SQL Server · Si una sentencia retiene 5,000 bloqueos o más en una tabla (o un índice), se produce el escalado de bloqueos; se registra con el evento extendido lock_escalation - [InnoDB Locking](https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html) · MySQL · Con REPEATABLE READ, el nivel de aislamiento por defecto de InnoDB, las búsquedas y los escaneos usan bloqueos next-key, y el gap lock impide insertar filas nuevas en ese hueco - [The Slow Query Log](https://dev.mysql.com/doc/refman/8.4/en/slow-query-log.html) · MySQL · Registra las consultas que superan long_query_time con su tiempo de ejecución (Query_time), su tiempo de bloqueo (Lock_time) y las filas leídas - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · pg_stat_activity: la consulta que cada sesión está ejecutando (query) y su hora de inicio (query_start) #### db-failover · Failover de la BD · Database failover Cuando la BD principal cae, no se puede escribir mientras se cambia a la de respaldo, y los últimos datos que no llegaron a replicarse pueden perderse. - Por qué → Efecto → En pantalla: Por un fallo de la BD principal, se promueve la BD de respaldo → No se puede escribir durante el cambio, que dura de varios segundos a unos minutos; con replicación asíncrona, pueden perderse los datos no replicados → Todos los guardados fallan durante un momento, rollback de objetos y experiencia - Síntomas: Acción perdida / rollback, Congelamiento, Desconexión, No conecta / carga infinita / Factores: Detención, Pérdida de paquetes - A quién: Todo el servidor / Cuándo: De vez en cuando, al azar - Responsable principal: Infraestructura de BD (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Hacer guardados que se puedan reintentar, configurar el pool de conexiones y la caché de DNS para abandonar pronto las conexiones cortadas y reconectar a la nueva dirección, comprobar la reconexión en los simulacros de failover. - Tareas (Equipo de infraestructura): Usar replicación síncrona o semisíncrona (a cambio de más latencia de escritura), hacer simulacros de failover, monitorear el tiempo de failover y el retraso de replicación. - Cifras de referencia: El failover automático de una BD gestionada suele tardar de decenas de segundos a 2 minutos. Con replicación asíncrona, se pueden perder los guardados más recientes, en la medida del retraso de replicación (de menos de 1 s a varios segundos). - En el gráfico: Desconexión masiva (Número de conexiones a la BD, número de errores de escritura) - Dónde mirar: Poner en un mismo gráfico el registro de failover de la BD (en RDS, los eventos RDS-EVENT-0013, inicio del failover, y RDS-EVENT-0049, failover completado; en BD autogestionadas, el log de la promoción) y las conexiones a la BD y los errores de conexión del servidor del juego. Con replicación asíncrona, revisar también el retraso de replicación justo antes del fallo (ReplicaLag en RDS, replay_lag de pg_stat_replication en PostgreSQL) - Se confirma si: Los fallos al guardar se concentran en un intervalo que coincide con el periodo entre el inicio y el final del failover. Lo que se revirtió equivale más o menos al retraso de replicación justo antes del fallo. Los servidores del juego que siguen con errores después del failover continúan usando conexiones abiertas con la dirección antigua - Se descarta si: Las desconexiones a horas sin registro de failover apuntan a la red o a una sobrecarga de la BD - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Casos reales: riot-euw-2021 - Fuentes: - [Failing over a Multi-AZ DB instance for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.Failover.html) · AWS · Un failover Multi-AZ suele tardar 60–120 s; después hay que volver a abrir las conexiones, y se recomienda un TTL de caché de DNS de la JVM de 60 s o menos - [High availability for Amazon Aurora](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Concepts.AuroraHighAvailability.html) · AWS · Durante el fallo fallan las lecturas y escrituras, y la recuperación suele llegar en menos de 60 s (a menudo en menos de 30 s) - [Semisynchronous Replication](https://dev.mysql.com/doc/refman/8.4/en/replication-semisync.html) · MySQL · Con replicación asíncrona, si la BD principal cae, puede que una transacción confirmada no esté en la réplica; la semisíncrona lo reduce esperando la confirmación de recepción de una réplica, a cambio de más latencia - [Log-Shipping Standby Servers (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/warm-standby.html) · PostgreSQL · El envío de logs es asíncrono, así que si el servidor principal cae se pierden las transacciones que aún no se enviaron; el retraso de la replicación en streaming suele ser de menos de 1 s - [Amazon RDS event categories and event messages](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.Messages.html) · AWS · RDS-EVENT-0013: inicio del failover Multi-AZ; RDS-EVENT-0049: failover Multi-AZ completado - [Amazon CloudWatch metrics for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html) · AWS · ReplicaLag: tiempo (en segundos) que la réplica de lectura va por detrás del origen - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · replay_lag de pg_stat_replication: tiempo desde que el servidor principal escribe el WAL hasta que la réplica avisa de que lo aplicó #### db-save-interval · Pérdida de progreso por intervalos de guardado largos · Periodic save window Si para reducir la carga solo se guarda una vez cada varios minutos, cuando el servidor se cae entre dos guardados se pierde el progreso. - Por qué → Efecto → En pantalla: El estado del personaje se guarda una vez cada varios minutos → Entre un guardado y otro se produce un crash o un fallo del servidor → Al volver a conectar, el personaje está como hace unos minutos (rollback) - Síntomas: Acción perdida / rollback / Factores: Pérdida de paquetes - A quién: Todo el servidor, Una zona o un canal / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Guardar al instante los eventos importantes (intercambios, obtención de objetos raros), registrar un log de cambios. - Tareas (Equipo de infraestructura): Comprobar que la BD tiene margen de IOPS y CPU para la escritura adicional que supone acortar el intervalo de guardado. - En el gráfico: Desconexión masiva (Número de conexiones, número de reportes de rollback) - Dónde mirar: Poner lado a lado la hora del crash o el fallo y la hora del último guardado de los personajes que reportaron rollback (log de guardados del servidor del juego o columna de fecha de modificación en la BD) - Se confirma si: El punto al que volvió coincide con el último guardado antes del crash, y el tiempo perdido es menor que el intervalo de guardado - Se descarta si: Si el log del servidor del juego dice que el guardado terminó y aun así se revirtió, apunta a la pérdida de datos de un failover de la BD (db-failover) o a valores antiguos leídos de una réplica (db-replica-lag) - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Asynchronous Commit (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-async-commit.html) · PostgreSQL · Agrupar las escrituras y pasarlas a disco más tarde aumenta el throughput, pero ante un fallo pueden perderse las transacciones más recientes (el mismo compromiso) - [Redis persistence](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/) · Redis · Si se hace una instantánea RDB cada pocos minutos, hay que asumir que un cierre anómalo puede hacer perder los datos de los últimos minutos #### db-cache-stampede · Estampida de caché · Cache stampede / thundering herd Si la caché de unos datos populares caduca a la vez, miles de solicitudes se lanzan de golpe contra la BD. - Por qué → Efecto → En pantalla: Los datos populares guardados en Redis u otra caché caducan a la vez → Las solicitudes que intentan regenerar esos mismos datos se lanzan de golpe contra la BD → Por la sobrecarga de la BD, varias funciones se ralentizan o se congelan una tras otra - Síntomas: Input lag, Congelamiento, No conecta / carga infinita / Factores: Detención, Latencia - A quién: Todo el servidor / Cuándo: A intervalos regulares, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Repartir al azar la hora de caducidad, dejar que solo una solicitud regenere el dato y que las demás usen el valor antiguo. - Tareas (Equipo de infraestructura): Configurar réplicas y failover automático para que la caché no se vacíe entera cuando Redis se reinicia o falla, comprobar que la BD tiene margen para aguantar con la caché vacía. - En el gráfico: Picos periódicos (Tasa de aciertos de la caché, consultas por segundo de la BD) - Dónde mirar: keyspace_hits y keyspace_misses (tasa de aciertos), expired_keys y reinicios (uptime_in_seconds) de INFO de Redis, superpuestos a las consultas por segundo de la BD; contar cuántas consultas iguales se ejecutan a la vez en la BD en ese momento (MySQL SHOW PROCESSLIST, PostgreSQL pg_stat_activity) - Se confirma si: Cuando los fallos de caché se disparan de repente, las consultas a la BD también se disparan, y la mayoría de las consultas simultáneas son la misma consulta que lee los mismos datos. Coincide con el ciclo de caducidad de una clave popular o con un reinicio de Redis - Se descarta si: Si los fallos de caché son los normales pero solo aumentan las consultas a la BD, apunta a una avalancha de inicios de sesión (db-login-storm) o a procesos batch (db-batch) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Lo mismo ocurre si Redis se reinicia o falla y la caché se vacía entera. Cuanto más pequeña se haya dimensionado la BD confiando en la caché, mayor es el riesgo. - Fuentes: - [Scaling Memcache at Facebook (NSDI '13)](https://www.usenix.org/conference/nsdi13/technical-sessions/presentation/nishtala) · USENIX · Cuando se invalida una clave muy usada, muchas lecturas se lanzan contra la BD (thundering herd); se evita con leases (solo un cliente regenera el dato) y devolviendo valores antiguos; los clústeres con la caché vacía se precalientan aparte - [Optimal Probabilistic Cache Stampede Prevention](https://www.vldb.org/pvldb/vol8/p886-vattani.pdf) · VLDB Endowment · Cuando un elemento popular caduca, varias solicitudes lo regeneran a la vez (estampida de caché); se evita regenerándolo de forma probabilística antes de que caduque - [High availability with Redis Sentinel](https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/) · Redis · Failover automático que promueve una réplica cuando cae el servidor principal - [INFO](https://redis.io/docs/latest/commands/info/) · Redis · keyspace_hits y keyspace_misses (búsquedas de claves con y sin éxito), expired_keys (claves caducadas), uptime_in_seconds (tiempo desde el arranque) - [SHOW PROCESSLIST Statement](https://dev.mysql.com/doc/refman/8.4/en/show-processlist.html) · MySQL · La sentencia que ejecuta cada sesión (Info) y el tiempo que lleva en su estado actual (Time, en segundos) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · pg_stat_activity: la consulta que cada sesión está ejecutando (query) #### db-long-tx · Transacciones abiertas durante mucho tiempo · Long-running transaction / MVCC purge lag Si una transacción permanece abierta mucho tiempo, sigue reteniendo sus bloqueos y la BD no puede limpiar (purge) las versiones antiguas de los datos, así que todo se vuelve cada vez más lento. - Por qué → Efecto → En pantalla: Se espera la respuesta de otro servidor con la transacción abierta, o se ejecuta en producción una consulta de agregación larga en la BD principal → Los bloqueos retenidos no se liberan y las versiones antiguas pendientes de limpieza se siguen acumulando → Timeouts en las funciones que usan esas filas; guardados y consultas cada vez más lentos en general a lo largo de varias horas - Síntomas: Input lag, Acción perdida / rollback / Factores: Latencia, Detención - A quién: Solo una función, Todo el servidor / Cuándo: Cuanto más tiempo lleva encendido, De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): No esperar llamadas de red ni respuestas del usuario dentro de una transacción, hacer las consultas de agregación en una réplica. - Tareas (Equipo de infraestructura): Configurar alertas y cierre forzado para las transacciones abiertas demasiado tiempo, ofrecer una réplica para agregaciones, vigilar el crecimiento del undo log y de las filas muertas. - En el gráfico: Subida gradual (Longitud del undo log (History list length), número de filas muertas) - Dónde mirar: En MySQL, buscar la transacción más antigua con trx_started de INFORMATION_SCHEMA.INNODB_TRX y revisar History list length (cantidad de undo log aún sin limpiar) en la sección TRANSACTIONS de SHOW ENGINE INNODB STATUS. En PostgreSQL, xact_start de pg_stat_activity y las sesiones con state idle in transaction, y n_dead_tup de pg_stat_user_tables - Se confirma si: Hay una transacción de minutos u horas de antigüedad; mientras tanto History list length o n_dead_tup no paran de subir, y bajan cuando se termina esa transacción y se ejecuta la limpieza (purge, VACUUM) - Se descarta si: Si no hay transacciones antiguas y todo va lento en general, apunta a checkpoints (db-checkpoint) o al disco - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: La BD conserva versiones antiguas para que quien lee pueda ver los datos como estaban antes de modificarse (MVCC). Este registro solo se puede borrar cuando termina la transacción más antigua, así que si una transacción queda abierta varias horas, en MySQL se acumula el undo log y en PostgreSQL las filas muertas (dead tuples) que VACUUM no pudo limpiar. En SQL Server, el log de transacciones no se reduce y puede llegar a llenar el disco. - Fuentes: - [InnoDB Multi-Versioning](https://dev.mysql.com/doc/refman/8.4/en/innodb-multi-versioning.html) · MySQL · Mientras quede una transacción que pueda ver versiones antiguas, no se puede descartar el undo log de update y el segmento de rollback crece; se recomienda hacer commit a menudo incluso en las transacciones de solo lectura - [Routine Vacuuming (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/routine-vacuuming.html) · PostgreSQL · Las versiones antiguas de las filas no se pueden borrar mientras otras transacciones puedan verlas; las transacciones abiertas mucho tiempo hay que terminarlas o cerrar la sesión - [Client Connection Defaults (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-client.html) · PostgreSQL · idle_in_transaction_session_timeout: corta las sesiones inactivas con una transacción abierta para que no retengan bloqueos mucho tiempo - [Troubleshoot a full transaction log (SQL Server Error 9002)](https://learn.microsoft.com/en-us/sql/relational-databases/logs/troubleshoot-a-full-transaction-log-sql-server-error-9002) · Microsoft SQL Server · Una transacción activa de larga duración impide truncar el log de transacciones - [The INFORMATION_SCHEMA INNODB_TRX Table](https://dev.mysql.com/doc/refman/8.4/en/information-schema-innodb-trx-table.html) · MySQL · TRX_STARTED: hora de inicio de la transacción - [Purge Configuration](https://dev.mysql.com/doc/refman/8.4/en/innodb-purge-configuration.html) · MySQL · Purge limpia la lista de undo logs de las transacciones confirmadas (history list); lo pendiente aparece como History list length en la sección TRANSACTIONS de SHOW ENGINE INNODB STATUS - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · xact_start (hora de inicio de la transacción) y state (idle in transaction) de pg_stat_activity, n_dead_tup (estimación de filas muertas) de pg_stat_user_tables #### db-redis-block · Comandos lentos en Redis · Redis blocking commands (single-threaded) Redis procesa los comandos de uno en uno, así que un solo comando lento bloquea todas las solicitudes que vienen detrás. - Por qué → Efecto → En pantalla: En producción se busca en todo el keyspace con KEYS, o se lee o borra de una vez un ranking o una lista de millones de elementos → Todas las demás solicitudes esperan hasta que termina ese comando (de decenas de ms a varios segundos) → Tirones a la vez en todas las funciones que usan sesiones, rankings o caché; inicios de sesión lentos - Síntomas: Congelamiento, Input lag, No conecta / carga infinita / Factores: Detención, Latencia - A quién: Todo el servidor, Solo una función / Cuándo: De vez en cuando, al azar, A intervalos regulares - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Sustituir KEYS por SCAN, dividir las claves grandes, borrar con UNLINK (borrado en segundo plano), repartir las caducidades que coinciden en el mismo segundo. - Tareas (Equipo de infraestructura): Vigilar el registro de comandos lentos (SLOWLOG), bloquear en los servidores de producción los comandos peligrosos como KEYS, revisar periódicamente las claves grandes, desactivar THP y dejar memoria libre para el fork, hacer los guardados RDB y AOF en una réplica. - Cifras de referencia: Un comando normal tarda menos de 1 ms. Manejar millones de elementos de una vez puede tardar de cientos de ms a varios segundos. - En el gráfico: Picos aleatorios (Latencia de respuesta de Redis, número de comandos lentos) - Dónde mirar: Ver con SLOWLOG GET los comandos que superan slowlog-log-slower-than; activar el monitor de latencia (desactivado por defecto) con CONFIG SET latency-monitor-threshold y revisar con LATENCY LATEST y LATENCY DOCTOR la latencia por evento, como fork o expire-cycle. Comprobar también el tiempo de fork con latest_fork_usec de INFO y las claves grandes con redis-cli --bigkeys - Se confirma si: A la hora de la detención, SLOWLOG tiene un KEYS o un comando que maneja una clave grande entera, o LATENCY registra a esa misma hora eventos fork o expire-cycle de decenas de ms o más - Se descarta si: Si SLOWLOG y LATENCY están vacíos y solo va lento desde el servidor del juego, apunta a la red o a esperas dentro del servidor del juego (SLOWLOG solo mide el tiempo de ejecución del comando, sin el intercambio con el cliente) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: También se detiene en el momento de duplicar el proceso (fork) para crear el archivo de guardado (instantánea RDB) o reescribir el AOF. En servidores actuales cuesta unos 10 ms por GB de memoria, así que con 30 GB son unos 300 ms. Con las páginas grandes (THP) activadas, después del fork cada escritura copia una página grande entera (copy-on-write), y las detenciones y el uso de memoria crecen mucho; por eso normalmente se desactiva THP y se deja memoria libre de sobra. Redis también se detiene un momento cuando caducan muchísimas claves en el mismo segundo y tiene que borrarlas. - Fuentes: - [Diagnosing latency issues](https://redis.io/docs/latest/operate/oss_and_stack/management/optimization/latency/) · Redis · Un solo hilo procesa las solicitudes en orden y un comando lento bloquea a todos los que vienen detrás; sustituir KEYS por SCAN; fork medido en servidores físicos y VM modernas: unos 9–13 ms por GB; con THP, la copia tras el fork dispara la latencia y la memoria; muchas caducidades en el mismo segundo provocan detenciones - [KEYS](https://redis.io/docs/latest/commands/keys/) · Redis · Usar con extrema precaución en producción: puede arruinar el rendimiento en BD grandes (medido en una computadora portátil de gama básica: 40 ms con 1 millón de claves) - [UNLINK](https://redis.io/docs/latest/commands/unlink/) · Redis · Borrado asíncrono que desvincula la clave al instante y libera la memoria en otro hilo - [SLOWLOG](https://redis.io/docs/latest/commands/slowlog/) · Redis · Log de comandos lentos que registra los comandos que superan slowlog-log-slower-than; el tiempo de ejecución no incluye la E/S con el cliente - [Redis latency monitoring](https://redis.io/docs/latest/operate/oss_and_stack/management/optimization/latency-monitor/) · Redis · latency-monitor-threshold es 0 (desactivado) por defecto; LATENCY LATEST y LATENCY DOCTOR; registra la latencia por evento, como fork o expire-cycle - [INFO](https://redis.io/docs/latest/commands/info/) · Redis · latest_fork_usec: tiempo que tardó el último fork (microsegundos) - [Redis CLI](https://redis.io/docs/latest/develop/tools/cli/) · Redis · --bigkeys: recorre el keyspace para encontrar claves grandes #### db-plan-flip · Consultas lentas por un cambio en el plan de ejecución · Query plan regression (stats, parameter sniffing) Aunque el código no cambie, si la BD cambia la forma de procesar una consulta (el plan de ejecución), una consulta que ayer tardaba 2 ms hoy tarda cientos de ms. - Por qué → Efecto → En pantalla: La actualización automática de estadísticas, un reinicio de la BD o un cambio en la distribución de los datos hacen que la BD calcule un plan de ejecución nuevo → Se elige un plan que no usa índice, la misma consulta pasa a ser de decenas a cientos de veces más lenta y las conexiones quedan ocupadas → Sin ningún despliegue, la carga de una función concreta se vuelve lenta de repente y otras solicitudes también esperan - Síntomas: Input lag, No conecta / carga infinita / Factores: Latencia, Detención - A quién: Solo una función, Todo el servidor / Cuándo: De vez en cuando, al azar - Responsable principal: Infraestructura de BD (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Separar las consultas cuyo número de resultados varía mucho según el valor o valorar hints del plan, diseñar las consultas para que usen índice siempre. - Tareas (Equipo de infraestructura): Vigilar los registros de consultas lentas y de planes de ejecución, fijar los planes buenos (Almacén de consultas de SQL Server, entre otros), controlar la hora de actualización de las estadísticas. - En el gráfico: Salto en escalón (Tiempo medio de ejecución por consulta) - Dónde mirar: Recoger periódicamente el tiempo medio de cada forma de consulta y ver la tendencia: en MySQL, AVG_TIMER_WAIT de events_statements_summary_by_digest; en PostgreSQL, mean_exec_time de pg_stat_statements (mean_time en la versión 12 y anteriores). Comparar los planes de ejecución de antes y después de la ralentización con EXPLAIN o auto_explain de PostgreSQL, y en SQL Server con la vista Consultas con regresión (Regressed Queries) del Almacén de consultas - Se confirma si: Sin despliegue de por medio, el tiempo medio de una consulta se multiplica de golpe por varias decenas (salto en escalón), en un momento que coincide con una actualización de estadísticas o un reinicio de la BD, y el plan de ejecución ha cambiado - Se descarta si: Si el plan de ejecución no ha cambiado y aun así va más lento, apunta al crecimiento de los datos, a esperas por bloqueo (db-hot-row) o al disco - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: SQL Server reutiliza el plan calculado para el primer valor que recibe (parameter sniffing). Si un plan calculado con un personaje nuevo que tiene unos pocos objetos se usa para un personaje veterano con decenas de miles, la consulta va mucho más lenta, y el caso contrario también es habitual. Al reiniciar se borran los planes, y a veces todo va bien un tiempo hasta que vuelve a empeorar. - Fuentes: - [Query Processing Architecture Guide](https://learn.microsoft.com/en-us/sql/relational-databases/query-processing-architecture-guide) · Microsoft SQL Server · Parameter sniffing: el plan de ejecución se calcula según los valores de los parámetros que llegan al compilar o recompilar - [Parameter Sensitive Plan Optimization](https://learn.microsoft.com/en-us/sql/relational-databases/performance/parameter-sensitive-plan-optimization) · Microsoft SQL Server · Si los datos no están distribuidos de forma uniforme, un único plan en caché no sirve para todos los valores de los parámetros - [Monitor performance by using the Query Store](https://learn.microsoft.com/en-us/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store) · Microsoft SQL Server · Los cambios de estadísticas, esquema o índices cambian el plan, y la caché de planes solo guarda el más reciente; forzar un plan en el Almacén de consultas fija el bueno, y la vista Consultas con regresión (Regressed Queries) compara las consultas ralentizadas y sus planes - [Statement Summary Tables](https://dev.mysql.com/doc/refman/8.4/en/performance-schema-statement-summary-tables.html) · MySQL · events_statements_summary_by_digest: COUNT_STAR y AVG_TIMER_WAIT (tiempo medio) por cada forma de consulta - [pg_stat_statements — track statistics of SQL planning and execution](https://www.postgresql.org/docs/current/pgstatstatements.html) · PostgreSQL · calls, total_exec_time y mean_exec_time (tiempo medio de ejecución) por sentencia - [pg_stat_statements (PostgreSQL 12 Documentation)](https://www.postgresql.org/docs/12/pgstatstatements.html) · PostgreSQL · Hasta la versión 12, las columnas se llaman total_time y mean_time - [auto_explain — log execution plans of slow queries](https://www.postgresql.org/docs/current/auto-explain.html) · PostgreSQL · Registra en el log el plan de ejecución de las consultas que tardan más que auto_explain.log_min_duration #### db-ddl-lock · Bloqueos por cambios de esquema (DDL) en producción · Schema change lock (DDL / metadata lock) Si se añade una columna o un índice a una tabla con el servicio en marcha, un bloqueo que solo se necesita durante un instante puede dejar esperando a todas las solicitudes que usan esa tabla. - Por qué → Efecto → En pantalla: Un hotfix añade una columna o un índice a una tabla en producción → El cambio de esquema espera a una transacción larga que ya estaba abierta, y todas las solicitudes que llegan después esperan al cambio de esquema → Las funciones que usan esa tabla (inventario, correo, etc.) se quedan congeladas por completo y dan timeout - Síntomas: Input lag, Acción perdida / rollback, No conecta / carga infinita / Factores: Detención - A quién: Solo una función, Todo el servidor / Cuándo: De vez en cuando, al azar, Al conectar o tras un mantenimiento - Responsable principal: Infraestructura de BD (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Acordar con el responsable de infraestructura de BD el calendario de los hotfixes con cambios de esquema, desplegar primero el código que funciona aunque la columna nueva no exista. - Tareas (Equipo de infraestructura): Poner un límite de espera de bloqueo corto y reintentar si falla, ejecutar el cambio cuando no haya transacciones largas, usar herramientas de cambio online, hacer los cambios en tablas grandes durante el mantenimiento. - En el gráfico: Salto en escalón (Sesiones esperando un bloqueo, latencia de las consultas de esa tabla) - Dónde mirar: En MySQL, contar las sesiones con State Waiting for table metadata lock en SHOW PROCESSLIST y buscar la sesión que bloquea (blocking_pid) con sys.schema_table_lock_waits. En PostgreSQL, las solicitudes con granted en false y AccessExclusiveLock en pg_locks, y la sesión que bloquea con pg_blocking_pids() - Se confirma si: Desde la hora en que empezó el cambio de esquema, todas las consultas a esa tabla se acumulan esperando el bloqueo, y al principio de la cola hay una transacción sin terminar o la sentencia del cambio de esquema - Se descarta si: Si las esperas se concentran en filas concretas y las demás filas de la misma tabla se procesan bien, apunta a una fila caliente (db-hot-row) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Para cambiar el esquema, MySQL retiene un momento un bloqueo de metadatos y PostgreSQL el bloqueo de tabla más fuerte. Aunque el cambio en sí sea instantáneo, si delante hay una transacción sin terminar, todas las solicitudes quedan esperando detrás. - Fuentes: - [Online DDL Performance and Concurrency](https://dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl-performance.html) · MySQL · Incluso el DDL online necesita un bloqueo exclusivo de metadatos durante un instante al terminar; si hay una transacción larga, espera, y esa solicitud de bloqueo en espera bloquea todas las transacciones posteriores - [Server System Variables](https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html) · MySQL · lock_wait_timeout: límite de espera del bloqueo de metadatos, 31,536,000 segundos (1 año) por defecto - [ALTER TABLE (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/sql-altertable.html) · PostgreSQL · Un ALTER TABLE sin indicación explícita toma el bloqueo más fuerte, ACCESS EXCLUSIVE - [Client Connection Defaults (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-client.html) · PostgreSQL · lock_timeout: si se espera un bloqueo más de este tiempo, la sentencia se cancela - [General Thread States](https://dev.mysql.com/doc/refman/8.4/en/general-thread-states.html) · MySQL · Waiting for table metadata lock: estado del hilo que espera un bloqueo de metadatos - [The schema_table_lock_waits and x$schema_table_lock_waits Views](https://dev.mysql.com/doc/refman/8.4/en/sys-schema-table-lock-waits.html) · MySQL · La sesión que espera el bloqueo de metadatos (waiting_query) y la que lo bloquea (blocking_pid) - [pg_locks (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/view-pg-locks.html) · PostgreSQL · granted en false indica espera de bloqueo; mode muestra el tipo de bloqueo, como AccessExclusiveLock - [System Information Functions and Operators (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/functions-info.html) · PostgreSQL · pg_blocking_pids(): lista de sesiones que impiden que la sesión indicada consiga un bloqueo ### L13 Arquitectura y operación de servidores (causas: 13) #### in-gateway · Paso por un gateway o proxy · Gateway / proxy hop Si se pone un servidor intermedio entre el cliente y el servidor del juego, cada paso por él suma tiempo de procesamiento y ese servidor se convierte en un punto único de fallo. - Por qué → Efecto → En pantalla: Arquitectura cliente ↔ gateway ↔ servidor del juego → El servidor intermedio añade procesamiento y espera; si se sobrecarga, afecta a todos → El ping sube para todos; si el gateway falla, todos los jugadores que pasan por él sufren una desconexión - Síntomas: Input lag, Desconexión / Factores: Latencia, Detención - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente, Siempre - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: diseñar la arquitectura para poder tener varios gateways y para que, si uno se cae, el personaje siga tal cual al reconectarse por otro (reconexión de sesión). Cliente: reconectar automáticamente si se corta el gateway. - Tareas (Equipo de infraestructura): Escalar los gateways horizontalmente (añadir más), monitorear la CPU, las conexiones y la latencia de procesamiento de cada gateway. - Cifras de referencia: Dentro del mismo centro de datos, cada paso suele costar menos de 1 ms. Si el gateway se sobrecarga, sube a decenas o cientos de ms. - En el gráfico: Sube con la carga (Latencia de procesamiento del gateway, CPU y conexiones del gateway) - Dónde mirar: CPU y número de conexiones del gateway, Recv-Q de sus sockets (ss, netstat) y diferencia de latencia antes y después del gateway. Para llamadas HTTP o gRPC que pasan por la malla de servicios, comparar la métrica estándar de Istio istio_request_duration_milliseconds separada por emisor (reporter=source) y receptor (reporter=destination) - Se confirma si: El tiempo de procesamiento del servidor del juego no cambia, pero sube solo la latencia del tramo del gateway, y en ese momento la CPU del gateway está saturada o se acumula Recv-Q - Se descarta si: Si las rutas que no pasan por el gateway (conexión directa, otro gateway) van igual de lentas, apunta a la conexión o al servidor del juego - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Con una malla de servicios (service mesh), como Istio, el proxy sidecar (Envoy) que acompaña a cada servidor también suma un salto. Las solicitudes entre servicios pasan primero por el sidecar del emisor y después por el del receptor, y cuantas más funciones se añaden al proxy (recolección de logs y métricas, etc.), más crecen el tiempo de procesamiento y la espera. - Casos reales: riot-edge-2020 - Fuentes: - [The Unique Architecture behind Amazon Games’ Seamless MMO New World](https://aws.amazon.com/blogs/gametech/the-unique-architecture-behind-amazon-games-seamless-mmo-new-world/) · AWS · En New World, el cliente se conecta a uno de los 4 servidores de entrada (REP) con dirección pública y desde ahí se comunica con los servidores de simulación (hubs) que hay detrás - [Designs, Lessons and Advice from Building Large Distributed Systems](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Keynote de LADIS 2009 (Jeff Dean). Ida y vuelta dentro del mismo centro de datos: unos 0.5 ms - [Site Reliability Engineering, Chapter 22: Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/) · Google · Si la cola crece por sobrecarga, la espera llega a ser varias veces el tiempo de procesamiento (con 100 ms de procesamiento y una cola de 10 veces el número de hilos, 1.1 s) - [Performance and Scalability](https://istio.io/latest/docs/ops/deployment/performance-and-scalability/) · Istio · En modo sidecar, las solicitudes pasan sucesivamente por el proxy sidecar del emisor y por el del receptor; cuantas más funciones se añaden, más largo es el camino de procesamiento dentro del proxy, y la recolección de telemetría aumenta la espera de la siguiente solicitud - [What is Envoy](https://www.envoyproxy.io/docs/envoy/latest/intro/what_is_envoy) · Envoy · Envoy es un proceso aparte que corre junto a cada servidor de aplicaciones, y la aplicación envía y recibe a través del Envoy en localhost - [Istio Standard Metrics](https://istio.io/latest/docs/reference/config/metrics/) · Istio · istio_request_duration_milliseconds (distribución del tiempo de procesamiento de solicitudes HTTP y gRPC); la etiqueta reporter distingue el proxy emisor (source) del receptor (destination) - [netstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/netstat.8.html) · net-tools · Recv-Q: en un socket conectado, bytes que el programa de usuario aún no ha recogido #### in-zone-transfer · Cambio de zona (traspaso entre servidores) · Zone / server handoff Al entrar en otra zona o mazmorra, los datos del personaje se traspasan a otro servidor, y en ese proceso surgen retrasos y fallos. - Por qué → Efecto → En pantalla: Al entrar en una mazmorra o cambiar de continente, cambia el servidor responsable → Guardar → transferir → cargar; si el servidor de destino está saturado o no hay instancias de mazmorra libres, toca esperar → Cargas largas, fallos al entrar, desconexión durante el traslado - Síntomas: No conecta / carga infinita, Congelamiento, Desconexión, Rubber banding / Factores: Latencia, Detención - A quién: Solo yo, Una zona o un canal / Cuándo: Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Reducir los datos que se traspasan, reservar de antemano el servidor de destino, devolver al personaje a su sitio original si falla. - Tareas (Equipo de infraestructura): Monitorear el margen de instancias libres en los servidores de mazmorras y zonas, asegurar suficientes servidores antes de las horas pico. - En el gráfico: Sube con la carga (Duración y fallos del cambio de zona) - Dónde mirar: Duración de cada etapa del traspaso que registra el servidor (guardar, transferir, cargar) y motivos de fallo, número de jugadores e instancias libres del servidor de destino - Se confirma si: A la hora de los reportes de cargas largas o fallos al entrar, el tiempo de traspaso sube o se acumulan los fallos, y el servidor de destino está saturado o sin instancias libres - Se descarta si: Si el traspaso terminó rápido pero todo se detiene al llegar, apunta a “Avalancha de spawns al entrar en una zona concurrida” o a la carga del cliente - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: En un mundo sin costuras (seamless), sin pantallas de carga, el servidor responsable también cambia al cruzar la frontera entre servidores. Cerca de esa frontera puede haber un tirón breve o rubber banding. - Fuentes: - [The Unique Architecture behind Amazon Games’ Seamless MMO New World](https://aws.amazon.com/blogs/gametech/the-unique-architecture-behind-amazon-games-seamless-mmo-new-world/) · AWS · El mundo sin pantallas de carga se divide en una cuadrícula que reparten varios servidores (hubs), y cuando el jugador se mueve su estado pasa de un hub a otro; los modos por sesión toman servidores libres de un pool compartido #### in-cascade · Fallo en cascada · Cascading failure Cuando un servicio se vuelve lento, los servidores que lo llaman se quedan bloqueados esperando su respuesta y hasta funciones sin relación se detienen. - Por qué → Efecto → En pantalla: Un servicio, como la BD o la autenticación, se vuelve lento → Los hilos y conexiones de los servidores que lo llaman quedan retenidos esperando respuesta, y los reintentos de las solicitudes fallidas suman carga → Hasta funciones que parecen no tener relación se vuelven lentas o se detienen - Síntomas: Congelamiento, Input lag, No conecta / carga infinita / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente, De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Poner timeout a todas las llamadas, usar circuit breakers y aislamiento por función (bulkheads), reintentar con intervalos crecientes y un número limitado de veces, separar las respuestas de health check del trabajo pesado. - Tareas (Equipo de infraestructura): Dar margen en el número de fallos y el intervalo de los health checks del balanceador de carga para que no saque de inmediato a un servidor que va lento un momento, limitar cuántos servidores pueden salir a la vez. - En el gráfico: Topa con el límite (Tiempo de respuesta y tasa de errores por servicio, hilos y conexiones en uso) - Dónde mirar: Poner en una sola pantalla, con el eje de tiempo alineado, el tiempo de respuesta, la tasa de errores y los reintentos de cada servicio, y buscar cuál se volvió lento primero. Detrás de un balanceador de carga, tiempo de respuesta de los destinos (TargetResponseTime en AWS ALB), número de 5xx de los destinos (HTTPCode_Target_5XX_Count) y número de destinos retirados por no estar sanos (UnHealthyHostCount) - Se confirma si: Primero sube la latencia de un servicio; después, los hilos y conexiones en uso de quienes lo llaman tocan el límite, los errores se extienden a otros servicios y crecen a la vez los reintentos y los destinos retirados - Se descarta si: Si varios servicios se volvieron lentos en el mismo instante, revisar primero un fallo de un recurso compartido (BD, red, host) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Los health checks (comprobaciones de que un servidor sigue vivo) también agravan la cascada. Si un servidor ocupado responde tarde al health check, el balanceador de carga saca a un servidor que funciona bien, su tráfico se concentra en los que quedan y el siguiente también empieza a responder tarde. - Casos reales: riot-edge-2020, riot-euw-2021, roblox-2021, aws-2021, aws-2025 - Fuentes: - [Site Reliability Engineering, Chapter 22: Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/) · Google · Si un servidor sobrecargado falla el health check y sale, la carga se concentra en los que quedan y los reintentos la agravan; se recomienda limitar los reintentos, usar backoff exponencial aleatorio y fijar plazos (deadlines) - [Circuit Breaker Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) · Microsoft Azure · Las solicitudes bloqueadas hasta el timeout retienen hilos y conexiones a la BD y hacen fallar funciones sin relación; si se acumulan fallos en un tiempo dado, rechazar las llamadas de inmediato - [Timeouts, retries, and backoff with jitter](https://d1.awsstatic.com/builderslibrary/pdfs/timeouts-retries-and-backoff-with-jitter.pdf) · AWS · Amazon Builders' Library. Con 5 niveles de llamadas y 3 reintentos en cada nivel, la carga sobre la BD se multiplica por 243; reintentar en un solo punto y limitarlo con un token bucket - [CloudWatch metrics for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html) · AWS · TargetResponseTime (tiempo desde que la solicitud sale del balanceador de carga hasta que el destino empieza a responder), HTTPCode_Target_5XX_Count (número de 5xx generados por los destinos), UnHealthyHostCount (número de destinos no sanos) #### in-subservice · Caída de un servidor auxiliar · Auxiliary service outage Si falla un servidor que funciona aparte del servidor del juego, como el del chat, los grupos o la casa de subastas, solo deja de funcionar esa función. - Por qué → Efecto → En pantalla: El servidor dedicado a una función se vuelve lento o se cae → Solo las solicitudes de esa función se quedan sin respuesta → El chat no funciona, las invitaciones de grupo no responden, el mercado se queda en carga infinita (el combate va normal) - Síntomas: Acción perdida / rollback, No conecta / carga infinita / Factores: Detención, Pérdida de paquetes - A quién: Solo una función / Cuándo: De vez en cuando, al azar, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Diseñar para que el juego continúe aunque la función falle, mostrar el estado de cada función, no concentrar varias funciones en un solo servidor central. - Tareas (Equipo de infraestructura): Health checks y alertas para cada servidor auxiliar, redundancia y reinicio automático. - En el gráfico: Desconexión masiva (Tasa de éxito de las solicitudes por función, conexiones y health checks de los servidores auxiliares) - Dónde mirar: Health checks, estado del proceso y conexiones de cada servidor auxiliar (chat, grupos, casa de subastas, etc.), tasa de éxito y tiempo de respuesta de las solicitudes por función. Detrás de un balanceador de carga, UnHealthyHostCount del grupo de destino - Se confirma si: Solo el servidor de la función reportada falla los health checks o pierde conexiones de golpe, mientras los ticks y el combate del servidor del juego van normales - Se descarta si: Si se detuvieron varias funciones a la vez, apunta al servidor central que hace de intermediario para todas ellas o a “Fallo en cascada” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Si un único servidor central (servidor de mundo o servidor gestor) hace de intermediario para grupos, gremios, mensajes privados y traslados entre servidores, cuando ese servidor se vuelve lento se detienen varias funciones a la vez. - Fuentes: - [Bulkhead Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead) · Microsoft Azure · Si se aíslan los componentes en pools, aunque uno falle los demás siguen funcionando y el fallo no se extiende - [REL05-BP01 Implement graceful degradation to transform applicable hard dependencies into soft dependencies](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_mitigate_interaction_failure_graceful_degradation.html) · AWS · AWS Well-Architected. Diseñar para que, aunque falle una dependencia, las funciones esenciales sigan funcionando con datos algo antiguos o alternativos - [CloudWatch metrics for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html) · AWS · UnHealthyHostCount: número de destinos que el health check da por no sanos #### in-deploy · Despliegues y reinicios · Deploy / rolling restart Si al reiniciar un servidor para actualizarlo no se trasladan sus conexiones, los jugadores que estaban en él se desconectan, y los guardados justo antes del cierre y las reconexiones llegan todos de golpe. - Por qué → Efecto → En pantalla: Se despliega un hotfix y se reinician los servidores uno tras otro → Se apaga sin trasladar las conexiones a otro servidor, y los guardados de todos los jugadores de ese servidor se concentran en la BD → Desconexión sin aviso, avalancha de reconexiones - Síntomas: Desconexión, No conecta / carga infinita, Input lag / Factores: Detención - A quién: Todo el servidor, Una zona o un canal / Cuándo: De vez en cuando, al azar, Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Implementar una función de drenaje (bloquear solo las conexiones nuevas y esperar a que salgan los jugadores que ya están), trasladar personajes a otro servidor, repartir los guardados antes del cierre, avisar de que el servidor está listo solo después de cargar la caché y terminar el calentamiento del JIT tras reiniciar, y en la recarga en caliente (hot reload) leer los datos de antemano en otro hilo y sustituirlos de una vez entre ticks. - Tareas (Equipo de infraestructura): Hacer que la herramienta de despliegue reinicie los servidores de uno en uno esperando al drenaje, que el servidor reiniciado reciba tráfico solo tras confirmar que está listo (calentamiento terminado), anunciar la hora del despliegue. - Cifras de referencia: Con 5,000 jugadores en un servidor, llegan 5,000 guardados a la BD en los pocos segundos antes del cierre. - En el gráfico: Desconexión masiva (Conexiones por servidor, escrituras en la BD) - Dónde mirar: Superponer el registro de la herramienta de despliegue (hora de reinicio de cada servidor) como líneas verticales (anotaciones) sobre los gráficos de conexiones, desconexiones, escrituras en la BD y solicitudes de inicio de sesión - Se confirma si: Las conexiones de cada servidor caen en picado una tras otra a la hora de su reinicio, con un pico de escrituras en la BD justo antes y de solicitudes de inicio de sesión justo después - Se descarta si: Si la hora de las desconexiones no coincide con el registro de despliegues y reinicios, apunta a un crash del servidor o a los equipos de red - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Justo después de volver a arrancar, el servidor también va lento durante unos minutos. La caché está vacía y se acumulan las consultas a la BD, y en los servidores Java o C# todavía no ha terminado el proceso que optimiza el código mientras se ejecuta (calentamiento del JIT), así que el mismo trabajo tarda más. Recargar scripts o tablas de datos sin apagar el servidor (hot reload) también detiene el tick mientras se leen, lo que provoca una pausa breve. - Fuentes: - [Site Reliability Engineering, Chapter 20: Load Balancing in the Datacenter](https://sre.google/sre-book/load-balancing-datacenter/) · Google · El servidor que recibe SIGTERM entra en estado lame duck, desvía las solicitudes nuevas a otros servidores y solo termina las que están en curso; en los primeros minutos tras reiniciar consume más recursos porque el JIT aún no ha optimizado el código, así que recibe tráfico solo después del calentamiento - [Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/workloads/pods/probes/) · Kubernetes · Con una readiness probe, no se envía tráfico hasta terminar de establecer conexiones, cargar archivos y calentar la caché - [Edit target group attributes for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/edit-target-group-attributes.html) · AWS · Al dar de baja un destino, no se le envían conexiones nuevas y las existentes se drenan (300 s por defecto) #### in-autoscale · Retraso del autoescalado · Autoscaling lag Cuando se junta mucha gente, se añaden servidores automáticamente, pero prepararlos lleva unos minutos y mientras tanto los servidores existentes van sobrecargados. - Por qué → Efecto → En pantalla: Empieza un evento y las conexiones se disparan → Un servidor nuevo tarda varios minutos en arrancar y estar listo → Cámara lenta y el juego no conecta durante los primeros minutos del evento - Síntomas: Cámara lenta, No conecta / carga infinita / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente, Al conectar o tras un mantenimiento - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Repartir a los jugadores entre canales (los que ya están en un canal lleno no se pueden mover a un servidor nuevo), reducir el tiempo de arranque y de carga de datos de los servidores nuevos. - Tareas (Equipo de infraestructura): Escalar por adelantado antes de los eventos, tener servidores de reserva ya calentados, y al reducir apagar cada servidor solo cuando hayan salido los jugadores que quedan. - Cifras de referencia: Detectar la carga lleva de 1 a unos pocos minutos (porque las métricas se miran como promedio de varios minutos), y arrancar el servidor nuevo, leer los datos del juego y llenar la caché lleva otros varios minutos. - En el gráfico: Avalancha tras la apertura (Número de instancias, uso de CPU, conexiones en espera) - Dónde mirar: Superponer el registro de actividad del autoescalado (hora en que se decidió escalar y hora en que la instancia nueva entró en servicio) sobre los gráficos de uso de CPU y conexiones. En AWS, las métricas del grupo de Auto Scaling (solo se ven si se activan) GroupDesiredCapacity (número objetivo), GroupPendingInstances (en preparación) y GroupInServiceInstances (en servicio) - Se confirma si: Tras el pico de conexiones, durante unos minutos solo suben el número objetivo y las instancias en preparación mientras la CPU de los servidores existentes está pegada al límite, y todo se alivia en cuanto aumentan las instancias en servicio - Se descarta si: Si sigue lento después de entrar las instancias nuevas, la causa está fuera del número de servidores (un recurso compartido como la BD, “Fallo en cascada”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: El autoescalado se usa sobre todo donde basta con recibir a los jugadores nuevos en servidores nuevos, como el login, los gateways o las mazmorras. Reducir también trae problemas: si de madrugada, cuando ya queda poca gente, se apagan servidores sin esperar a que salgan los jugadores que quedan, esos jugadores se desconectan. - Casos reales: aws-2021, aws-2025 - Fuentes: - [Target tracking scaling policies for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-scaling-target-tracking.html) · AWS · Las métricas básicas de EC2 van cada 5 minutos (cada minuto con el monitoreo detallado), así que para reaccionar rápido se recomiendan métricas con intervalos de 1 minuto o menos - [Amazon CloudWatch metrics for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-metrics.html) · AWS · Las métricas de grupo se publican cada minuto solo si se activan: GroupDesiredCapacity (número de instancias que se quiere mantener), GroupPendingInstances (instancias que aún no están en servicio) y GroupInServiceInstances (instancias en servicio) - [Scheduled scaling for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-scheduled-scaling.html) · AWS · Aumentar y reducir la capacidad a horas fijas, por adelantado, según los cambios de carga previsibles - [Decrease latency for applications with long boot times using warm pools](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-warm-pools.html) · AWS · Para aplicaciones que tardan en arrancar, un pool de instancias ya inicializadas (warm pool) reduce el retraso del escalado #### in-monitoring · Sobrecarga por logs y monitoreo · Logging / monitoring overhead Cuando hay un incidente, los logs se disparan, y los servidores que envían sus logs de forma síncrona se vuelven todavía más lentos por culpa de esos logs. - Por qué → Efecto → En pantalla: Al aparecer errores, se dispara el volumen de logs y métricas enviados → El recolector de logs se atrasa y los servidores que envían de forma síncrona se quedan esperando → Durante el incidente, los tirones y congelamientos empeoran por culpa de los logs - Síntomas: Tirones, Congelamiento / Factores: Detención - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente, De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Enviar de forma asíncrona, usar muestreo, descartar cuando se llene el búfer, agrupar los logs del mismo error antes de enviarlos. - Tareas (Equipo de infraestructura): Dimensionar el recolector de logs para el volumen pico de un incidente, poner alertas de acumulación en el recolector. - En el gráfico: Picos aleatorios (Volumen de logs enviados, cola del recolector de logs) - Dónde mirar: Líneas y bytes de log por segundo del servidor, cola y descartes del agente recolector de logs, junto con el tiempo de tick. Si hay hilos detenidos, ver con bcc offcputime -p si esperan al escribir o enviar logs - Se confirma si: Cuando el tick se dispara, el volumen de logs sube a decenas de veces lo normal, y el tiempo de espera del hilo del juego se concentra en las pilas de llamadas de escritura o envío de logs - Se descarta si: Si el volumen de logs es el normal o el hilo del juego no espera en los logs, la avalancha de logs es solo una consecuencia del incidente; buscar aparte la causa del primer error - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Logging in C#](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging) · Microsoft · Los métodos de log de .NET son síncronos, así que si el almacenamiento es lento se recomienda escribir primero en uno rápido y moverlos después - [Asynchronous loggers](https://logging.apache.org/log4j/2.x/manual/async.html) · Apache Software Foundation · El logging asíncrono absorbe las ráfagas cortas con una cola, pero si la salida sigue lenta, la cola se llena y todo baja a la velocidad de la salida más lenta, o se descartan logs según la política (Discard) - [Demonstrations of offcputime, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/offcputime_example.txt) · IO Visor · Suma, por pila de llamadas, el tiempo que los hilos pasan detenidos fuera de la CPU (off-CPU); -p indica el proceso #### in-clock-skew · Desfase de reloj entre servidores · Clock skew between servers Si cada servidor tiene un reloj un poco distinto, las comprobaciones de cooldowns, buffs y comienzos de evento no coinciden entre servidores. - Por qué → Efecto → En pantalla: El reloj de un servidor cuya sincronización horaria se detuvo se desfasa de cientos de ms a varios segundos respecto a los demás → Si se pasan horas absolutas entre servidores, como la hora en que termina un buff, las comprobaciones no coinciden → Tras moverse a otro servidor, un buff desaparece o el cooldown vuelve a empezar - Síntomas: Acción perdida / rollback / Factores: Latencia - A quién: Solo yo / Cuándo: Al moverse o cambiar de zona - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Pasar entre servidores el tiempo restante, sin usar horas absolutas. - Tareas (Equipo de infraestructura): Vigilar la sincronización horaria (NTP, chrony), poner alertas por diferencia de reloj entre servidores. - Cifras de referencia: Con la sincronización horaria (NTP, chrony) funcionando, los servidores de un mismo centro de datos suelen estar a pocos ms entre sí. Si la sincronización se detiene, o si un servidor virtual se queda detenido mucho tiempo y luego se reanuda, la diferencia llega a cientos de ms o varios segundos. - En el gráfico: Subida gradual (Desfase (offset) del reloj por servidor) - Dónde mirar: Reunir y comparar, servidor por servidor, los campos de chronyc tracking System time (diferencia entre el reloj del sistema y el reloj NTP), Last offset y Ref time (momento en que se aplicó por última vez una medición de la fuente horaria) - Se confirma si: El offset del servidor problemático se aleja cientos de ms o más del de los demás, o su Ref time se quedó parado hace tiempo, y los desajustes solo aparecen en los traslados desde o hacia ese servidor - Se descarta si: Si todos los servidores están a pocos ms, apunta al cálculo del tiempo en el juego o a “Error de sincronización del reloj” en el cliente - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Los saltos bruscos hacia delante o hacia atrás del reloj de un solo servidor se tratan en “Salto del reloj del sistema (step de NTP)”, en la capa del SO del servidor. - Fuentes: - [RFC 5905: Network Time Protocol Version 4: Protocol and Algorithms Specification](https://www.rfc-editor.org/rfc/rfc5905) · IETF · En una LAN rápida, un cliente NTP suele mantenerse dentro de unos cientos de µs - [chrony – Frequently Asked Questions](https://chrony-project.org/faq.html) · chrony · La deriva (drift) del reloj de una computadora normal es menor de 100 ppm, pero en una máquina virtual puede ser mayor; una máquina virtual suspendida y reanudada puede quedar con la hora desfasada y necesitar una corrección por salto (step) - [clock_gettime(2) — Linux manual page](https://man7.org/linux/man-pages/man2/clock_gettime.2.html) · Linux man-pages · CLOCK_REALTIME puede saltar de forma discontinua por cambios manuales o correcciones de NTP; CLOCK_MONOTONIC no se ve afectado por esos saltos - [chronyc(1)](https://chrony-project.org/doc/4.6/chronyc.html) · chrony · En chronyc tracking: System time (diferencia entre el reloj NTP y el reloj del sistema), Last offset (offset estimado en la última corrección), Ref time (momento en que se aplicó la última medición de la fuente horaria) #### in-bots · Exceso de macros y bots · Bots and macros Los bots envían solicitudes con mucha más frecuencia que una persona y acaparan la capacidad de procesamiento del servidor. - Por qué → Efecto → En pantalla: Se conectan en masa bots que repiten sin descanso la caza, los desplazamientos o los intercambios → Aumentan la carga de procesamiento del servidor y la de la BD → Una zona de caza concreta o todo el servidor se vuelve lento (cámara lenta, input lag) - Síntomas: Cámara lenta, Input lag / Factores: Detención - A quién: Todo el servidor, Una zona o un canal / Cuándo: Siempre, Horas pico de la noche - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Detectar bots, limitar la frecuencia de solicitudes por cuenta y por personaje. - Tareas (Equipo de infraestructura): Limitar la frecuencia de conexiones y solicitudes por IP (con margen, porque en cibercafés y redes móviles varias personas comparten una IP), bloquear los rangos de bots con el firewall o el WAF. - En el gráfico: Alto solo en algunos (Solicitudes por segundo por cuenta/IP) - Dónde mirar: Con los logs del servidor del juego, distribución de solicitudes por segundo por cuenta y por personaje, y la lista de los que más envían. Sin métricas en el código, solicitudes por IP en el firewall o el WAF - Se confirma si: Unas pocas cuentas o IP envían solicitudes sin parar a una frecuencia imposible para una persona, y al limitarlas la carga del servidor baja de forma visible - Se descarta si: Si las solicitudes se reparten de forma pareja entre las cuentas, apunta a un aumento normal de jugadores (“Tick que excede su presupuesto”, “Retraso del autoescalado”) - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Using rate-based rule statements in AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based.html) · AWS · Contar las solicitudes según un criterio (IP, etc.) y limitar la velocidad si hay demasiadas dentro de una ventana de tiempo fija - [RFC 6269: Issues with IP Address Sharing](https://www.rfc-editor.org/rfc/rfc6269) · IETF · Cuando varios abonados comparten una IP, los bloqueos y límites por IP afectan también a otros usuarios #### in-external · Dependencia de servicios externos · External dependencies (auth, billing, platform) Si un servicio externo, como el login de la plataforma, los pagos o la verificación de identidad, va lento o se detiene, todo se bloquea en ese paso. - Por qué → Efecto → En pantalla: Fallo o lentitud de un servicio externo de autenticación o de pagos → Ese paso se queda esperando respuesta → No se puede iniciar sesión, los pagos fallan. Quienes ya están jugando siguen bien - Síntomas: No conecta / carga infinita, Acción perdida / rollback / Factores: Detención - A quién: Todo el servidor, Solo una función / Cuándo: Al conectar o tras un mantenimiento, Al hacer ciertas acciones - Responsable principal: Externo (Externo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Poner timeout a las llamadas externas y mostrar un mensaje claro, cachear el resultado de la autenticación, tener un procedimiento de reintento y compensación para los pagos. - Tareas (Externo): Pedir a los proveedores de autenticación, pagos o plataforma que confirmen el fallo y lo resuelvan, indicar a los jugadores que el fallo está en un servicio externo. - En el gráfico: Salto en escalón (Tiempo de respuesta y tasa de errores de las llamadas externas, inicios de sesión exitosos) - Dónde mirar: Tiempo de respuesta, tasa de errores y timeouts de cada llamada externa (login de la plataforma, pagos, verificación de identidad) y página de estado del proveedor - Se confirma si: Desde la hora en que se acumulan los fallos de inicio de sesión o de pago, solo los errores y timeouts de una llamada externa concreta suben un escalón y se quedan altos, y la página de estado del proveedor muestra un incidente a la misma hora - Se descarta si: Si las llamadas externas van bien y aun así no se puede iniciar sesión, apunta al propio servidor de login (“Agotamiento del pool de hilos”, BD) o a la cola de conexiones pendientes (backlog) del sistema operativo - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Casos reales: fastly-2021, aws-2021, aws-2025 - Fuentes: - [Timeouts, retries, and backoff with jitter](https://d1.awsstatic.com/builderslibrary/pdfs/timeouts-retries-and-backoff-with-jitter.pdf) · AWS · Amazon Builders' Library. Mientras se espera la respuesta se retienen recursos como hilos y conexiones, así que hay que poner timeouts, y las API con efectos secundarios solo se reintentan si su idempotencia está garantizada - [Circuit Breaker Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) · Microsoft Azure · Las llamadas con alta probabilidad de fallar se rechazan de inmediato, sin esperar al timeout, para mantener el tiempo de respuesta - [REL05-BP01 Implement graceful degradation to transform applicable hard dependencies into soft dependencies](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_mitigate_interaction_failure_graceful_degradation.html) · AWS · AWS Well-Architected. Aunque falle un servicio del que se depende, mantener las funciones esenciales aunque sea con datos algo antiguos (base para cachear el resultado de la autenticación) #### in-region-match · Errores de matchmaking y asignación de región · Wrong region assignment (matchmaking / GeoDNS) Si a un jugador se le asigna un servidor de una región lejana cuando hay una cercana, tiene siempre el ping alto aunque su conexión esté bien. - Por qué → Efecto → En pantalla: Datos de GeoIP erróneos, VPN, asignación de todo el grupo según el ping medio de sus miembros, reglas que amplían la búsqueda a regiones lejanas cuando faltan jugadores, asignación según la ubicación del resolver DNS → Se conecta a un servidor de una región al otro lado del océano aunque haya una región cercana → En un juego con servidores en varias regiones, solo tú (o solo tu grupo) tienes siempre el ping alto, con input lag, rubber banding y habilidades que no salen - Síntomas: Input lag, Rubber banding, Acción perdida / rollback / Factores: Latencia - A quién: Solo yo, Una región o un ISP / Cuándo: Siempre, Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo), Infraestructura de red (Equipo de infraestructura), Externo (Externo) - Tareas (Equipo de desarrollo): Servidor: asignar según el ping por región que mide el cliente, sin depender de GeoIP; poner un tope de ping a las reglas que amplían la búsqueda a regiones lejanas; en los grupos, mirar además del promedio el ping del miembro que lo tiene más alto; registrar en el log la región asignada y el ping en ese momento. Cliente: medir por UDP el ping a cada región y enviarlo con la solicitud de matchmaking, mostrar en pantalla la región conectada y el ping, ofrecer la opción de elegir la región a mano. - Tareas (Equipo de infraestructura): Si la región se elige por DNS, comprobar que el DNS autoritativo admite EDNS Client Subnet (si el resolver que usa el jugador no lo envía, se asigna según la ubicación del resolver), actualizar con regularidad la base de datos de GeoIP, añadir el país y el ASN de GeoIP a los logs de conexión de los servidores de cada región para encontrar los países e ISP que acaban en regiones lejanas. - Tareas (Externo): Indicar a los jugadores que desactiven la VPN o el acelerador de juegos y vuelvan a conectarse, indicar a quienes usan el DNS de su empresa o un DNS extranjero que prueben con el DNS de su ISP, pedir al proveedor de GeoIP que corrija las ubicaciones erróneas. - Cifras de referencia: Si a un jugador de Seúl le toca la región de la costa oeste de EE. UU. y no la de Tokio, el ping pasa de unos 30 ms a unos 130 ms. GeoIP acierta el país en torno al 99.8% de las veces, pero a nivel de ciudad, incluso en EE. UU., solo alrededor del 66% de los casos cae dentro de un radio de 50 km, y con una VPN lo que aparece es la ubicación del servidor VPN. - En el gráfico: Alto solo en algunos (RTT (ping) por jugador, distribución de las regiones asignadas) - Dónde mirar: Añadir el país y el ASN de GeoIP a las IP de cliente de los registros de conexión de los servidores de cada región (logs de acceso del balanceador de carga, VPC Flow Logs) y contar a qué región se conectó cada país e ISP. Para un solo jugador, comparar la región a la que se conectó realmente con el ping medido hasta la región cercana (medido por el jugador, o con mtr desde un servidor de esa región hacia su IP) - Se confirma si: Los jugadores o países con RTT alto están conectados a una región lejana teniendo una cercana, y el ping medido hasta la región cercana es bajo - Se descarta si: Si se le asignó bien la región cercana y aun así el ping es alto, apunta a “Enrutamiento con rodeos” o a la conexión o el Wi-Fi de ese jugador - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Cuando la región se elige por DNS (DNS por geolocalización o por latencia), la ubicación se estima a partir de la dirección del resolver DNS que usa el jugador, sin ver la del propio jugador. Si el resolver no admite EDNS Client Subnet, que transmite parte de la dirección del jugador, a quienes usan el DNS de su empresa o un DNS lejano se les asigna según dónde está el resolver. Los sistemas de matchmaking también juzgan a veces a un grupo por el ping medio de sus miembros o, tras una espera larga, amplían el criterio de ping y lo asignan a una región lejana. En AWS GameLift Servers el criterio predeterminado para el ping del grupo también es el promedio, y su configuración de ejemplo amplía el tope de ping de 50 ms a 100 ms y luego a 200 ms. En un jugador con la VPN activada pueden sumarse la latencia añadida por el servidor intermedio (“Paso por una VPN o un acelerador de juegos”) y la asignación a una región lejana; para distinguirlas, se comprueba si la región asignada cambia al desactivar la VPN y volver a conectarse. El caso en que no hay ninguna región cercana y hay que conectarse a una lejana se trata en “Retardo de propagación (distancia física)”. - Fuentes: - [RFC 7871: Client Subnet in DNS Queries](https://www.rfc-editor.org/rfc/rfc7871) · IETF · Un DNS que responde distinto según la ubicación la estima a partir de la dirección del resolver que envía la consulta, y si el jugador usa un resolver centralizado lejos de él, la respuesta no es la adecuada. EDNS Client Subnet (función opcional) transmite parte de la dirección del jugador - [How Amazon Route 53 uses EDNS0 to estimate the location of a user](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-edns0.html) · AWS · Si el resolver no admite edns-client-subnet, la ubicación del jugador se estima por la dirección del resolver y se responde según dónde está el resolver (igual en el enrutamiento por geolocalización y por latencia) - [Geolocation accuracy](https://support.maxmind.com/knowledge-base/articles/maxmind-geolocation-accuracy) · MaxMind · País: alrededor del 99.8%; ciudad en EE. UU. (dentro de 50 km): alrededor del 66%; con VPN aparece la ubicación del servidor VPN y no la del usuario final; las IP de redes móviles se usan en zonas amplias y no permiten una ubicación precisa; la base de datos hay que actualizarla continuamente; se pueden pedir correcciones - [FlexMatch rule types](https://docs.aws.amazon.com/gameliftservers/latest/flexmatchguide/match-rules-reference-ruletype.html) · AWS · La regla de latencia (maxLatency) mira la latencia del jugador en cada ubicación; para los grupos usa por defecto el promedio de sus miembros (partyAggregation avg); la cola también puede colocar partidas en regiones que no cumplen la regla de latencia - [Create a player latency policy](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/queues-design-latency.html) · AWS · Coloca la partida en la ubicación con la latencia media más baja de todos los jugadores, pero también se colocan jugadores con latencias extremas; ejemplo de política que amplía el tope de ping de 50 ms a 100 ms y luego a 200 ms - [Amazon GameLift Servers UDP ping beacons](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/reference-udp-ping-beacons.html) · AWS · El cliente del juego mide la latencia con los endpoints UDP que hay en cada ubicación de hosting y la usa para la colocación y el matchmaking; se parece más al tráfico real del juego que un ping ICMP - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Mediana de ida y vuelta medida desde Seúl (Korea Central): Tokio (Japan East) 29 ms, costa oeste de EE. UU. 124–136 ms - [Flow log records](https://docs.aws.amazon.com/vpc/latest/userguide/flow-log-records.html) · AWS · srcaddr de un registro de VPC Flow Logs: en el tráfico entrante, dirección IP del emisor #### in-cert · Certificado TLS expirado o mal configurado · TLS certificate expiry / misconfiguration Si el certificado de un servidor de login, de API o de parches expira o le falta el certificado intermedio, desde ese momento falla la conexión TLS de los clientes que abren una conexión nueva. - Por qué → Efecto → En pantalla: El certificado está fuera de su periodo de validez, el servidor lo envía sin el certificado intermedio, o la fecha y hora del dispositivo del jugador están mal → El cliente no puede validar el certificado y corta la conexión TLS → El juego no conecta o se queda en carga infinita en el login o la descarga de parches, fallan solo las funciones HTTPS como la tienda. Quienes ya estaban conectados suelen seguir bien - Síntomas: No conecta / carga infinita, Acción perdida / rollback / Factores: Detención - A quién: Todo el servidor, Solo una función, Solo yo / Cuándo: Al conectar o tras un mantenimiento, Al hacer ciertas acciones - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Registrar los errores de certificado con un código distinto del de otros fallos de conexión y mostrar un aviso; si el error es de fecha, indicar que se active el ajuste automático de fecha y hora del dispositivo; si se usa fijación de certificados (pinning), incluir también claves de respaldo y coordinar con el equipo de infraestructura el calendario de cambio de certificados. - Tareas (Equipo de infraestructura): Red: si TLS termina en el balanceador de carga o la CDN, poner alertas sobre el estado de la renovación automática de los certificados gestionados y los días que quedan (DaysToExpiry en ACM), mantener los registros DNS de validación. Servidores/SO: si TLS termina en el servidor, automatizar la renovación y recargar la configuración después, configurar la cadena incluyendo el certificado intermedio, comprobar periódicamente desde fuera la validez restante de cada dirección de login, API y parches, y poner alertas. - Cifras de referencia: Los certificados de Let’s Encrypt duran 90 días y se recomienda renovarlos cada 60, y AWS Certificate Manager comprueba los certificados validados por DNS 45 días antes de que expiren y los renueva automáticamente. Si la renovación automática falla en silencio, las conexiones nuevas se bloquean todas a la vez justo a la hora de la expiración. - En el gráfico: Desconexión masiva (Inicios de sesión exitosos, errores de handshake TLS) - Dónde mirar: Ver con openssl s_client -connect HOST:443 -showcerts la lista de certificados que envía realmente el servidor y comprobar la fecha de expiración (notAfter) de cada uno con openssl x509 -noout -enddate. Si TLS termina en el balanceador de carga, errores de negociación TLS (ClientTLSNegotiationErrorCount en AWS ALB y NLB) e inicios de sesión exitosos - Se confirma si: La fecha de expiración ya pasó o falta el certificado intermedio en la lista que envía el servidor, y los errores empiezan a subir a la hora en que expiró o se cambió el certificado - Se descarta si: Si la lista de certificados y la fecha de expiración están bien pero solo fallan algunos jugadores, revisar la fecha y hora de sus dispositivos o la lista de certificados raíz de un SO antiguo - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Una configuración a la que le falta el certificado intermedio puede parecer correcta al abrirla en un navegador de PC. El navegador recuerda certificados intermedios que obtuvo en otros sitios y completa el hueco, pero los clientes sin esa memoria, como las apps de Android, fallan. Además, la validez se está acortando. Let’s Encrypt prevé reducir la validez predeterminada a 64 días en 2027 y a 45 días en 2028, así que una configuración fija de renovar cada 60 días solo deja cuatro días de margen con certificados de 64 días, y con los de 45 días se pasa de la fecha de expiración. AWS Certificate Manager tampoco renueva automáticamente los certificados importados, y si se borran los registros DNS de validación la renovación falla. El bloqueo del login se parece al de “Fallos y lentitud del DNS”, pero un problema de certificado falla en el handshake TLS, después de encontrar la dirección del servidor, y empieza a la misma hora en que expiró o se cambió el certificado. - Fuentes: - [RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile](https://www.rfc-editor.org/rfc/rfc5280) · IETF · La validez de un certificado va de notBefore a notAfter; la validación de la ruta comprueba, para cada certificado de la cadena, que la hora actual está dentro de su validez (si el reloj de quien valida está mal, falla) - [FAQ](https://letsencrypt.org/docs/faq/) · Let's Encrypt · Validez predeterminada del certificado: 90 días; se recomienda renovar cada 60 días - [Decreasing Certificate Lifetimes to 45 Days](https://letsencrypt.org/2025/12/02/from-90-to-45) · Let's Encrypt · La validez predeterminada se reduce a 64 días desde febrero de 2027 y a 45 días desde febrero de 2028; renovar a intervalos fijos de 60 días deja de bastar y se recomienda renovar hacia los dos tercios de la validez - [Renewal for domains validated by DNS](https://docs.aws.amazon.com/acm/latest/userguide/dns-renewal-validation.html) · AWS · 45 días antes de la expiración comprueba si el certificado está en uso en un servicio de AWS y si existe el registro CNAME de validación, y lo renueva automáticamente; si no puede validarlo, avisa 30, 15, 7, 3 y 1 días antes de la expiración - [Managed certificate renewal in AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/managed-renewal.html) · AWS · Los certificados importados y los ya expirados no se renuevan automáticamente - [Supported CloudWatch metrics](https://docs.aws.amazon.com/acm/latest/userguide/cloudwatch-metrics.html) · AWS · DaysToExpiry: días que faltan para que expire el certificado; se publica dos veces al día hasta la expiración - [Security with network protocols](https://developer.android.com/privacy-and-security/security-ssl) · Android (Google) · Si el servidor envía la cadena sin el certificado intermedio, las apps de Android fallan con SSLHandshakeException, pero un navegador de PC puede completarla con certificados intermedios ya obtenidos y no dar error; la cadena que envía el servidor se comprueba con openssl s_client - [Network security configuration](https://developer.android.com/privacy-and-security/security-config) · Android (Google) · Con fijación de certificados (pinning) hay que incluir claves de respaldo para prepararse ante cambios de clave o de CA; si no, las conexiones se cortan hasta que se actualiza la app - [openssl-s_client](https://docs.openssl.org/3.0/man1/openssl-s_client/) · OpenSSL · -showcerts: muestra la lista de certificados que envió el servidor, en el orden en que los envió (no es la cadena validada) - [openssl-x509](https://docs.openssl.org/3.0/man1/openssl-x509/) · OpenSSL · -enddate: muestra la fecha de expiración del certificado (notAfter); -checkend: comprueba si expira dentro de los segundos indicados - [CloudWatch metrics for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html) · AWS · ClientTLSNegotiationErrorCount: número de conexiones que no pudieron establecer una sesión TLS, por ejemplo porque el cliente no pudo validar el certificado del servidor y cortó la conexión - [CloudWatch metrics for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html) · AWS · ClientTLSNegotiationErrorCount: número de handshakes TLS en los que falló la negociación entre el cliente y el listener TLS #### in-login-queue · Tope de la cola de inicio de sesión y periodo de gracia para reconectar demasiado corto · Login queue cap / no reconnect grace Cuando la gente entra en masa justo después de un lanzamiento o un mantenimiento, la cola de inicio de sesión llega a su tope y rechaza nuevas entradas, y quien estaba esperando pierde su lugar si se desconecta un momento y vuelve al final de la cola. - Por qué → Efecto → En pantalla: Hay más gente intentando entrar de la que el servidor de login puede aceptar a la vez, así que se usa una cola, y si se alarga demasiado se rechazan nuevas entradas para proteger el servidor → Cuanto más larga es la cola, más dura la espera, y mientras tanto basta un corte breve del Wi-Fi o de la red móvil para perder el lugar → El juego no conecta o se queda en carga infinita, se cierra con un error durante la espera y hay que volver a esperar desde el final - Síntomas: No conecta / carga infinita, Desconexión / Factores: Detención - A quién: Todo el servidor, Solo yo / Cuándo: Al conectar o tras un mantenimiento, Horas pico de la noche - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo), Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Servidor: ajustar el tope de la cola a lo que el servidor de login puede procesar de verdad, guardar durante un tiempo el lugar de quien se desconecta mientras espera (periodo de gracia para reconectar), mostrar la posición y el tiempo de espera estimado, registrar como métricas la longitud de la cola, los rechazos y las desconexiones durante la espera. Cliente: si se corta durante la espera, reconectar automáticamente al mismo lugar sin cerrar el juego, y espaciar los reintentos con backoff exponencial y jitter. - Tareas (Equipo de infraestructura): Servidores/SO: medir antes del lanzamiento, con pruebas de carga, el límite de procesamiento de los servidores de login y de lobby, tener servidores de reserva listos para añadirlos en el lanzamiento, ver las métricas de la cola en el mismo gráfico que los intentos de conexión. - Cifras de referencia: En el lanzamiento de una expansión de FINAL FANTASY XIV en 2021, se rechazaban nuevas entradas cuando la cola de un centro de datos lógico superaba las 17,000 personas (Error 2002). Si la conexión se cortaba durante la espera, el servidor de lobby esperaba entre unas decenas de segundos y 1 minuto, y si el jugador volvía a conectarse en ese tiempo, seguía desde su posición en la cola. - En el gráfico: Topa con el límite (Longitud de la cola de inicio de sesión, rechazos por tope alcanzado, desconexiones durante la espera) - Dónde mirar: Poner en el mismo gráfico que los intentos de conexión la longitud de la cola, el tiempo medio de espera, los rechazos por tope alcanzado y las desconexiones durante la espera que registran los servidores de login y de lobby - Se confirma si: Justo después del lanzamiento o del mantenimiento, mientras la longitud de la cola se queda plana en el tope, suben los rechazos, y las desconexiones durante la espera se concentran en jugadores con Wi-Fi o red móvil - Se descarta si: Si la cola es corta y aun así el login va lento, apunta a la BD (db-login-storm) o a la cola de conexiones pendientes del sistema operativo (so-backlog) - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Cuando la avalancha de inicios de sesión vuelve lenta la BD, el caso se trata en “Avalancha de inicios de sesión y consultas N+1”, y cuando se desborda la cola de conexiones pendientes del sistema operativo, en “Desbordamiento de la cola de conexiones pendientes (backlog)”. Esta entrada trata del diseño de la cola de inicio de sesión que el juego pone a propósito. El tope de la cola es una protección del servidor de login y no se puede quitar: rechazar pronto las solicitudes que sobran es lo que permite seguir procesando las que sí se pueden atender. Lo importante es reducir el perjuicio que los rechazos y las desconexiones causan al jugador, y cuanto más larga es la cola, más se concentran los errores en jugadores con conexiones inestables, como el Wi-Fi o la red móvil. - Casos reales: ffxiv-2021 - Fuentes: - [Response to Congestion (as of Dec. 11)](https://na.finalfantasyxiv.com/lodestone/news/detail/6a94b30182b6d963994fdc0b789264ac9f24986f) · Square Enix · Si la cola de un centro de datos lógico supera las 17,000 personas, se rechazan nuevas entradas para que el servidor de login no se caiga (Error 2002); si la conexión se corta durante la espera, el servidor de lobby espera entre unas decenas de segundos y 1 minuto: si el jugador vuelve en ese tiempo sigue desde su posición, y si no, vuelve al final - [Using load shedding to avoid overload](https://aws.amazon.com/builders-library/using-load-shedding-to-avoid-overload/) · Amazon Builders' Library · Limitación de carga (load shedding): rechazar pronto las solicitudes que sobran para seguir procesando las que se pueden atender ### Diseño del netcode (causas: 16) #### sy-request-response · Feedback solo tras la respuesta del servidor (solicitud-respuesta) · Request-response (no client-side feedback) Al presionar un botón no hay animación ni sonido hasta que llega la respuesta del servidor. El ping se convierte directamente en el tiempo de respuesta. - Por qué → Efecto → En pantalla: Las habilidades, el movimiento y la recogida de objetos se reproducen solo cuando llega la confirmación del servidor → Desde que se presiona, no hay ninguna respuesta durante el tiempo de ida y vuelta + la espera del tick → Con 150 ms de ping, todas las acciones responden 0.2 s tarde - Síntomas: Input lag / Factores: Latencia - A quién: Solo yo / Cuándo: Siempre, Al hacer ciertas acciones - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: empezar las animaciones, los sonidos y los efectos en cuanto se presiona (feedback anticipado) y mostrar solo los resultados (daño, recompensas) tras la confirmación del servidor, aplicar al instante el movimiento y el ataque básico con predicción, y al recibir una corrección de posición del servidor, volver a aplicar desde esa posición los inputs que aún no se han confirmado. Servidor: calcular el movimiento a partir de los inputs recibidos y enviar una corrección solo cuando la diferencia con la posición que predijo el cliente supere un umbral. - Cifras de referencia: Tiempo de respuesta ≈ ping + la mitad del intervalo de tick + un frame. Con 20 ticks y 150 ms de ping, unos 190 ms. - En el gráfico: Siempre alto (Tiempo desde el input hasta el inicio del feedback, RTT (ping)) - Dónde mirar: Registrar en el log del cliente de una build de desarrollo la hora del input, la hora de inicio de la primera animación o sonido y la hora de llegada de la respuesta del servidor, y verlas junto al RTT del juego. Medir variando el ping con la emulación de red del motor (Unreal NetEmulation.PktLag) o añadiendo latencia con tc netem de Linux en un servidor de pruebas - Se confirma si: El feedback empieza siempre en el mismo instante en que llega la respuesta del servidor, el tiempo del input al feedback equivale al RTT + la espera del tick, y crece exactamente lo que se añade de latencia - Se descarta si: Si el feedback empieza en cuanto se presiona y solo llegan tarde resultados como los números de daño, es el diseño normal. Si incluso con ping bajo el retraso supera el intervalo de tick, apunta a “Doble espera de tick” o a un problema de frames en el cliente - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: En juegos que no necesitan respuestas rápidas, como los de turnos, los de cartas o los idle, este modelo es el más simple y seguro. El problema aparece cuando en un juego con control en tiempo real también se hacen así el movimiento o el ataque básico. - Fuentes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Un cliente que solo espera el resultado del servidor muestra cada acción 500 ms tarde si la latencia es de 500 ms. Se resuelve con predicción en el cliente y reconciliación con el servidor - [Using Gameplay Abilities in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-gameplay-abilities-in-unreal-engine) · Epic Games · Local Predicted se ejecuta en cuanto se presiona y el servidor decide al final; Server Initiated no tiene predicción, así que quien la usa percibe la latencia - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · El cliente predice y guarda los movimientos, y solo se corrige cuando el error respecto al servidor supera el margen permitido (MAXPOSITIONERRORSQUARED); tras la corrección, vuelve a aplicar los movimientos guardados - [Using Network Emulation in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-network-emulation-in-unreal-engine) · Epic Games · Pruebas con latencia mínima y máxima y porcentaje de pérdida de paquetes en el servidor y el cliente; en la consola se configura con comandos como NetEmulation.PktLag - [tc-netem(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-netem.8.html) · iproute2 · Herramienta de pruebas que imita una red real añadiendo latencia y jitter (delay TIME JITTER) y pérdida (loss random PERCENT) a los paquetes salientes #### sy-chatty · Protocolo con muchas idas y vueltas secuenciales (chatty) · Chatty protocol / sequential round trips Si una sola acción necesita varias idas y vueltas al servidor en secuencia, el ping se multiplica por ese número. - Por qué → Efecto → En pantalla: Abrir la tienda → pedir la lista → consultar el precio → comprar → actualizar el inventario, cada paso como una solicitud aparte → La siguiente solicitud solo se envía tras recibir la respuesta de la anterior → Con 150 ms de ping, una compra tarda casi 1 segundo. Las cargas son inusualmente largas - Síntomas: Input lag, No conecta / carga infinita / Factores: Latencia - A quién: Solo una función, Solo yo / Cuándo: Al hacer ciertas acciones, Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: cambiar el protocolo para agrupar varios pasos en una sola solicitud y respuesta (p. ej., incluir el inventario actualizado en la respuesta de la compra). Cliente: descargar de antemano los datos necesarios, usar una interfaz que no espere el resultado. - Cifras de referencia: Tiempo total ≈ número de idas y vueltas × (ping + procesamiento del servidor + espera del tick). Con 5 idas y vueltas y 150 ms de ping, unos 0.85–1 s. - En el gráfico: Siempre alto (Tiempo de finalización por función, idas y vueltas por acción) - Dónde mirar: En una captura de paquetes del lado del servidor (Wireshark), contar cuántas veces se alternan solicitudes y respuestas, y con qué intervalo, mientras una cuenta de prueba hace una sola acción, como una compra en la tienda o el inicio de sesión. Si hay logs de solicitudes del servidor, agruparlos por ID de sesión y ver el número de solicitudes y la hora de llegada y de respuesta de cada una - Se confirma si: Una sola acción provoca varias idas y vueltas sucesivas en las que cada solicitud espera la respuesta anterior, el tiempo de finalización es aproximadamente idas y vueltas × RTT, y la misma función va proporcionalmente más lenta para los jugadores de regiones con ping alto - Se descarta si: Si hay solo una o dos idas y vueltas pero una respuesta tarda mucho, la causa está en el procesamiento del servidor o en la BD. Si todos los jugadores van igual de lentos sin importar el ping, revisar la carga del servidor - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Chatty I/O antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/chatty-io/) · Microsoft Azure · Muchas solicitudes de E/S pequeñas acumulan latencia y empeoran mucho la capacidad de respuesta. Se recomienda agruparlas en menos solicitudes y más grandes #### sy-no-queue · Sin búfer de inputs para habilidades · No input/spell queue Si no se puede presionar la siguiente habilidad hasta que el servidor confirme que terminó la anterior, cada combo arrastra un tiempo de ida y vuelta. - Por qué → Efecto → En pantalla: El input de la siguiente habilidad solo se acepta “después de confirmarse la anterior” → Entre una habilidad y la siguiente queda un hueco del tamaño del ping → Aparecen huecos en cada combo, y cuanto más ping, menos DPS - Síntomas: Input lag, Acción perdida / rollback / Factores: Latencia - A quién: Solo yo, Solo una función / Cuándo: Al hacer ciertas acciones - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: añadir un margen de búfer de inputs que acepte también los inputs hechos cierto tiempo antes de que termine el cooldown (p. ej., 0.3–0.4 s) y los envíe de inmediato al servidor. Servidor: no rechazar los inputs que llegan un poco antes y ejecutarlos en el instante en que termina el cooldown. - Cifras de referencia: En un combo de habilidades con cooldown de 1 segundo, con 150 ms de ping queda un hueco de 0.15 s o más entre cada una, y el número de habilidades usadas en el mismo tiempo baja más de un 13%. - En el gráfico: Siempre alto (Hueco entre habilidades, RTT (ping)) - Dónde mirar: Registrar en el log del servidor, por personaje, la hora en que terminó el cooldown, la hora en que llegó la solicitud de la siguiente habilidad y la hora en que se ejecutó, y comparar el hueco con el RTT del jugador - Se confirma si: Entre el fin del cooldown y la ejecución de la siguiente habilidad siempre queda un hueco de aproximadamente el RTT, y cuanto más ping tiene el jugador, más largo es el hueco y menos habilidades usa en el mismo tiempo - Se descarta si: Si el hueco es constante sin importar el ping, es una cuestión de diseño (cooldown global o duración de las animaciones). Si el hueco solo se dispara de vez en cuando, revisar jitter, pérdida de paquetes o “Tick que excede su presupuesto” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Por ejemplo, World of Warcraft tiene un margen de búfer de inputs que el jugador puede ajustar en la configuración. Si el margen es mayor que el tiempo de ida y vuelta, el ping casi no se nota entre las habilidades del combo. - Fuentes: - [Latency and Player Actions in Online Games (Communications of the ACM, 2006)](https://web.cs.wpi.edu/~claypool/papers/precision-deadline/final.pdf) · ACM · En EverQuest 2, cuanto más sube la latencia, menos daño hace el personaje y más dura el combate (de 0 a 500 ms, unos 5 segundos más en un combate de unos 2 minutos) #### sy-short-window · Ventanas de tiempo cortas que el ping consume · Timing window too short for latency + reaction Si el tiempo para reaccionar es corto, como en las esquivas, los parries o los bloqueos, el ping consume ese margen y aparecen ataques imposibles de evitar. - Por qué → Efecto → En pantalla: Ventanas de tiempo cortas, como un aviso de ataque del jefe de 0.5 s o una ventana de parry de 0.2 s → El aviso se ve tarde (latencia servidor → cliente + interpolación) y tu input también llega tarde (latencia cliente → servidor + espera del tick) → Esquivaste a tiempo y aun así te golpea, el parry no sale - Síntomas: Acción perdida / rollback, Input lag / Factores: Latencia - A quién: Solo yo, Solo una función / Cuándo: Al hacer ciertas acciones - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo), Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Servidor: programar el aviso del ataque en hora del servidor y enviarlo por adelantado, ampliar la ventana de tiempo según el ping (compensación de lag). Cliente: reproducir el aviso recibido a la hora del servidor programada. - Tareas (Equipo de infraestructura): Poner servidores cerca de las regiones con muchos jugadores (servidores regionales) para reducir el propio ping. - Cifras de referencia: Con 150 ms de ping y 100 ms de interpolación, el aviso tarda unos 0.18 s en aparecer en tu pantalla y tu input unos 0.1 s en llegar al servidor. Si se suman los 0.25 s de reacción humana, un aviso de 0.5 s es casi imposible. - En el gráfico: Alto solo en algunos (Tasa de fallos de esquivas y parries (por rango de ping)) - Dónde mirar: Registrar en el log del servidor la hora de inicio y de fin de la ventana de tiempo, la hora de llegada del input del jugador al servidor y el RTT de ese jugador, y ver la tasa de fallos por rangos de ping (p. ej., de 50 en 50 ms) - Se confirma si: Cuanto más alto es el rango de ping, más alta es claramente la tasa de fallos, y los inputs fallidos llegan poco después de cerrarse la ventana (dentro del RTT más el tiempo de interpolación) - Se descarta si: Si la tasa de fallos es parecida en todos los rangos de ping, es la dificultad del patrón. Si el input llegó dentro de la ventana y aun así cuenta como fallo, revisar el código de registro de impactos o la validación del servidor - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Factors influencing the latency of simple reaction time (Frontiers in Human Neuroscience, 2015)](https://doi.org/10.3389/fnhum.2015.00131) · Frontiers · Tiempo de reacción simple medio: unos 231 ms (213 ms corrigiendo la latencia de los dispositivos); los grandes estudios recientes dan 233–400 ms - [Latency and Player Actions in Online Games (Communications of the ACM, 2006)](https://web.cs.wpi.edu/~claypool/papers/precision-deadline/final.pdf) · ACM · Cuanto más precisa es una acción y más corto su plazo, más sensible es a la latencia (límites: unos 100 ms en primera persona, unos 500 ms en tercera persona, unos 1,000 ms con vista omnisciente) - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Método para programar eventos según la hora del servidor (ServerTime) para que todos los clientes los reproduzcan en el mismo instante #### sy-no-lagcomp · Registro de impactos sin compensación de lag · Server-now hit validation Si el servidor resuelve los impactos solo con “la posición actual en el servidor”, lo que viste en tu pantalla y el resultado no coinciden. - Por qué → Efecto → En pantalla: En tu pantalla, el rival está en su posición de hace unos 0.2 s (con 150 ms de ping y 100 ms de interpolación) → El servidor resuelve con la posición actual, y el rival ya no está donde apuntaste → En tu pantalla le diste, pero cuenta como fallo. Hay que disparar por delante de los objetivos en movimiento - Síntomas: Acción perdida / rollback / Factores: Latencia - A quién: Solo yo / Cuándo: Al hacer ciertas acciones - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: rebobinar hasta el momento que veía el atacante y resolver ahí (compensación de lag), o cambiar a un sistema de selección de objetivo. Cliente: enviar con cada ataque el momento que estaba viendo (la hora del servidor que se está interpolando). - En el gráfico: Alto solo en algunos (Tasa de acierto contra objetivos en movimiento (por rango de ping)) - Dónde mirar: Registrar juntos en el log de resolución del servidor la hora del ataque, la posición del objetivo en la pantalla del atacante (valor enviado por el cliente), la posición del objetivo en el servidor usada para resolver y el RTT del atacante. En una build de desarrollo se ve de inmediato si se dibuja sobre la pantalla del cliente la posición que usó el servidor - Se confirma si: En los fallos, la diferencia entre las dos posiciones es aproximadamente la velocidad del objetivo × (RTT del atacante + tiempo de interpolación), y cuanto más ping, más baja solo la tasa de acierto contra objetivos en movimiento - Se descarta si: Si también se falla contra objetivos quietos, es un problema de hitboxes o de detección de colisiones. Si hay desajuste incluso con rebobinado, revisar si el cliente informa mal al servidor de su tiempo de interpolación - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Sin compensación de lag hay que disparar por delante, tanto como la latencia. Con compensación de lag, el servidor rebobina la latencia más el tiempo de interpolación para resolver - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · El servidor rebobina hasta el estado del juego que veía el jugador al disparar para resolver el impacto; el cliente envía también la hora de simulación que estaba viendo - [Source SDK 2013: player_lagcompensation.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player_lagcompensation.cpp) · Valve · Tiempo que rebobina el motor Source = latencia de red + tiempo de interpolación #### sy-lagcomp-overreach · Compensación de lag excesiva · Excessive lag compensation Si se rebobina demasiado a favor del atacante, a quien recibe el disparo le dan aunque ya se haya escondido. - Por qué → Efecto → En pantalla: El servidor rebobina mucho para favorecer a un atacante con ping alto → En la pantalla de quien recibe el disparo, ya estaba a cubierto → “Me dieron detrás de una pared”, ventaja para quien tiene ping alto - Síntomas: Acción perdida / rollback / Factores: Latencia - A quién: Solo yo, Una región o un ISP / Cuándo: Al hacer ciertas acciones - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Poner un tope de rebobinado (p. ej., 200–250 ms) y, para atacantes con más ping, rebobinar solo hasta ese límite y dejar que compensen el resto disparando por delante. - En el gráfico: Alto solo en algunos (Tiempo rebobinado por impacto (por ping del atacante)) - Dónde mirar: Registrar en el log de resolución del servidor, para cada impacto, el tiempo rebobinado, el RTT del atacante y la hora del servidor en que la víctima se puso a cubierto. En una build de desarrollo, dibujar en pantalla las hitboxes rebobinadas (sv_showlagcompensation en el motor Source) - Se confirma si: Los impactos de los reportes “me dieron detrás de una pared” se concentran en atacantes con tiempos de rebobinado largos, y el tiempo rebobinado crece sin tope con el ping del atacante - Se descarta si: Si los impactos detrás de paredes también ocurren con rebobinados cortos, es un problema de hitboxes o de detección de colisiones. Si la víctima tiene ping alto, ocurrió porque su movimiento llegó tarde al servidor - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: El rebobinado da prioridad “a quien dispara”. También se ha propuesto una excepción “a favor de quien recibe”: no rebobinar si en su propia pantalla ya había llegado a un lugar seguro. - Fuentes: - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Sin límite de rebobinado, alguien con 500 ms de latencia podría acertar 0.5 s después de que el rival se pusiera a cubierto; por eso se pone un límite - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · Fenómeno de “recibir el impacto ya detrás de la esquina” (shot around the corner), límites de rebobinado en FPS comerciales, propuesta de una técnica que no rebobina si la víctima está a salvo - [Source SDK 2013: player_lagcompensation.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player_lagcompensation.cpp) · Valve · En el motor Source, el tope de rebobinado sv_maxunlag vale 1 segundo por defecto (máximo 1 segundo); sv_showlagcompensation muestra en pantalla las hitboxes rebobinadas #### sy-client-auth · Autoridad del cliente · Client-authoritative results Si cada cliente decide sus propios resultados, en tu pantalla todo va fluido, pero los resultados no coinciden con los de otras pantallas y el juego queda expuesto a las trampas. - Por qué → Efecto → En pantalla: El cliente decide la posición y los impactos, y el servidor solo los reenvía → Dos jugadores afirman haber acertado primero y el servidor no puede comprobarlo → El rival se teletransporta o atraviesa paredes, “yo le di y no cuenta” - Síntomas: Teletransporte, Acción perdida / rollback / Factores: Latencia - A quién: Todo el servidor / Cuándo: Siempre - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: validar él mismo los resultados importantes (impactos, etc.), comprobar velocidad y distancia en el movimiento. Cliente: al recibir un resultado rechazado o corregido por el servidor, volver a ese valor. - En el gráfico: Siempre alto (Velocidades de movimiento imposibles, reportes de impacto contradictorios) - Dónde mirar: Registrar en el servidor tal cual las posiciones e impactos que reportan los clientes, calcular la velocidad de movimiento con reportes de posición consecutivos y contar los reportes que superan la velocidad máxima y los casos en que dos jugadores dicen haber acertado primero - Se confirma si: El servidor reenvía los reportes a los demás clientes sin validarlos, y aparecen de forma constante velocidades imposibles o impactos contradictorios, sin relación con parches ni regiones - Se descarta si: Si el servidor calcula o valida los resultados, no es esta causa. En ese caso, para el teletransporte revisar la pérdida de paquetes o el búfer de interpolación - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Que el cliente reporte los resultados solo es viable si se puede confiar en el cliente. Por el riesgo de trampas se usa un servidor autoritativo - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Modelo de autoridad del servidor: el servidor nunca se fía del estado del juego que vio el cliente - [Distributed authority topologies (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/distributed-authority.html) · Unity · Repartir la autoridad entre los clientes facilita las trampas y elimina la simulación única que gobierna todas las entidades #### sy-lockstep · Espera al jugador más lento en lockstep · Lockstep waits for the slowest peer En una arquitectura en la que todos calculan juntos el mismo turno, si el input de uno llega tarde, todos esperan. - Por qué → Efecto → En pantalla: Cada turno solo se puede calcular cuando han llegado los inputs de todos los jugadores → El input de un jugador llega tarde por jitter o pérdida de paquetes → Todos sufren un tirón a la vez y, en casos graves, aparece la ventana “Esperando a los jugadores” - Síntomas: Congelamiento, Tirones, Input lag / Factores: Jitter, Pérdida de paquetes, Detención - A quién: Una zona o un canal / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: ajustar el retardo de input automáticamente según el ping, dejar fuera un momento solo al que se retrasa para que los demás sigan sin esperar. Cliente: aplicar el retardo de input fijado; en un P2P sin servidor intermedio, el cliente anfitrión también se encarga de ajustar el retardo de input y de gestionar a los que se retrasan. - Cifras de referencia: Si el retardo de input se fija por debajo de “el tiempo que tarda el input en llegar al otro + jitter”, los congelamientos se vuelven frecuentes. Ese tiempo es la mitad del ping si se intercambian directamente, o aproximadamente la mitad de la suma de los pings de los dos si pasan por un servidor intermedio (relay). - En el gráfico: Picos aleatorios (Tiempo de espera por turno, latencia de llegada de los inputs por jugador) - Dónde mirar: Registrar en cada turno la hora de llegada de los inputs de cada jugador y el tiempo que el turno estuvo detenido esperando, y ver en los turnos detenidos de quién se esperaba el input. Si hay servidor intermedio, también se puede ver con el intervalo de llegada de los paquetes de input de cada jugador en una captura de paquetes del servidor - Se confirma si: En cada turno detenido, el input de la misma persona llegó más tarde que el retardo de input, y en ese momento su jitter o su pérdida de paquetes se disparan - Se descarta si: Si todos los inputs llegaron a tiempo y aun así se detiene, el problema es el tiempo de cálculo de la computadora más lenta o el procesamiento del servidor. Si no hay congelamientos pero los resultados de las dos pantallas difieren, es una desincronización de los cálculos (desync): revisar “Discrepancias de pathfinding en la sincronización de comandos” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · El frame n solo se puede calcular cuando han llegado todos sus inputs, así que si alguno se retrasa, se espera. Si el búfer de retardo de reproducción que absorbe el jitter es pequeño, hay tirones - [1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond](https://www.gamedeveloper.com/programming/1500-archers-on-a-28-8-network-programming-in-age-of-empires-and-beyond) · Game Developer · Programar los comandos para ejecutarse dos turnos después y ajustar la duración del turno a la computadora más lenta y al ping (Speed Control) - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · Fijar el retardo de input (incoming delay) en la latencia “A→servidor + servidor→B” para que todos lo apliquen en el mismo instante #### sy-rollback · Predicciones fallidas en el netcode de rollback · Rollback misprediction Se predice el input del rival y se muestra por adelantado; si la predicción falla, se rebobina y se vuelve a calcular. Cuanto mayor es el ping, más hay que rebobinar. - Por qué → Efecto → En pantalla: El rival cambia de input (distinto de lo predicho) → El input real llega con un retraso de medio ping, y hay que rebobinar y recalcular ese mismo tramo → Las animaciones del rival se saltan algunos frames o cambian de golpe - Síntomas: Teletransporte / Factores: Latencia, Jitter - A quién: Solo yo / Cuándo: Al hacer ciertas acciones, De vez en cuando, al azar - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Combinar 1–3 frames de retardo de input para reducir lo que se rebobina, poner un tope al rebobinado. - Cifras de referencia: Con 100 ms de ping (50 ms en cada sentido), a 60 FPS se rebobinan unos 3 frames. Con 2 frames de retardo de input, baja a 1 frame. - En el gráfico: Picos aleatorios (Frames rebobinados, RTT (ping)) - Dónde mirar: Registrar en el cliente, en cada rebobinado, los frames rebobinados, el RTT en ese momento, el retardo de input configurado y el tiempo que llevó rebobinar y recalcular - Se confirma si: En el instante en que saltaron las animaciones del rival hay muchos frames rebobinados, y el rebobinado medio es aproximadamente (latencia en un sentido − retardo de input) ÷ tiempo de frame, y crece con el ping - Se descarta si: Si hay tirones aunque se rebobine poco, es un problema de rendimiento: el recálculo supera el tiempo de un frame. Si tras rebobinar los resultados de las dos pantallas siguen siendo distintos, es una desincronización de los cálculos (desync) - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [GGPO Rollback Networking SDK](https://www.ggpo.net/) · GGPO · Se predice el input del rival y se avanza; si el input real es distinto, se recalcula desde el punto de divergencia hasta el presente - [8 Frames in 16ms: Rollback Networking in 'Mortal Kombat' and 'Injustice 2'](https://www.gdcvault.com/play/1025471/8-Frames-in-16ms-Rollback) · GDC · El rollback elimina el retardo de input local del lockstep, y se rebobinan y recalculan hasta 8 frames en 16 ms #### sy-no-timestamp · Reproducción al llegar, sin marcas de tiempo · Events played on arrival (no timestamps) Si los eventos del servidor no llevan la hora en que ocurrieron y se reproducen en cuanto llegan, el timing de las animaciones sigue tal cual el jitter de la red. - Por qué → Efecto → En pantalla: Los eventos “inicio de ataque” o “reproducir efecto” se ejecutan en cuanto llegan → Cada paquete tarda un tiempo distinto en llegar y los intervalos son irregulares → Las animaciones de ataques seguidos se aceleran y se frenan, el timing de los patrones del jefe cambia cada vez - Síntomas: Tirones, Cámara rápida / Factores: Jitter - A quién: Solo yo / Cuándo: Siempre - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: reproducir según la hora que trae cada evento (eventos programados, búfer de interpolación). Servidor: añadir a cada evento la hora en que ocurrió (hora del servidor). - En el gráfico: Picos aleatorios (Intervalo de reproducción de eventos, intervalo de llegada de paquetes) - Dónde mirar: Emparejar por número de evento la hora en que ocurrió cada evento en el log del servidor con su hora de llegada y de reproducción en el log del cliente, y comparar los intervalos. En una build de desarrollo, reproducirlo añadiendo jitter (el valor de jitter de tc netem, la latencia mínima y máxima de la emulación de red de Unreal) - Se confirma si: Los eventos ocurren a intervalos regulares en el servidor, pero los intervalos de reproducción siguen tal cual a los de llegada y son irregulares - Se descarta si: Si los paquetes llegan a intervalos regulares y aun así la reproducción es irregular, es un problema de frames en el cliente (“Pico de frametime”). Si ya en el servidor los intervalos son irregulares, apunta a “Tick que excede su presupuesto” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Se añade la hora del servidor a cada actualización y se dibuja la posición correspondiente a la hora objetivo, que es la hora actual menos el tiempo de interpolación (100 ms) - [Snapshot Interpolation](https://gafferongames.com/post/snapshot_interpolation/) · Gaffer On Games · Si se dibuja cada snapshot en cuanto llega, el jitter produce tirones; si se acumulan un momento en el búfer de interpolación antes de dibujarlos, el movimiento es fluido - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Ejemplo en el que el RPC lleva la hora de envío y el receptor reproduce el efecto según la hora del servidor - [tc-netem(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-netem.8.html) · iproute2 · Herramienta de pruebas que imita una red real añadiendo latencia y jitter (delay TIME JITTER) y pérdida (loss random PERCENT) a los paquetes salientes - [Using Network Emulation in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-network-emulation-in-unreal-engine) · Epic Games · Pruebas con latencia mínima y máxima y porcentaje de pérdida de paquetes en el servidor y el cliente; en la consola se configura con comandos como NetEmulation.PktLag #### sy-double-tick · Doble espera de tick · Double tick quantization Si las solicitudes se acumulan hasta el siguiente tick para procesarlas y el resultado también se envía en el tick posterior, el intervalo de tick se suma dos veces. - Por qué → Efecto → En pantalla: Las solicitudes recibidas se procesan en el siguiente tick → El resultado también se acumula para enviarlo en el siguiente tick de envío → El ping de la conexión es bajo, pero la respuesta llega siempre con un retraso de aproximadamente 1.5 veces el intervalo de tick. En un servidor de 10 ticks, 0.15 s de media y 0.2 s en el peor caso - Síntomas: Input lag / Factores: Latencia - A quién: Todo el servidor / Cuándo: Siempre - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Enviar la respuesta en el mismo tick en que se procesa, subir el tick rate, enviar al instante las respuestas importantes. - Cifras de referencia: En un servidor de 10 ticks cada tick dura 100 ms, así que solo la espera de tick añade 150 ms de media y 200 ms en el peor caso. Con una sola espera, la media es de 50 ms. - En el gráfico: Siempre alto (Tiempo desde que llega la solicitud hasta que se envía la respuesta) - Dónde mirar: En una captura de paquetes del lado del servidor, medir el intervalo entre la llegada del paquete de solicitud y la salida del paquete de respuesta mientras una cuenta de prueba repite la misma acción (p. ej., usar un objeto). Si hay logs del servidor, ver la hora de llegada de la solicitud, el número del tick que la procesó y la hora de envío de la respuesta - Se confirma si: El tiempo dentro del servidor es de aproximadamente 1.5 veces el intervalo de tick de media y 2 veces como máximo, y es constante sin importar el RTT - Se descarta si: Si el tiempo dentro del servidor ronda la mitad del intervalo de tick de media, solo hay una espera de tick. Si es más largo que el intervalo de tick y varía, revisar “Tick que excede su presupuesto” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Un input que llega espera como máximo un tick hasta el siguiente límite de tick, y aplicarlo y enviarlo cuesta otro frame. Cuanto más alto es el tick rate, menor es la espera - [VALORANT's 128-Tick Servers](https://www.riotgames.com/en/news/valorants-128-tick-servers) · Riot Games · Parte de la latencia viene de la red y parte del tick rate del servidor - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Los cambios de NetworkVariable no se envían al instante: se acumulan y se envían en cada tick de red #### sy-strict-check · Validación del servidor demasiado estricta · Over-strict server validation Si el servidor comprueba con demasiada rigidez la velocidad de movimiento, los cooldowns o el alcance, rechaza incluso inputs legítimos que llegaron juntos por el jitter. - Por qué → Efecto → En pantalla: Criterios estrictos como “distancia máxima por tick” o “tolerancia de cooldown: 0 ms” → Si por el jitter llegan dos comandos en el mismo tick, se consideran una infracción de las reglas → Rubber banding, una habilidad rechazada aunque el cooldown ya terminó - Síntomas: Rubber banding, Acción perdida / rollback / Factores: Jitter - A quién: Solo yo / Cuándo: De vez en cuando, al azar, Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Validar con un margen acumulado (token bucket), dejar un margen equivalente al ping y el jitter. - En el gráfico: Picos aleatorios (Rechazos de validación y correcciones de posición del servidor) - Dónde mirar: Registrar en el log del servidor, para cada rechazo de validación o corrección de posición, el motivo, el número de comandos de ese jugador que llegaron en ese tick y el intervalo de llegada respecto al comando anterior - Se confirma si: Los rechazos y correcciones se concentran en los momentos en que llegaron 2 o más comandos en un mismo tick, y el movimiento y el número de usos sumados en ventanas de unos segundos están dentro de las reglas - Se descarta si: Si incluso sumando en ventanas de unos segundos se superan las reglas, puede haber exceso de velocidad o trampas reales. Si los rechazos se concentran en un ISP concreto y por la noche, apunta a “Falsos positivos de validación concentrados en un ISP” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Admite comandos que llegan juntos con un presupuesto de procesamiento que se acumula en cada tick (máximo sv_maxusrcmdprocessticks, 24 ticks). Comentario de los desarrolladores: con un bloqueo más estricto, los jugadores legítimos también sufrían tirones - [RFC 2697: A Single Rate Three Color Marker](https://www.rfc-editor.org/rfc/rfc2697) · IETF · Token bucket: decide con la tasa media (CIR) y el tamaño de ráfaga que se admite de una vez (CBS) #### sy-host · Arquitectura de anfitrión (host) · Listen server / host advantage Cuando la computadora de un jugador hace de servidor, su conexión y el rendimiento de su PC determinan lo que perciben todos. - Por qué → Efecto → En pantalla: La computadora del anfitrión hace de servidor (P2P, listen server) → Si la conexión o la computadora del anfitrión van lentas, afecta a todos; el anfitrión juega con ping 0 → Solo el anfitrión tiene ventaja; si se va, todos sufren un congelamiento o una desconexión - Síntomas: Tirones, Congelamiento, Desconexión / Factores: Latencia, Detención - A quién: Una zona o un canal / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo), Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Servidor: pasar a servidores dedicados que resuelvan la partida y, mientras tanto, elegir como anfitrión en el matchmaking a quien tenga mejor conexión y PC. Cliente: admitir la migración del anfitrión (host migration), medir en el matchmaking el ping con los demás participantes, la velocidad de subida y el rendimiento de su PC, y enviarlos. - Tareas (Equipo de infraestructura): Conseguir servidores o instancias para los servidores dedicados y ubicarlos cerca de las regiones con muchos jugadores. - En el gráfico: Alto solo en algunos (Reportes de lag y desconexiones por anfitrión) - Dónde mirar: Registrar en el log de la partida la velocidad de subida del anfitrión (host), el RTT de cada participante con el anfitrión, el tiempo de frame de la computadora del anfitrión y la hora en que se fue, y agrupar por anfitrión los reportes de lag y desconexión. Los jugadores también pueden comprobarlo repitiendo la partida con las mismas personas y otro anfitrión - Se confirma si: El lag y las desconexiones se concentran en las salas de un anfitrión concreto, todos los participantes empeoran a la vez cuando su velocidad de subida es baja o su tiempo de frame es largo, y sin migración del anfitrión todos se desconectan en el instante en que se va - Se descarta si: Si solo empeoran los participantes de una misma región, sin importar el anfitrión, es un problema de conexión o de ruta. Con servidores dedicados, no es esta causa - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Networking Overview for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-overview-for-unreal-engine) · Epic Games · El anfitrión de un listen server tiene ventaja sobre los demás clientes y soporta mucha carga porque hace de servidor y renderiza a la vez - [Distributed authority topologies (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/distributed-authority.html) · Unity · Si el propietario de la sesión se va, se elige automáticamente un nuevo propietario entre los clientes que quedan - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · Un juego P2P también puede verse como una arquitectura cliente-servidor en la que el anfitrión hace a la vez de servidor #### sy-optimistic-reject · Rechazo del servidor tras el feedback anticipado · Client-side feedback rejected by server Si el servidor no acepta después un golpe o una habilidad que tu pantalla ya mostró, lo que viste claramente queda anulado. - Por qué → Efecto → En pantalla: Los efectos de golpe y las animaciones de habilidad se reproducen antes de la confirmación del servidor (feedback anticipado) → El servidor vuelve a comprobar el alcance, la posición del objetivo, el cooldown y los recursos, y lo rechaza → Salta sangre pero no hay daño, la habilidad hace la animación pero no tiene efecto, solo se activa el cooldown - Síntomas: Acción perdida / rollback, Rubber banding / Factores: Latencia - A quién: Solo yo, Solo una función / Cuándo: Al hacer ciertas acciones - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: mostrar con el resultado del servidor solo lo que necesita confirmación, como los números de daño, las muertes o las recompensas, comprobar primero los motivos de rechazo más comunes y, si hay rechazo, devolver el cooldown y los recursos y mostrar el motivo. Servidor: dejar un margen equivalente al ping en las comprobaciones de alcance y posición del objetivo, incluir el motivo en la respuesta de rechazo, recopilar como métrica la tasa de rechazo por habilidad. - Cifras de referencia: El rechazo llega un ping + la espera del tick después de presionar. Con 150 ms de ping, durante unos 0.2 s crees que acertaste. - En el gráfico: Alto solo en algunos (Tasa de rechazo del servidor por habilidad (por rango de ping)) - Dónde mirar: Recopilar en el servidor la tasa de rechazo por habilidad y los motivos de rechazo (alcance, posición del objetivo, cooldown, recursos), y dividirlos por rangos de RTT del jugador. En el cliente, registrar cuántas veces se rechaza una acción con feedback anticipado - Se confirma si: Los rechazos se concentran en habilidades concretas y en los motivos de alcance o posición del objetivo, y la tasa de rechazo sube con el ping - Se descarta si: Si los motivos son el cooldown o los recursos y no dependen del ping, revisar si los valores de datos (cooldown, costo) difieren entre el cliente y el servidor. Si no hay rechazos y el feedback empieza solo tras la respuesta del servidor, apunta a “Feedback solo tras la respuesta del servidor (solicitud-respuesta)” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: El feedback anticipado es la mejor forma de disimular el ping. Pero cuanto más difiere la información que usan el cliente y el servidor para decidir (posición del rival, recursos restantes), más frecuentes son los rechazos. Si se recopila la tasa de rechazo por habilidad como métrica, es fácil encontrar dónde no coinciden las validaciones. - Fuentes: - [Using Gameplay Abilities in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-gameplay-abilities-in-unreal-engine) · Epic Games · Las habilidades Local Predicted se ejecutan al instante en el cliente, pero el servidor decide al final y puede revertir el resultado - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · El disparo del arma se predice en el cliente y su efecto se reproduce primero; el error de predicción se corrige con el resultado del servidor #### sy-path-mismatch · Discrepancias de pathfinding en la sincronización de comandos · Command sync with divergent pathing Si solo se intercambia “ve aquí” y cada lado calcula la ruta por su cuenta, basta una pequeña diferencia de cálculo para que un personaje o un monstruo tome otra ruta y después vuelva arrastrado a su sitio. - Por qué → Efecto → En pantalla: En el movimiento por clic o la persecución de monstruos, solo se envía el destino y el cliente calcula la ruta por separado → Por diferencias en los datos del terreno, colisiones con otros personajes o un orden de cálculo distinto, se mueve por una ruta distinta a la del servidor → Un monstruo atraviesa una pared y de golpe aparece en otro sitio, tu personaje cambia de dirección tras el clic como si se deslizara - Síntomas: Teletransporte, Rubber banding / Factores: Latencia - A quién: Una zona o un canal, Solo yo / Cuándo: Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: enviar también los puntos intermedios de la ruta (waypoints), sincronizar la posición periódicamente. Cliente: corregir los desajustes de forma suave, usar los mismos datos de terreno que el servidor. - En el gráfico: Picos aleatorios (Correcciones de posición por entidad (número y distancia)) - Dónde mirar: Registrar para cada entidad la diferencia entre la posición enviada por el servidor y la calculada por el cliente, y marcar en el mapa las coordenadas donde hubo correcciones. Resumir con checksums las rutas o posiciones de los dos lados y compararlas periódicamente permite encontrar el momento en que empezaron a divergir - Se confirma si: Las correcciones se concentran en ciertos terrenos (umbrales, pasillos estrechos, pendientes) o en zonas concurridas, y se repiten en el mismo sitio incluso para jugadores con métricas de red normales - Se descarta si: Si las correcciones ocurren en cualquier sitio y solo cuando se disparan la pérdida o el jitter, es un problema de conexión. Si un monstruo salta a la vez en las pantallas de varios jugadores, revisar “Un cliente lento controla al monstruo” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Este modelo es una de las razones por las que los juegos de movimiento por clic y de selección de objetivo (tab target) son poco sensibles al ping. Pero no hay garantía de que los dos lados obtengan el mismo resultado, así que hace falta sí o sí un mecanismo que sincronice la posición de vez en cuando. Los cálculos en coma flotante pueden dar resultados ligeramente distintos según el tipo de CPU, el compilador y sus opciones de optimización (incluida la diferencia entre builds de depuración y de release). En arquitecturas como el lockstep o el rollback, que solo intercambian inputs y suponen que los dos lados calculan exactamente lo mismo, estas pequeñas diferencias se acumulan y pueden provocar una desincronización (desync) en la que el estado del juego de las dos pantallas se separa. - Fuentes: - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · Aunque sea determinista en la misma máquina, el resultado en coma flotante puede variar si cambian el compilador, el SO o la CPU - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Si se envía el estado junto con los inputs, se pueden sincronizar los dos lados sin un determinismo perfecto - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Con pérdida de paquetes o cuando dos personajes intentan ir al mismo sitio, las simulaciones del servidor y del cliente divergen y hace falta corregir - [1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond](https://www.gamedeveloper.com/programming/1500-archers-on-a-28-8-network-programming-in-age-of-empires-and-beyond) · Game Developer · Diferencias minúsculas crecen con el tiempo y las rutas de los aldeanos se desvían poco a poco. Se comparan con checksums el mundo, las entidades y la búsqueda de rutas para detectar la desincronización (out-of-sync) - [Floating Point Determinism](https://gafferongames.com/post/floating_point_determinism/) · Gaffer On Games · El mismo código de coma flotante puede dar resultados distintos según el compilador, la arquitectura de CPU o las builds de depuración y de release. Caso en que CPU de AMD e Intel dieron valores ligeramente distintos en funciones trascendentes - [/fp (Specify floating-point behavior)](https://learn.microsoft.com/en-us/cpp/build/reference/fp-specify-floating-point-behavior) · Microsoft · /fp:fast puede reordenar o combinar operaciones de coma flotante y dar resultados distintos de otras opciones /fp, y una operación combinada con FMA también puede diferir de multiplicar y sumar por separado #### sy-low-send-rate · Tasa de envío de snapshots baja · Low snapshot / update rate Si el servidor envía las actualizaciones de posición (snapshots) solo unas pocas veces por segundo, hay que alargar en proporción el búfer de interpolación, y los demás personajes se ven más en el pasado. - Por qué → Efecto → En pantalla: Para ahorrar tráfico, las actualizaciones de posición se envían solo 5–10 veces por segundo → Para dibujar con fluidez, el búfer debe ser del doble del intervalo entre paquetes (200–400 ms); si es más corto, basta perder un paquete para que haya un congelamiento → Los cambios de dirección del rival se ven tarde y no coinciden con la resolución de impactos. Con un búfer corto hay tirones, y teletransporte cuando se pierden paquetes - Síntomas: Tirones, Teletransporte, Acción perdida / rollback / Factores: Latencia, Pérdida de paquetes - A quién: Todo el servidor / Cuándo: Siempre - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: enviar con frecuencia las entidades cercanas o en combate y con menos frecuencia las lejanas, enviar solo lo que cambió (compresión delta) para reducir el tamaño de cada envío y subir la frecuencia. Cliente: ajustar automáticamente la longitud del búfer de interpolación al intervalo entre paquetes. - Cifras de referencia: Con 10 envíos por segundo, el intervalo entre paquetes es de 100 ms y el búfer de 200 ms. Sumando los 75 ms de latencia en un sentido de un ping de 150 ms, al rival se le ve unos 0.3 s en el pasado. - En el gráfico: Siempre alto (Intervalo de llegada de paquetes por cliente, longitud del búfer de interpolación) - Dónde mirar: En una captura de paquetes del lado del servidor, filtrar solo el flujo hacia un jugador y ver los paquetes por segundo y sus intervalos con I/O Graphs de Wireshark. Si hay logs del juego, ver también el intervalo de actualización por entidad y el margen del búfer de interpolación del cliente (tiempo que falta para que llegue el siguiente snapshot) - Se confirma si: Las actualizaciones de posición son siempre escasas, 5–10 por segundo (intervalos de 100–200 ms), y el búfer de interpolación pasa de 200 ms o su margen llega a 0 con frecuencia - Se descarta si: Si las actualizaciones salen con frecuencia pero los intervalos de llegada varían, apunta a jitter o pérdida de paquetes. Si con mucha gente solo se reciben con poca frecuencia las entidades lejanas, apunta a “Presupuesto de envío y prioridad por conexión” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Con 10 actualizaciones por segundo, 200 ms de interpolación aguantan la pérdida de una. Por defecto, Half-Life usa 20 actualizaciones por segundo y 100 ms de interpolación - [Snapshot Interpolation](https://gafferongames.com/post/snapshot_interpolation/) · Gaffer On Games · Con 10 por segundo, aguantar hasta dos pérdidas seguidas requiere 350 ms de retraso; con 30 por segundo, baja a 150 ms - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Con prioridades acumuladas, las entidades importantes se envían más a menudo y el resto se envía por turnos dentro del límite de ancho de banda - [8.8. The “I/O Graphs” Window](https://www.wireshark.org/docs/wsug_html_chunked/ChStatIOGraphs.html) · Wireshark · Grafica por intervalos de tiempo el número de paquetes y bytes que cumplen el filtro de visualización ### Problemas que solo afectan a algunos (causas: 24) #### pt-slow-burst · Un jugador con lag se mueve a ráfagas en la pantalla de los demás · Laggy player seen by others (bursty inputs) Los inputs de alguien con mala conexión llegan al servidor de forma irregular y a ráfagas. Si el servidor aplica en cada tick lo que haya recibido, los demás ven a ese personaje detenerse un instante y luego avanzar varios pasos de golpe. - Por qué → Efecto → En pantalla: Los comandos de movimiento del jugador con lag llegan 0 en un tick y 2–3 en otro → El servidor los aplica todos de una vez en el tick en que llegan, y la posición de ese personaje avanza en escalones → En las pantallas de los demás, solo ese personaje se detiene un instante y luego avanza de golpe. El resto se ve bien - Síntomas: Cámara rápida, Teletransporte / Factores: Jitter, Pérdida de paquetes - A quién: Solo un personaje se ve raro, Una región o un ISP / Cuándo: Siempre, Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Externo (Externo) - Tareas (Equipo de desarrollo): Repartir los comandos de forma pareja con un búfer de inputs por jugador, aplicarlos con su intervalo original según el número de secuencia del input; alargar solo el búfer de interpolación en las pantallas de los demás no basta (porque el propio historial de posiciones del servidor ya va a saltos). - Tareas (Externo): Indicar al jugador con lag que use cable y revise el Wi-Fi y el router. - Cifras de referencia: Con 80 ms de jitter, en un servidor de 20 ticks (50 ms) el número de comandos por tick oscila entre 0 y 3. - En el gráfico: Alto solo en algunos (Comandos aplicados por tick por jugador, jitter por jugador) - Dónde mirar: En una captura de paquetes del lado del servidor, filtrar solo los paquetes del jugador reportado, contar cuántos llegan en cada intervalo de tick (p. ej., 50 ms) y comparar con otros jugadores. Si hay logs del servidor, ver por jugador los comandos de movimiento aplicados en cada tick y los números de secuencia de input - Se confirma si: Solo los paquetes del jugador reportado llegan a ráfagas, alternando entre 0 y 2–3 por tick, con jitter y pérdida altos en ese jugador, mientras los paquetes de los demás llegan de forma pareja. Mejora si ese jugador se pasa a cable - Se descarta si: Si varios personajes se mueven a ráfagas a la vez, apunta al retraso del tick del servidor o a la conexión de quien mira. Si la llegada y la aplicación son parejas y aun así solo ese personaje parece saltar, es un problema de interpolación o de visualización en el lado de quien mira - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: En una arquitectura con autoridad del servidor, esto es el comportamiento normal. El lag de una sola persona solo lo ven los demás como “esa persona se mueve raro”, y no afecta al control de los demás ni al movimiento de los monstruos. Pero lo que se hace directamente con esa persona (intercambios, mecánicas de grupo, resolución en PvP) también se retrasa. - Fuentes: - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · El servidor mete los inputs que llegan en la cola de movimiento de cada jugador por orden de tick y, si se vacía, la rellena con predicción. Las correcciones solo las ve ese jugador; el resto lo ve fluido - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Incluso paquetes enviados 60 veces por segundo llegan agrupados: 2 en un frame y 0 en el siguiente - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Repartir entre los ticks del servidor los comandos que llegan juntos (meter out) #### pt-event-server · Cámara rápida en servidores que procesan cada paquete al llegar · Event-driven processing of bursty inputs En un servidor que procesa y anuncia cada paquete en cuanto llega, las acciones acumuladas de un jugador con lag se ejecutan una tras otra al instante. - Por qué → Efecto → En pantalla: Las solicitudes de habilidades y de movimiento del jugador con lag llegan a ráfagas → El servidor las ejecuta en orden en cuanto las recibe y las anuncia a todos de inmediato → Los demás ven a esa persona usar varias habilidades en un instante o moverse como en cámara rápida - Síntomas: Cámara rápida / Factores: Jitter - A quién: Solo un personaje se ve raro / Cuándo: Al hacer ciertas acciones, Siempre - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: ejecutar las acciones con el intervalo de las horas de input que traen (aceptando la hora solo dentro de un margen permitido), o, sin rechazar las acciones que llegan juntas, ejecutarlas por turnos separadas por un intervalo mínimo (cooldown global); no comprobar el cooldown solo con la hora de llegada (se pierden inputs legítimos). Cliente: añadir a cada acción la hora del input al enviarla. - En el gráfico: Alto solo en algunos (Intervalo de ejecución de acciones por jugador) - Dónde mirar: Registrar en el log del servidor, por jugador, la hora de llegada de cada acción, la hora de ejecución y la hora de input que añade el cliente (si existe), y comparar los intervalos de ejecución con los de input. Ver también el intervalo de llegada de los paquetes de ese jugador en una captura de paquetes del lado del servidor - Se confirma si: Los intervalos de input son normales, pero los de llegada y ejecución en el servidor se amontonan en unos pocos ms, y esos momentos coinciden con la hora de los reportes de cámara rápida de los demás - Se descarta si: Si ya los intervalos de las horas de input están amontonados, apunta al cliente o a una macro. Si los intervalos de ejecución en el servidor son parejos y solo se ven amontonados en las pantallas de los demás, apunta a la conexión de quien mira - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · Cada vez que recibe un ServerMove, el servidor calcula el movimiento y fija el intervalo de tiempo con la diferencia de timestamp respecto al movimiento anterior. Si difiere demasiado de la hora del servidor, descarta ese movimiento - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · Si los inputs se aplican según llegan, aunque se envíen a 60 Hz los intervalos no son regulares y el resultado es irregular #### pt-input-buffer · Tamaño del búfer de inputs de cada jugador · Per-player server input buffer (jitter buffer) Si el servidor guarda un poco los inputs de cada jugador y los saca de uno en uno por tick, los demás lo ven fluido, pero el momento en que el servidor confirma las acciones de ese jugador se retrasa en la misma medida. - Por qué → Efecto → En pantalla: El servidor acumula en un búfer los inputs del jugador con lag y aplica uno por tick → Si el búfer es pequeño, se vacía a menudo y ese personaje se queda quieto o el servidor lo mueve suponiendo el último input; si es grande, los inputs del propio jugador se confirman tarde → Pequeño: los demás lo ven detenerse un instante. Grande: los resultados de sus habilidades salen tarde (input lag) - Síntomas: Tirones, Input lag / Factores: Jitter - A quién: Solo un personaje se ve raro, Solo yo / Cuándo: Siempre - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: ajustar automáticamente el tamaño del búfer de cada jugador según el estado de su conexión, sacar dos inputs a la vez para ponerse al día cuando se acumulan, indicar al cliente de quien vacía a menudo el búfer que envíe sus inputs antes. Cliente: adelantar un poco el envío de inputs según lo indique el servidor (ajuste del tiempo del cliente). - Cifras de referencia: Depende del juego, pero suele equivaler a 1–3 ticks. VALORANT, con servidores de 128 ticks, mantiene un búfer de servidor aún más corto, de medio frame de media (unos 4 ms). Es habitual un búfer adaptativo que solo crece para quienes tienen mucho jitter. - En el gráfico: Alto solo en algunos (Longitud del búfer de inputs y veces que se vacía, por jugador) - Dónde mirar: Registrar en el servidor, por jugador y en cada tick, los inputs que quedan en el búfer, cuántas veces se vació y se rellenó suponiendo el último input, y el tiempo desde que llega un input hasta que se aplica - Se confirma si: Quienes tienen un búfer pequeño lo vacían a menudo y en esos momentos se detienen un instante en las pantallas de los demás, y en quienes tienen un búfer grande el tiempo del input a su aplicación crece tanto como la longitud del búfer - Se descarta si: Si el búfer casi nunca se vacía pero los demás ven tirones, es un problema de interpolación en el lado de quien mira. Si el búfer es corto y aun así el input lag es alto, apunta al propio RTT o a “Doble espera de tick” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · El servidor ajusta la referencia de tiempo del cliente para que la cola de inputs tenga la mínima latencia posible y solo lo justo para absorber las llegadas irregulares. El objetivo de búfer en el servidor es medio frame de media - [NetworkTimeSystem class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkTimeSystem.html) · Unity · LocalBufferSec: tiempo que el servidor guarda en búfer los mensajes del cliente. Se adelanta el tiempo del cliente para que los mensajes lleguen antes al servidor - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Los jugadores con mala conexión pueden aumentar el valor del búfer #### pt-isp-validation · Falsos positivos de validación concentrados en un ISP · Anti-cheat / movement validation false positives on bad ISPs Los inputs de quienes usan conexiones con mucho jitter llegan a ráfagas, así que caen a menudo en las comprobaciones de velocidad y cooldown del servidor. - Por qué → Efecto → En pantalla: El jitter de las conexiones de un ISP o una región concretos aumenta por la noche → El servidor interpreta como exceso de velocidad o infracción de cooldown los inputs legítimos que llegaron juntos → Solo los jugadores de ese ISP sufren rubber banding, rechazos de habilidades y, en casos graves, una desconexión porque el servidor los expulsa - Síntomas: Rubber banding, Acción perdida / rollback, Desconexión / Factores: Jitter - A quién: Una región o un ISP, Solo yo / Cuándo: Horas pico de la noche, Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Comprobar con un margen acumulado a lo largo de varios segundos, relajar el criterio teniendo en cuenta el estado de la conexión (ping, jitter), poner una fase de aviso antes de la expulsión, y repartir en cada tick los inputs que llegan juntos con un búfer de inputs por jugador para reducir los propios falsos positivos. - Tareas (Equipo de infraestructura): Revisar por franja horaria la distribución de la tasa de pérdida y el jitter de cada ISP y compartirla con el equipo de desarrollo, revisar la ruta del tramo de ese ISP (mtr en ambos sentidos) y, si hace falta, cambiar la ruta o escalar al ISP. - En el gráfico: Alto solo a ciertas horas (Rechazos de validación y expulsiones por ISP (ASN), jitter por ISP) - Dónde mirar: Añadir el ISP (ASN) de la IP de conexión y la hora a los logs de rechazos de validación, correcciones y expulsiones del servidor, y contarlos por ISP y franja horaria. El equipo de infraestructura lanza a la misma hora un mtr en ambos sentidos hacia ese ISP para ver el jitter y la pérdida - Se confirma si: Los rechazos y expulsiones se concentran en un ISP y aumentan por la noche, el jitter de ese ISP es alto a la misma hora, y el movimiento sumado en ventanas de unos segundos está dentro de las reglas - Se descarta si: Si se repite solo en ciertas cuentas sin importar el ISP, puede haber trampas reales. Si aumenta en todos los ISP a la vez, la causa está en el servidor: el tick se retrasa y los comandos se aplican amontonados (“Tick que excede su presupuesto”) - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Comentario de los desarrolladores: el presupuesto de comandos que se acumula en cada tick frena el exceso de velocidad, pero un límite más estricto provoca tirones también a los jugadores legítimos - [RFC 2697: A Single Rate Three Color Marker](https://www.rfc-editor.org/rfc/rfc2697) · IETF · Token bucket: decide con la tasa media y el tamaño de ráfaga permitido - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · Si la diferencia entre los timestamps del cliente y del servidor es grande, el movimiento se descarta o pasa por un procedimiento que resuelve la diferencia de tiempo; se calcula con la hora del servidor para evitar los speed hacks #### pt-raid-member · Un miembro del grupo con lag y las mecánicas del jefe · One laggy member in a synchronized mechanic En las mecánicas de raid en las que todos deben reaccionar juntos en un momento preciso, la reacción tardía de una sola persona con lag hace fracasar a todo el grupo. - Por qué → Efecto → En pantalla: Mecánicas compartidas como “todos se dispersan a la vez” o “uno presiona un botón” → El jugador con lag ve tarde el aviso y su input también llega tarde → El grupo entero cae (wipe) por culpa de esa persona, y los demás sienten que “fue por el que tenía lag” - Síntomas: Acción perdida / rollback, Input lag / Factores: Latencia - A quién: Una zona o un canal, Solo un personaje se ve raro / Cuándo: Cuando se junta mucha gente, Al hacer ciertas acciones - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: dar a la ventana de tiempo de la mecánica un margen equivalente al ping, enviar los avisos por adelantado en hora del servidor, diseñar para que el fallo de uno no acabe con todo el grupo. Cliente: reproducir los avisos recibidos según la hora del servidor. - En el gráfico: Alto solo en algunos (RTT por jugador de quienes provocaron el fallo de la mecánica) - Dónde mirar: Registrar en el log de mecánicas del servidor el jugador que provocó el fallo, la hora de llegada de su input, la ventana de tiempo y su RTT y pérdida - Se confirma si: La mayoría de los inputs que provocaron el wipe son de la misma persona, cuyo RTT es claramente más alto que la media del grupo, y sus inputs llegan justo después de cerrarse la ventana - Se descarta si: Si los fallos se reparten por igual entre los miembros del grupo, el problema es que la propia ventana es corta (“Ventanas de tiempo cortas que el ping consume”). Si el input del jugador con lag llegó dentro de la ventana y aun así falla, apunta al código de validación del servidor - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Método para programar eventos según la hora del servidor para que todos los reproduzcan en el mismo instante - [Factors influencing the latency of simple reaction time (Frontiers in Human Neuroscience, 2015)](https://doi.org/10.3389/fnhum.2015.00131) · Frontiers · Tiempo de reacción simple medio: unos 231 ms #### pt-mob-control · Un cliente lento controla al monstruo · Monster movement delegated to a player client Para reducir la carga del servidor, algunos juegos delegan el cálculo del movimiento de un monstruo en el cliente de un jugador cercano. Si la conexión de ese jugador es mala, el monstruo se mueve raro en las pantallas de todos. - Por qué → Efecto → En pantalla: El servidor delega el cálculo del movimiento del monstruo en el cliente del jugador más cercano (o del primero en llegar) → Los resultados que reporta ese jugador llegan tarde o a ráfagas al servidor → Solo ese monstruo se detiene un instante y luego se teletransporta en las pantallas de todos los que están cerca. En la pantalla del propio jugador encargado se ve bien - Síntomas: Teletransporte, Tirones, Cámara rápida / Factores: Jitter, Pérdida de paquetes - A quién: Solo un personaje se ve raro, Una zona o un canal / Cuándo: Siempre, De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Pasar el control a alguien con buena conexión (según ping y pérdida), hacer que el servidor lo recupere de inmediato si se cortan los reportes, y que el propio servidor calcule los monstruos importantes, como los jefes. - En el gráfico: Alto solo en algunos (Intervalo de reporte de posición por monstruo (por cliente con el control)) - Dónde mirar: Registrar en el servidor, para cada monstruo, el cliente que tiene el control y su intervalo de reporte, RTT y pérdida. En una captura de paquetes del lado del servidor también se puede ver el intervalo de llegada de los paquetes de ese cliente - Se confirma si: El control de todos los monstruos que se mueven raro lo tiene la misma persona, sus intervalos de reporte son irregulares o se cortan, y al pasar el control a otro todo vuelve a la normalidad de inmediato - Se descarta si: Si los monstruos que calcula el propio servidor también saltan, apunta al retraso del tick del servidor o a la conexión de quien mira. Si siguen saltando después de pasar el control, apunta a “Discrepancias de pathfinding en la sincronización de comandos” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: Como el encargado lo ve todo bien, los reportes solo llegan como “el monstruo se comporta raro”. Si todos menos una persona ven raro el mismo monstruo, lo primero es comprobar quién tiene el control de ese monstruo. - Fuentes: - [Authority (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/authority.html) · Unity · En el modelo de autoridad distribuida, cada instancia del juego (cliente) asume la autoridad sobre algunas entidades de red y las calcula - [Distributed authority topologies (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/distributed-authority.html) · Unity · Si la autoridad se reparte entre los clientes, no hay una simulación única y el juego queda expuesto a las trampas #### pt-heavy-char · Personaje con datos sobredimensionados · One character with oversized data (inventory, mail, buffs) Un personaje con miles de objetos o correos acumulados, o con listas de amigos o de bloqueados y buffs fuera de lo normal, tiene varias veces más datos que cargar al conectarse, que guardar y que anunciar a su alrededor. Va lento solo con ese personaje, sin importar la conexión. - Por qué → Efecto → En pantalla: Un personaje antiguo o las recompensas de eventos acumulan miles de elementos en el inventario o el buzón → En cada conexión, cambio de zona o guardado se lee y escribe todo eso en la BD, y la información de equipamiento y buffs que se envía a los de alrededor también es grande → Solo ese personaje tiene cargas de entrada largas y tirones al abrir el inventario o el correo. Si el servidor espera el guardado en el hilo del juego, los de alrededor también sufren una pausa breve - Síntomas: No conecta / carga infinita, Input lag, Congelamiento / Factores: Detención - A quién: Solo yo, Solo una función / Cuándo: Al conectar o tras un mantenimiento, Al hacer ciertas acciones, Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de BD (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Poner límites de almacenamiento al inventario y al correo y limpiar automáticamente los correos antiguos, cargar por partes solo lo necesario, guardar solo lo que cambió y fuera del hilo del juego. - Tareas (Equipo de infraestructura): Buscar en el log de consultas lentas las consultas lentas que se repiten con el mismo personaje y pasarlas al equipo de desarrollo, entregar la lista de personajes con más filas de objetos y de correo. - Cifras de referencia: Si cada objeto es una fila en la BD, un personaje con 5,000 objetos lee 5,000 filas cada vez que se conecta. Decenas de veces más que un personaje normal. - En el gráfico: Alto solo en algunos (Tiempo de conexión y de guardado por personaje, filas leídas de la BD por personaje) - Dónde mirar: Buscar en el log de consultas lentas de la BD (MySQL slow query log, PostgreSQL log_min_duration_statement) las lecturas y guardados lentos que se repiten con el mismo ID de personaje, y sacar la lista de personajes con más filas en las tablas de objetos y de correo - Se confirma si: Las consultas lentas se concentran en unos pocos ID de personaje, esos personajes tienen decenas de veces más filas de objetos y de correo que la media, y van igual de lentos desde otra computadora y otra conexión - Se descarta si: Si otros personajes de la misma cuenta u otros jugadores también van lentos, apunta a los servidores de BD o a los bloqueos. Si ese personaje va bien desde otra computadora, apunta al entorno del jugador - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Si con el mismo personaje va igual de lento desde otra computadora y otra conexión, mientras los demás personajes de la misma cuenta van bien, hay que sospechar de los datos del personaje. Por eso el reporte debe incluir siempre el nombre del personaje. - Fuentes: - [Extraneous Fetching antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/extraneous-fetching/) · Microsoft Azure · Traer más datos de los necesarios aumenta la carga de E/S y vuelve lentas las respuestas - [PostgreSQL Documentation: Error Reporting and Logging](https://www.postgresql.org/docs/current/runtime-config-logging.html) · PostgreSQL · log_min_duration_statement: registra las sentencias SQL que tardan más de cierto tiempo, para rastrear consultas lentas - [The Slow Query Log](https://dev.mysql.com/doc/refman/8.4/en/slow-query-log.html) · MySQL · Log de consultas lentas que registra las consultas que superan long_query_time #### pt-phase · Diferencias de canal, instancia o phasing · Different channel / instance / phase Si dos personajes están en canales o instancias distintos, o en “fases” (phasing) distintas en las que los NPC visibles cambian según el progreso de las misiones, cada uno ve un mundo distinto. - Por qué → Efecto → En pantalla: El segundo personaje está asignado a otro canal o va en otra etapa de la misión → El servidor no le envía ese NPC a ese personaje (es lo normal) → El NPC solo falta en uno de los dos. Parece un bug, pero es lo previsto por el diseño - Síntomas: Entidades invisibles / fantasma / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC, Solo yo / Cuándo: Siempre, Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: enviar al cliente la información de canal y fase, añadir a la checklist de QA “comprobar el canal y la etapa de la misión de los dos personajes”. Cliente: mostrar en pantalla el canal y la fase. - En el gráfico: Alto solo en algunos (Entidades cercanas por cliente, canal y fase) - Dónde mirar: Comparar en pantalla el número de canal de los dos personajes y la etapa de la misión correspondiente, y volver a mirar con el mismo canal y la misma etapa. Si hay logs de envío de entidades del servidor, comprobar por qué no se envió ese NPC a ese personaje (canal o fase) - Se confirma si: Los dos personajes están en canales o etapas de misión distintos, y al igualarlos el NPC aparece - Se descarta si: Si el canal y la etapa coinciden y aun así falta en uno de los dos, apunta a “Mensajes de aparición descartados durante la carga”, “Pérdida de la ráfaga de mensajes de aparición al entrar” o “Condición de carrera en el registro de visibilidad (AOI)” - Se verifica con: En el entorno del jugador - Para saber más: También hay que comprobar si el progreso de las misiones se guarda por cuenta o por personaje. Si son dos personajes de la misma cuenta, el progreso de uno puede cambiar la fase del otro. - Fuentes: - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · El servidor replica a cada conexión solo los actores relevantes (relevant) y no envía los que no lo son - [Object visibility (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/basics/object-visibility.html) · Unity · CheckObjectVisibility decide qué entidades ve cada cliente, y las ocultas no se envían a ese cliente #### pt-loading-drop · Mensajes de aparición descartados durante la carga · Spawn messages dropped before the client is ready En cuanto el personaje entra en una zona, el servidor envía los mensajes de aparición de los NPC cercanos, pero el cliente todavía está cargando el mapa y los descarta. - Por qué → Efecto → En pantalla: El servidor envía los mensajes de aparición de las entidades cercanas justo después de procesar la entrada → El cliente está cargando y todavía no tiene el manejador (handler) de esos mensajes, así que los descarta → El servidor los da por enviados y no los repite. El NPC no se ve hasta que sale del rango de visión y vuelve - Síntomas: Entidades invisibles / fantasma / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC, Solo yo / Cuándo: Al conectar o tras un mantenimiento, Al moverse o cambiar de zona - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: enviar “listo” al terminar la carga, o guardar los paquetes recibidos durante la carga y procesarlos después. Servidor: enviar la información del entorno solo después de recibir “listo”. - Cifras de referencia: Si dos clientes cargan a la vez en la misma computadora, o el que carga está en una ventana en segundo plano, se reparten la CPU y el disco y además su procesamiento queda limitado, así que esa carga puede tardar varias veces más. Si el servidor procesa las entradas más rápido, el mismo bug también sale a la luz. - En el gráfico: Alto solo en algunos (Tiempo de carga por cliente, mensajes descartados durante la carga) - Dónde mirar: Comparar el número y el tipo de mensajes que el cliente recibió y descartó durante la carga, y la hora en que terminó la carga, con la hora en que el servidor envió los mensajes de aparición. Es fácil de reproducir cargando dos clientes a la vez en la misma computadora o dejando el que carga en una ventana en segundo plano - Se confirma si: El servidor envió el mensaje de aparición del NPC invisible, llegó antes de terminar la carga, y a esa hora aumentaron los mensajes descartados. Solo ocurre en el cliente que tarda más en cargar - Se descarta si: Si el mensaje de aparición llegó después de terminar la carga y aun así no se ve, apunta a “Pérdida del snapshot de referencia (baseline)” o “Confusión por reutilización de IDs de entidad”. Si el servidor ni siquiera envió el mensaje de ese NPC, apunta a “Condición de carrera en el registro de visibilidad (AOI)” o “Diferencias de canal, instancia o phasing” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [NetworkConfig class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkConfig.html) · Unity · SpawnTimeout: los mensajes de entidades que aún no se han creado se retienen y, si no se crean a tiempo, se descartan - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · Los actores que dejan de ser relevantes se borran en el cliente y, cuando vuelven a serlo, se replican de nuevo #### pt-aoi-race · Condición de carrera en el registro de visibilidad (AOI) · Interest-management race on enter/leave Si el momento en que un personaje se registra en la cuadrícula de visibilidad coincide con el momento en que un NPC cambia de celda, el mensaje de aparición de ese NPC puede perderse. - Por qué → Efecto → En pantalla: El procesamiento de una entrada, un cambio de canal o una teletransportación coincide en el mismo instante con el movimiento de un NPC → Ese NPC queda fuera del cálculo de “entidades que ahora son visibles” → Solo unos pocos NPC concretos no se ven, o sigue ahí un NPC que ya se fue - Síntomas: Entidades invisibles / fantasma / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC, Solo yo / Cuándo: Al moverse o cambiar de zona, De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Procesar las actualizaciones de visibilidad en un solo hilo y en un orden fijo, volver a sincronizar periódicamente toda la “lista de visibles”. - En el gráfico: Picos aleatorios (Diferencias entre la lista de visibles del servidor y la lista de entidades del cliente) - Dónde mirar: Registrar en el servidor, con el número de tick, el registro en la cuadrícula de visibilidad, los cambios de celda de las entidades y el envío de mensajes de aparición y desaparición, y comparar periódicamente la “lista de visibles” del servidor con la lista que tiene el cliente - Se confirma si: El NPC que falta cambió de celda en el mismo tick en que se procesó la entrada o la teletransportación de ese personaje, y no hay registro de envío de su mensaje de aparición - Se descarta si: Si el mensaje de aparición se envió pero el cliente no lo recibió o lo descartó, el problema está en la entrega (“Pérdida de la ráfaga de mensajes de aparición al entrar”, “Mensajes de aparición descartados durante la carga”). Si siempre falta el mismo NPC, apunta a “Diferencias de canal, instancia o phasing” u “Opciones de visualización distintas” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Replication Graph in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/replication-graph-in-unreal-engine) · Epic Games · Los MMORPG, entre otros, dividen el mundo en una cuadrícula con una lista de actores por celda y envían según la celda en la que está el cliente - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · La relevancia se decide por conexión, y los actores que dejan de ser relevantes se borran en el cliente #### pt-baseline · Pérdida del snapshot de referencia (baseline) · Lost baseline for delta compression Cuando el servidor envía “solo lo que cambió desde la última vez”, si se pierde la información completa que se envía una vez al principio (la referencia), los cambios posteriores no se pueden aplicar. - Por qué → Efecto → En pantalla: El paquete con la información completa (referencia) de una entidad se pierde o se descarta antes de procesarse → El cliente no tiene sobre qué aplicar los cambios siguientes y los ignora → Esa entidad no se ve, o aparece de repente mucho después - Síntomas: Entidades invisibles / fantasma, Teletransporte / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC, Solo yo / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: reenviar siempre la referencia hasta recibir el acuse de recibo (ACK), y generar los cambios solo respecto a referencias que el cliente confirmó haber recibido. Cliente: enviar el acuse de recibo (ACK) de la referencia solo después de aplicarla, y al recibir cambios de una entidad desconocida, volver a pedirla al servidor. - En el gráfico: Picos aleatorios (Cambios recibidos para entidades desconocidas) - Dónde mirar: Cotejar las veces que el cliente descartó cambios recibidos sin referencia, y los ID de esas entidades, con la hora en que el servidor envió la referencia de esa entidad y la hora en que recibió el ACK. Reproducirlo en un entorno de desarrollo añadiendo pérdida (loss de tc netem, porcentaje de pérdida de paquetes de la emulación de red de Unreal) - Se confirma si: Para la entidad invisible, el servidor envió la referencia y, aunque no recibió el ACK, siguió enviando solo cambios, que el cliente descartó - Se descarta si: Si la referencia recibió su ACK y se aplicó en el cliente y aun así no se ve, apunta a “Pérdida del mensaje de desaparición (entidad fantasma)” o “Confusión por reutilización de IDs de entidad” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Snapshot Compression](https://gafferongames.com/post/snapshot_compression/) · Gaffer On Games · Los cambios solo deben generarse respecto a una referencia (baseline) que el otro lado confirmó (ack), y el estado inicial se envía aparte - [Quake III Arena source: code/server/sv_snapshot.c](https://raw.githubusercontent.com/id-Software/Quake-III-Arena/master/code/server/sv_snapshot.c) · id Software · Se comprime en delta respecto al snapshot que confirmó el cliente, y si esa referencia es demasiado antigua se envía el snapshot completo - [tc-netem(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-netem.8.html) · iproute2 · Herramienta de pruebas que imita una red real añadiendo latencia y jitter (delay TIME JITTER) y pérdida (loss random PERCENT) a los paquetes salientes - [Using Network Emulation in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-network-emulation-in-unreal-engine) · Epic Games · Pruebas con latencia mínima y máxima y porcentaje de pérdida de paquetes en el servidor y el cliente; en la consola se configura con comandos como NetEmulation.PktLag #### pt-ghost · Pérdida del mensaje de desaparición (entidad fantasma) · Missed despawn (ghost entity) A la inversa, si se pierde el mensaje de “ha desaparecido”, un NPC o jugador que ya murió o se fue sigue solo en tu pantalla. - Por qué → Efecto → En pantalla: Se pierde o llega desordenado el mensaje de muerte, de salida o de abandono del rango de visión → El cliente cree que esa entidad sigue ahí → Monstruos que no reaccionan al golpearlos, jugadores que ya se fueron pero siguen ahí de pie - Síntomas: Entidades invisibles / fantasma / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC, Solo yo / Cuándo: De vez en cuando, al azar, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: enviar periódicamente la “lista de lo que se ve ahora”. Cliente: borrar las entidades que no estén en la lista, ocultar las entidades que deberían moverse y llevan mucho tiempo sin actualizarse. - En el gráfico: Picos aleatorios (Entidades que solo quedan en el cliente) - Dónde mirar: Comparar la “lista de lo que se ve ahora” que envía el servidor con la lista de entidades del cliente, contar las que solo existen en el cliente y cotejar por ID de entidad los logs de envío y recepción de los mensajes de desaparición - Se confirma si: El servidor envió el mensaje de desaparición de la entidad fantasma pero no hay registro de recepción en el cliente, o la desaparición llegó antes que la aparición y el orden quedó invertido - Se descarta si: Si la entidad también sigue en la lista de visibles del servidor, el servidor no la limpió. Si ocurre justo después de aparecer una entidad nueva con el mismo ID, apunta a “Confusión por reutilización de IDs de entidad” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · Los actores dinámicos que dejan de ser relevantes se eliminan en el cliente - [Object visibility (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/basics/object-visibility.html) · Unity · Si se oculta una entidad, ese cliente la elimina (despawn) #### pt-spawn-burst · Pérdida de la ráfaga de mensajes de aparición al entrar · Initial spawn burst lost (unreliable channel, receive buffer, fragmentation) En cuanto el personaje entra en una zona, el servidor envía de golpe los datos de aparición de decenas o cientos de entidades cercanas. Si se envían por un canal no confiable (unreliable), o si el búfer de recepción se desborda mientras el cliente no lee el socket porque está cargando, una parte se pierde y no vuelve a llegar. - Por qué → Efecto → En pantalla: Justo después de entrar, los datos de aparición llegan todos en un instante → El cliente que está cargando lee el socket tarde y se desborda el búfer de recepción del SO, o un paquete UDP grande se fragmenta y basta perder un fragmento para perderlo entero. En un canal no confiable, tampoco se reenvía → Solo en el cliente que carga más lento faltan algunos NPC. Al salir del rango de visión y volver, aparecen - Síntomas: Entidades invisibles / fantasma / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC, Solo yo / Cuándo: Al conectar o tras un mantenimiento, Al moverse o cambiar de zona - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: enviar los mensajes de aparición y desaparición siempre por un canal confiable con reenvío garantizado, y repartir en partes la información inicial. Cliente: recibir en un hilo separado de la carga, aumentar el tamaño del búfer de recepción. - Cifras de referencia: El tamaño predeterminado del búfer de recepción UDP en el cliente varía según el SO, pero suele ser de decenas a cientos de KB. Si los datos de entrada de una ciudad llena de gente superan ese tamaño, basta con que la carga impida leer el socket un momento para que se desborde. - En el gráfico: Avalancha tras la apertura (Volumen recibido justo después de entrar, mensajes de aparición perdidos) - Dónde mirar: Comparar el número de mensajes de aparición que envió el servidor justo después de la entrada con los que recibió el cliente, y ver por qué canal (confiable o no confiable) se enviaron. En una captura de paquetes del lado del servidor, ver el volumen enviado a ese jugador justo después de entrar y los paquetes fragmentados (filtro de Wireshark ip.flags.mf == 1 || ip.frag_offset > 0) - Se confirma si: Se recibieron menos de los que se enviaron, los que faltan se agrupan en la ráfaga justo después de entrar, y se enviaron por un canal no confiable o los paquetes grandes estaban fragmentados. Ocurre más en el cliente que carga más lento - Se descarta si: Si se enviaron y se recibieron los mismos y aun así no se ve, se descartaron después de recibirlos (“Mensajes de aparición descartados durante la carga”) o es un problema del cálculo de visibilidad. Si faltan en cualquier momento, sin relación con la entrada, apunta a pérdida en la conexión - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Basta perder un fragmento de un paquete fragmentado para perderlo entero - [UDP vs. TCP](https://gafferongames.com/post/udp_vs_tcp/) · Gaffer On Games · UDP no garantiza la entrega ni el orden, así que hay que detectar los paquetes perdidos y reenviarlos uno mismo - [Socket.ReceiveBufferSize Property](https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.receivebuffersize) · Microsoft · El tamaño predeterminado del búfer de recepción del socket varía según el SO - [Display Filter Reference: Internet Protocol Version 4](https://www.wireshark.org/docs/dfref/i/ip.html) · Wireshark · Con ip.flags.mf (More fragments) e ip.frag_offset (Fragment Offset) se filtran los paquetes IP fragmentados #### pt-id-reuse · Confusión por reutilización de IDs de entidad · Entity ID reused without a generation counter Si el servidor reutiliza el mismo ID de entidad cuando reaparece un NPC muerto, un cliente que se perdió el mensaje de desaparición en ese intervalo confunde el NPC nuevo con el antiguo. - Por qué → Efecto → En pantalla: Un NPC muere y reaparece con el mismo ID de entidad → El cliente que se perdió el mensaje de desaparición ignora el mensaje de aparición porque “ya conoce esa entidad”, o la deja en estado de muerta → En una sola pantalla el NPC falta o se ve caído en el suelo, y a veces se ve con el aspecto de otro NPC - Síntomas: Entidades invisibles / fantasma / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC, Solo yo / Cuándo: De vez en cuando, al azar, Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: añadir un número de generación al ID de entidad para distinguir las reutilizaciones. Cliente: al recibir un mensaje de aparición con un ID conocido, borrar la entidad existente y crearla de nuevo. - En el gráfico: Picos aleatorios (Mensajes de aparición con un ID ya conocido) - Dónde mirar: Registrar en el servidor la hora de creación y de borrado de cada ID de entidad (con el número de generación, si existe), y contar las veces que el cliente recibió mensajes de aparición con un ID que ya conocía y los borrados y recreaciones que la actualización de visibilidad trató como “sin cambios” - Se confirma si: El NPC que no se ve o se ve caído tiene el mismo ID que un NPC que acababa de morir, y en ese intervalo ese cliente no recibió el mensaje de desaparición, o el servidor no envió ni el de desaparición ni el de aparición - Se descarta si: Si los ID llevan número de generación y también se usa en las comparaciones, no es esta causa. Si no se ve aunque el ID no sea reutilizado, apunta a la pérdida del mensaje de aparición - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Para saber más: También ocurre en el lado del servidor. Si la lista de entidades visibles se compara solo por ID, un NPC que murió y reapareció con el mismo ID entre dos actualizaciones de visibilidad se toma como “sin cambios”, y no se envía ni el mensaje de desaparición ni el de aparición. Si cada jugador actualiza la visibilidad en un momento distinto, solo lo sufren los clientes que coinciden con ese instante. - Fuentes: - [Entity struct (Entities 1.3)](https://docs.unity3d.com/Packages/com.unity.entities@1.3/api/Unity.Entities.Entity.html) · Unity · Una Entity se compone de un Index y un número de generación (Version), con lo que se distingue si un Index reutilizado sigue siendo válido - [NetworkConfig class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkConfig.html) · Unity · RecycleNetworkIds y NetworkIdRecycleDelay: los ID de red se reutilizan después de dejarlos libres cierto tiempo #### pt-port-collision · Colisión de puertos UDP fijos · Two clients bound to the same local UDP port Si el cliente está hecho para usar un puerto local fijo, el segundo cliente de la misma computadora no puede usar ese puerto o se reparte los paquetes con el primero. - Por qué → Efecto → En pantalla: Los dos clientes intentan abrir el mismo puerto UDP local (compartido a la fuerza con una opción de reutilización) → El SO entrega los paquetes entrantes a uno solo de los sockets, o no garantiza cuál los recibe. El router y el servidor también ven a los dos clientes con la misma dirección → Uno de ellos no recibe los paquetes del mundo: no ve los NPC ni a otros jugadores, o se desconecta - Síntomas: Entidades invisibles / fantasma, Desconexión, No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC / Cuándo: Al conectar o tras un mantenimiento, Siempre - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: dejar que el SO elija automáticamente el puerto local (bind al puerto 0). Servidor: distinguir las conexiones con un token de sesión emitido para cada una. - En el gráfico: Alto solo en algunos (Paquetes recibidos por cliente) - Dónde mirar: En la computadora del jugador, con los dos clientes abiertos, ver en el Símbolo del sistema con netstat -ano -p udp el puerto UDP local que abrió cada proceso del juego (PID). En el lado del servidor, comprobar si las dos sesiones llegan con la misma IP pública y el mismo puerto - Se confirma si: Los dos procesos del juego están vinculados al mismo puerto local, o en el servidor las dos sesiones aparecen con la misma IP y el mismo puerto. Con un solo cliente abierto, todo va bien - Se descarta si: Si los dos clientes usan puertos locales distintos y aun así uno falla, apunta a “Bug de sesiones identificadas por IP o dispositivo” o a “Restricciones al multicliente” - Se verifica con: En el entorno del jugador - Fuentes: - [Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE](https://learn.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse) · Microsoft · Si se hace un segundo bind al mismo puerto con SO_REUSEADDR, el puerto queda secuestrado y no se sabe qué socket recibirá los paquetes - [bind function (winsock.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-bind) · Microsoft · Hacer bind al puerto 0 asigna un puerto único del rango de puertos dinámicos (49152–65535) - [netstat](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/netstat) · Microsoft · -a muestra los puertos TCP y UDP, -n las direcciones en forma numérica, -o el ID de proceso (PID) y -p udp solo UDP #### pt-session-key · Bug de sesiones identificadas por IP o dispositivo · Session keyed by IP or machine ID Si el servidor o un servidor intermedio distingue las conexiones por IP o por ID de dispositivo, toma los dos clientes de la misma computadora (la misma IP pública) por una sola persona. - Por qué → Efecto → En pantalla: La tabla de sesiones se indexa por IP o por IP + ID de dispositivo → Los datos del segundo cliente sobrescriben la primera sesión o se mezclan con ella → Uno no ve los NPC y el otro se desconecta o recibe datos ajenos - Síntomas: Entidades invisibles / fantasma, Desconexión / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC, Misma casa, Una región o un ISP / Cuándo: Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: hacer que tanto el servidor como los servidores intermedios distingan cada conexión con un token de sesión único; corregirlo sin falta, porque también lo sufren varias personas de una misma casa (detrás del NAT del router) y los usuarios de redes móviles en las que el ISP reparte una IP entre muchos abonados (CGNAT). Cliente: usar un token de sesión propio para cada cliente abierto. - En el gráfico: Alto solo en algunos (Sesiones simultáneas desde la misma IP pública, sesiones sobrescritas) - Dónde mirar: Registrar en los logs del servidor y de los servidores intermedios la clave usada para buscar la sesión, el token de sesión y la IP y el puerto del cliente, y ver si la sesión existente cambió en el momento en que entró una segunda conexión desde la misma IP. Se reproduce abriendo dos clientes uno tras otro en la misma computadora - Se confirma si: En el momento en que se conecta el segundo cliente cambian la dirección o los datos del personaje de la primera sesión, y otros jugadores detrás del mismo router o de la misma red móvil (CGNAT) sufren las mismas desconexiones - Se descarta si: Si las dos sesiones de la misma IP se mantienen por separado con tokens distintos, no es esta causa. Si los dos procesos usan el mismo puerto local, apunta a “Colisión de puertos UDP fijos” - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [RFC 6269: Issues with IP Address Sharing](https://www.rfc-editor.org/rfc/rfc6269) · IETF · Cuando varios abonados comparten una dirección IPv4 mediante NAT o CGN, no se puede distinguir a los usuarios solo por la IP #### pt-multiclient · Restricciones al multicliente · Multi-client restriction policy Si el módulo de seguridad o una política del servidor limitan los clientes de una misma computadora, el segundo cliente no puede abrirse o conectarse, o se desconecta el que se abrió primero. Algunos juegos solo bloquean funciones del cliente adicional. - Por qué → Efecto → En pantalla: El módulo de seguridad detecta una ejecución duplicada, o el servidor limita las conexiones adicionales desde el mismo dispositivo → Se rechaza la segunda ejecución o conexión, o se corta una de las dos. En raras ocasiones solo se bloquean algunas funciones del cliente adicional → No conecta, o uno de los dos se desconecta. En los juegos que solo bloquean funciones, uno de los dos no ve los NPC o la tienda - Síntomas: No conecta / carga infinita, Entidades invisibles / fantasma, Desconexión / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC / Cuándo: Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: si se limita, mostrar un mensaje claro, configurar una excepción para QA en el módulo de seguridad. Servidor: configurar también una excepción para QA en el límite de conexiones por dispositivo. - En el gráfico: Alto solo en algunos (Rechazos y desconexiones por motivo (conexión duplicada)) - Dónde mirar: Ver el mensaje que aparece al abrir el segundo cliente y el mensaje de desconexión del que se abrió primero. Comprobar si los logs de rechazos y expulsiones del servidor registran códigos de motivo como conexión duplicada o mismo dispositivo - Se confirma si: Al abrir o conectar el segundo cliente aparece un mensaje de rechazo, o el primero se desconecta por conexión duplicada, y con un solo cliente abierto no hay problema - Se descarta si: Si los dos se conectan sin motivo de rechazo ni desconexión pero solo uno no ve los NPC, apunta a “Colisión de puertos UDP fijos”, “Bug de sesiones identificadas por IP o dispositivo” o a causas de carga o de visualización - Se verifica con: En el entorno del jugador - Fuentes: - [CreateMutexW function (synchapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexw) · Microsoft · Si el mutex con nombre ya existe, devuelve ERROR_ALREADY_EXISTS, lo que se usa para detectar ejecuciones duplicadas y limitar a una sola instancia #### pt-background · Procesamiento limitado de las ventanas en segundo plano · Background window throttling Cuando la ventana del cliente está en segundo plano, el juego, el motor y el SO reducen sus frames y su procesamiento. Los paquetes recibidos no se procesan a tiempo y se acumulan o desbordan. - Por qué → Efecto → En pantalla: Límite de frames en segundo plano de las opciones del juego o del driver gráfico (p. ej., el driver de NVIDIA permite elegir entre 20 y 200 por segundo), ahorro de energía, ajuste del motor que detiene el juego en segundo plano. El SO también da prioridad de CPU y GPU a la ventana en primer plano → Se procesan menos paquetes por frame, la cola crece y, si el búfer de recepción se desborda, se descartan → Al traer la ventana al frente todo aparece de golpe, o algunos NPC no llegan a verse nunca - Síntomas: Entidades invisibles / fantasma, Cámara rápida, Desconexión / Factores: Detención, Pérdida de paquetes - A quién: Solo un cliente en tu PC / Cuándo: Tras un rato inactivo, Siempre - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Externo (Externo) - Tareas (Equipo de desarrollo): Seguir recibiendo de la red en un hilo separado del bucle del juego, garantizar un procesamiento mínimo también en segundo plano, activar el ajuste de ejecución en segundo plano del motor (runInBackground en Unity). - Tareas (Externo): Indicar a los jugadores que desactiven el límite de frames en segundo plano del driver gráfico y el modo de ahorro de energía de su PC. - Cifras de referencia: En Unity, si runInBackground está desactivado, el bucle del juego se detiene en el instante en que la ventana pierde el foco. Si la recepción solo se hace en ese bucle, mientras tanto no se procesa ningún paquete. - En el gráfico: Hueco y luego ráfaga (Intervalo entre frames del cliente, paquetes procesados por frame) - Dónde mirar: En la misma computadora, poner una ventana delante y la otra detrás, intercambiar los papeles y comparar. Medir con PresentMon el intervalo entre frames de los dos procesos y, si hay logs del juego, ver el estado de foco de la ventana y los paquetes procesados en cada frame - Se confirma si: Solo con la ventana en segundo plano el intervalo entre frames crece mucho (si es el límite del driver, se queda plano en el intervalo que corresponde a los frames configurados) o el procesamiento se detiene, y al intercambiar las ventanas el problema pasa al otro cliente - Se descarta si: Si también ocurre en la ventana en primer plano, no es por el límite en segundo plano. Si siempre falla el mismo cliente, esté donde esté su ventana, apunta a “Opciones de visualización distintas” o a una diferencia de versión - Se verifica con: En el entorno del jugador - Fuentes: - [Application.runInBackground](https://docs.unity3d.com/ScriptReference/Application-runInBackground.html) · Unity · El valor predeterminado de runInBackground es false, y en ese caso la aplicación se pausa en segundo plano - [Manage 3D Settings (reference) — NVIDIA Control Panel Help](https://www.nvidia.com/content/Control-Panel-Help/vLatest/en-us/mergedProjects/nv3d/Manage_3D_Settings_(reference).htm) · NVIDIA · Background Application Max Frame Rate: limita los frames máximos de un juego en segundo plano a 20–200 por segundo - [Priority Boosts](https://learn.microsoft.com/en-us/windows/win32/procthread/priority-boosts) · Microsoft · Windows sube la prioridad del proceso de la ventana en primer plano por encima de la de los procesos en segundo plano - [PresentMon README](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README.md) · Intel · Herramienta que recoge, por aplicación, los tiempos de frame de CPU, GPU y pantalla de las aplicaciones gráficas de Windows #### pt-asset-lock · Conflictos por acceso simultáneo a archivos de caché o assets · Shared cache / asset file lock conflicts Si dos clientes escriben a la vez en la misma carpeta de caché o bloquean archivos, uno de ellos no puede cargar los modelos o texturas de los NPC. - Por qué → Efecto → En pantalla: Los dos clientes escriben a la vez en los archivos de caché o de parches de la misma carpeta de instalación → Falla el bloqueo del archivo o se lee un archivo a medio escribir, y la carga falla → NPC con el nombre visible pero sin modelo, o transparentes - Síntomas: Entidades invisibles / fantasma / Factores: Detención - A quién: Solo un cliente en tu PC / Cuándo: Al conectar o tras un mantenimiento, Al moverse o cambiar de zona - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Usar una carpeta de caché por cliente, reintentar si falla el bloqueo del archivo, mostrar al menos un modelo por defecto si falla la carga. - En el gráfico: Alto solo en algunos (Fallos de carga de assets por cliente) - Dónde mirar: En la computadora del jugador, filtrar con Process Monitor solo las rutas de las carpetas de instalación y de caché del juego y ver el resultado de las aperturas y escrituras de archivos de los dos procesos. Si hay logs del cliente, buscar fallos de carga de assets y el código de error de apertura de archivo (ERROR_SHARING_VIOLATION) - Se confirma si: La apertura del archivo del modelo invisible terminó en una infracción de uso compartido o en un fallo de bloqueo, y a la misma hora el otro cliente estaba escribiendo ese archivo. Desaparece con un solo cliente abierto o separando las carpetas de instalación y de caché - Se descarta si: Si el mismo modelo tampoco se ve con un solo cliente abierto, apunta a archivos dañados o a “Desajuste de versión o datos del cliente”. Si el archivo se abrió bien pero no se dibuja, apunta a “Fallo de streaming por falta de memoria o VRAM” - Se verifica con: En el entorno del jugador - Fuentes: - [Creating and Opening Files](https://learn.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files) · Microsoft · Un archivo abierto sin modo de uso compartido no lo pueden abrir otros procesos, que reciben ERROR_SHARING_VIOLATION - [Process Monitor](https://learn.microsoft.com/en-us/sysinternals/downloads/procmon) · Microsoft · Registra en tiempo real la actividad del sistema de archivos, del registro y de los procesos, y permite filtrar por cualquier campo, como la ruta #### pt-vram · Fallo de streaming por falta de memoria o VRAM · Memory / VRAM exhaustion Si dos clientes se reparten la memoria gráfica, no queda sitio para cargar los modelos y texturas nuevos que hacen falta, y algunos no se dibujan. - Por qué → Efecto → En pantalla: Los dos clientes se reparten la VRAM y la RAM. El SO también puede reducir primero la cuota de memoria gráfica de la ventana en segundo plano → El motor no consigue cargar modelos y texturas nuevos, o los descarga y vuelve a cargar sin parar → Los NPC aparecen tarde, borrosos o no aparecen, tirones - Síntomas: Entidades invisibles / fantasma, Tirones / Factores: Detención - A quién: Solo un cliente en tu PC / Cuándo: Al moverse o cambiar de zona, Cuando se junta mucha gente - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Externo (Externo) - Tareas (Equipo de desarrollo): Ajustar la calidad automáticamente al presupuesto de memoria, mostrar un modelo sustituto si falla la carga. - Tareas (Externo): Indicar a quienes abren dos clientes a la vez que bajen la calidad gráfica o usen el modo de bajos requisitos, informar de la VRAM y la RAM recomendadas. - En el gráfico: Topa con el límite (Uso de memoria de GPU dedicada por proceso) - Dónde mirar: En la pestaña Detalles del Administrador de tareas de la computadora del jugador, añadir la columna de memoria de GPU dedicada y comparar la suma de los dos clientes con la VRAM de la tarjeta gráfica. En el juego, registrar el presupuesto (Budget) y el uso actual (CurrentUsage) que devuelve QueryVideoMemoryInfo de DXGI - Se confirma si: La suma de los dos clientes queda plana cerca de la capacidad de VRAM, y los fallos de carga de modelos y texturas se concentran en los momentos en que el uso actual supera el presupuesto. Desaparece al bajar la calidad o con un solo cliente abierto - Se descarta si: Si queda VRAM libre y aun así no se ve, apunta a “Conflictos por acceso simultáneo a archivos de caché o assets” o a “Opciones de visualización distintas” - Se verifica con: En el entorno del jugador - Fuentes: - [Residency (Direct3D 12)](https://learn.microsoft.com/en-us/windows/win32/direct3d12/residency) · Microsoft · El presupuesto de memoria de video puede reducirse mucho al cambiar a otra aplicación, y si se supera, la aplicación se detiene o falla la creación de recursos. Fuera del primer plano, tampoco se garantiza la reserva - [GPUs in the task manager](https://devblogs.microsoft.com/directx/gpus-in-the-task-manager/) · Microsoft · Añadiendo columnas en la pestaña Detalles del Administrador de tareas se ve el uso de memoria de GPU dedicada y compartida por proceso. La memoria de GPU dedicada es la VRAM de la tarjeta gráfica - [DXGI_QUERY_VIDEO_MEMORY_INFO structure (dxgi1_4.h)](https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_4/ns-dxgi1_4-dxgi_query_video_memory_info) · Microsoft · Budget (presupuesto de memoria de video que fija el SO) y CurrentUsage (uso actual de la aplicación). Si el uso supera el presupuesto, puede haber tirones #### pt-display-option · Opciones de visualización distintas · Different display settings Si opciones como el límite de personajes visibles, ocultar los nombres o modelos de los NPC o el modo de bajos requisitos son distintas en los dos clientes, cada uno ve cosas distintas. - Por qué → Efecto → En pantalla: Solo un cliente tiene activado el “límite de personajes cercanos visibles” o el modo de bajos requisitos → No se dibujan los NPC lejanos o de baja prioridad (es lo normal) → El NPC solo falta en uno de los dos - Síntomas: Entidades invisibles / fantasma / Factores: Detención - A quién: Solo un cliente en tu PC, Solo yo / Cuándo: Cuando se junta mucha gente, Siempre - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Indicar de forma visible que una entidad está oculta por una opción, separar los archivos de configuración por cliente para que no se mezclen. - En el gráfico: Alto solo en algunos (Entidades dibujadas en pantalla por cliente) - Dónde mirar: Comparar lado a lado el límite de personajes visibles, la ocultación de nombres y modelos y el modo de bajos requisitos de los dos clientes, y probar a igualar uno con el otro. Comprobar también si los dos clientes comparten un mismo archivo de configuración y se lo sobrescriben - Se confirma si: Al igualar la configuración las dos pantallas se ven iguales, y los NPC que no se veían eran entidades lejanas fuera del límite de visualización o de baja prioridad - Se descarta si: Si con la configuración igualada sigue faltando en uno de los dos, apunta a “Diferencias de canal, instancia o phasing” o a la pérdida del mensaje de aparición - Se verifica con: En el entorno del jugador - Fuentes: - [Changing the Quantity of Characters Displayed On-screen (FINAL FANTASY XIV UI Guide)](https://na.finalfantasyxiv.com/uiguide/faq/faq-other/setting_ch_quantity.html) · Square Enix · El ajuste de límite de visualización (Character and Object Quantity) regula cuántos personajes y objetos se dibujan en pantalla #### pt-version · Desajuste de versión o datos del cliente · Client version / data table mismatch Si el segundo cliente es otra instalación o no terminó de parchearse, no conoce los ID de NPC nuevos que envía el servidor y los ignora en silencio. - Por qué → Efecto → En pantalla: Una instalación en otra carpeta, o un cliente abierto en plena instalación de un parche → Si recibe un ID de NPC o de modelo desconocido, lo salta → Solo los NPC recién añadidos faltan en uno de los dos - Síntomas: Entidades invisibles / fantasma / Factores: Pérdida de paquetes - A quién: Solo un cliente en tu PC / Cuándo: Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Cliente: enviar la versión de datos al conectarse y, si recibe un ID desconocido, registrarlo en el log y mostrar algo en su lugar. Servidor: comprobar la versión de datos al conectarse y, si no coincide, rechazar la conexión e indicar que hay que parchear. - En el gráfico: Alto solo en algunos (ID desconocidos recibidos por versión del cliente) - Dónde mirar: Comparar la ruta del ejecutable de los dos clientes y la versión del cliente y de los datos que aparece en pantalla o en el log. En el juego, registrar la versión de datos enviada al conectarse y las veces que se saltaron ID de NPC o de modelo desconocidos - Se confirma si: Los dos clientes tienen versiones o carpetas de instalación distintas, el NPC que no se ve se añadió en un parche reciente, y en la instalación ya parcheada sí se ve - Se descarta si: Si la versión y la carpeta de instalación coinciden y aun así falta en uno de los dos, apunta a “Diferencias de canal, instancia o phasing” o a causas de carga o de entrega - Se verifica con: En el entorno del jugador - Fuentes: - [NetworkConfig class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkConfig.html) · Unity · Si ProtocolVersion es distinto no se comunican, y ForceSamePrefabs comprueba al conectarse si hay diferencias en la lista de prefabs #### pt-priority · Presupuesto de envío y prioridad por conexión · Per-connection bandwidth budget and priority Si el servidor limita lo que envía a cada conexión y empieza por lo más cercano, la conexión con un límite bajo recibe tarde, o nunca, los NPC lejanos. - Por qué → Efecto → En pantalla: En zonas concurridas, el servidor envía por orden de importancia dentro del límite de envío de cada conexión → Las conexiones con un ancho de banda estimado bajo (p. ej., la de una ventana en segundo plano que confirma tarde la recepción) aplazan una y otra vez las entidades del final de la lista → Los NPC lejanos se ven tarde, o no se ven, en uno solo de los clientes - Síntomas: Entidades invisibles / fantasma, Input lag / Factores: Latencia - A quién: Solo un cliente en tu PC, Una zona o un canal / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: subir con el tiempo la prioridad de las entidades aplazadas (evitar la inanición, starvation), garantizar un intervalo mínimo de actualización. Cliente: enviar los acuses de recibo a tiempo también en segundo plano, para que no baje el ancho de banda estimado. - En el gráfico: Sube con la carga (Entidades aplazadas por conexión, volumen enviado por conexión) - Dónde mirar: Registrar en el servidor, por conexión y por tick, los bytes enviados, el límite de envío (ancho de banda estimado), las entidades que no se pudieron enviar y se aplazaron, y el tiempo transcurrido desde el último envío de cada entidad. En Unreal, Networking Insights muestra el tamaño de los paquetes de cada conexión y las entidades replicadas que contienen - Se confirma si: El NPC que no se ve es una entidad aplazada durante mucho tiempo en esa conexión, el límite de esa conexión es más bajo que el de las demás, y las entidades aplazadas aumentan cuanta más gente hay - Se descarta si: Si no hay entidades aplazadas y ese NPC se envió a tiempo, el problema está en una etapa posterior al envío (búfer de recepción, carga, opciones de visualización). Si todas las conexiones están pegadas al límite, es un problema del volumen total de envío del servidor o del diseño de visibilidad - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Cuando el ancho de banda se satura, los actores que se replican se eligen según su prioridad (distancia, línea de visión, tiempo desde la última replicación). No todos los actores se replican siempre - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Prioridad acumulada: las entidades que no cupieron en este paquete entran primero en el siguiente, y el límite de ancho de banda se ajusta en tiempo real - [Networking Insights in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-insights-in-unreal-engine) · Epic Games · Muestra, por conexión, el tamaño de los paquetes enviados y recibidos y las entidades y propiedades replicadas que contienen #### pt-clock-hold · Entidades retenidas por errores en la estimación del reloj · Clock estimate error holds or discards entities Si la hora del servidor que estima el cliente es incorrecta, la información de entidades que acaba de llegar se retiene “porque todavía es futuro” o se descarta “porque es demasiado antigua”. - Por qué → Efecto → En pantalla: La estimación de la hora del servidor de uno de los clientes se desvía mucho (medida durante la carga, tras reactivarse del ahorro de energía) → La hora de referencia de la interpolación y la hora de la información de entidades no coinciden → Las entidades aparecen tarde o se ven quietas - Síntomas: Entidades invisibles / fantasma, Tirones / Factores: Latencia - A quién: Solo un cliente en tu PC / Cuándo: Tras un rato inactivo, Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Repetir periódicamente la sincronización horaria y restablecerla de inmediato si la diferencia es grande, no usar valores medidos durante la carga o justo después de reactivarse del ahorro de energía. - En el gráfico: Alto solo en algunos (Error de estimación de la hora del servidor por cliente) - Dónde mirar: Registrar en el cliente la hora del servidor estimada, el RTT, la hora en que se repitió la sincronización horaria y las veces que se retuvo o descartó información de entidades. Probar a reproducirlo justo después de una carga o de reactivarse del ahorro de energía - Se confirma si: Solo en el cliente afectado el error de estimación supera el umbral de restablecimiento (hardResetThresholdSec en Unity, 0.2 s por defecto), hay registros de información de entidades retenida por ser futura o descartada por ser pasada, y al repetir la sincronización horaria todo vuelve a la normalidad de inmediato - Se descarta si: Si el error de estimación es pequeño y aun así aparecen tarde, apunta a “Presupuesto de envío y prioridad por conexión” o a causas de carga - Se verifica con: Requiere logs y métricas del servidor o el cliente del juego - Fuentes: - [NetworkTimeSystem class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkTimeSystem.html) · Unity · Si la diferencia de tiempo supera hardResetThresholdSec (0.2 s por defecto), se fuerza el ajuste; normalmente se corrige poco a poco con adjustmentRatio, acelerando o frenando - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · LocalTime va por delante del servidor y ServerTime por detrás. En los mensajes que llegan tarde, el tiempo de espera puede ser negativo ### Causas raíz de la retransmisión TCP (causas: 20) #### rt-wireless · Pérdida en el tramo inalámbrico · Wi-Fi / cellular link loss El Wi-Fi y las redes móviles reintentan varias veces la transmisión en el tramo inalámbrico y, si aun así no lo consiguen, descartan el paquete. TCP vuelve a enviar ese paquete bastante después. - Por qué → Efecto → En pantalla: La señal es débil o hay muchas interferencias, y las transmisiones en el tramo inalámbrico fallan una tras otra → Al superar el límite de reintentos del dispositivo inalámbrico (normalmente de unos pocos a algo más de diez), el paquete se descarta → Congelamiento mientras dura la espera de la retransmisión TCP; los paquetes siguientes aguardan en el búfer de recepción y luego llega todo en cámara rápida - Síntomas: Congelamiento, Cámara rápida, Teletransporte / Factores: Pérdida de paquetes, Jitter - A quién: Solo yo, Misma casa / Cuándo: De vez en cuando, al azar, Al moverse o cambiar de zona - Responsable principal: Externo (Externo) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de servidor (Equipo de desarrollo), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: activar TCP_NODELAY (con Nagle activado, RACK no tiene paquetes posteriores con los que detectar la pérdida), no acumular las actualizaciones de estado mientras la retransmisión bloquea el envío y mandar solo la más reciente (limitar con TCP_NOTSENT_LOWAT lo que se acumula en el kernel). Cliente: activar TCP_NODELAY (las pérdidas en el sentido de los inputs del jugador las recupera el SO del cliente), mostrar en pantalla el estado de la red cuando se concentran las pérdidas o el ping se dispara. - Tareas (Equipo de infraestructura): Acelerar la recuperación de pérdidas con RACK-TLP (el servidor no puede evitar la pérdida inalámbrica; lo único que puede hacer es recuperarse antes), comprobar que no se hayan cambiado los valores predeterminados de los Linux recientes: net.ipv4.tcp_recovery=1 (RACK) y net.ipv4.tcp_early_retrans=3 (TLP). - Tareas (Externo): Indicar a los jugadores que usen conexión por cable o las bandas de 5 GHz o 6 GHz, y que cambien la ubicación o el canal del router. - Cifras de referencia: Con un 1% de pérdida inalámbrica, desaparece 1 de cada 100 paquetes del juego. Si se reciben 10 por segundo, hay un tirón aproximadamente cada 10 segundos. Sin RACK-TLP, cada pérdida detiene la conexión durante un RTO (ping + 200 ms o más). - En el gráfico: Alto solo en algunos (Tasa de retransmisión por conexión, RTT (ping) por conexión) - Dónde mirar: Desde la computadora del jugador, enviar cientos de pings a la dirección del router (gateway) y al servidor del juego, comparar la pérdida y la dispersión de la latencia, y repetir la medición con cable o con datos móviles. En el servidor, retrans y rtt (media/desviación) de la conexión de ese jugador con ss -ti - Se confirma si: El ping al router ya muestra pérdida o latencia irregular, que desaparece al pasar a cable. Desde el servidor, solo la conexión de ese jugador tiene retrans y desviación del RTT altas - Se descarta si: Si hasta el router todo está limpio y la pérdida empieza más allá, apunta al ISP o a la ruta (“Desbordamiento de la cola en el cuello de botella (pérdida por congestión)”, “Cambio de ruta o ruta ECMP defectuosa”). Si empeoran a la vez varios jugadores del mismo ISP, revisar primero el tramo del ISP - Se verifica con: En el entorno del jugador - Para saber más: Los reintentos del dispositivo inalámbrico generan jitter (varios ms por reintento), y solo hay pérdida cuando se supera el límite de reintentos. Por eso, a medida que empeora la calidad de la señal, los síntomas crecen en este orden: “jitter → congelamientos ocasionales → congelamientos frecuentes”. Al pasar de un router (AP) a otro (roaming) se pueden perder paquetes seguidos durante un intervalo de decenas de ms a varios segundos. Las redes móviles hacen muchos reintentos en el tramo con la estación base, así que el problema suele verse como picos de latencia de cientos de ms, y la pérdida es menos frecuente. - Casos reales: ffxiv-2021 - Fuentes: - [net/wireless/core.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/wireless/core.c?h=v6.12) · Linux kernel · Límite de reintentos predeterminado de la pila inalámbrica de Linux: 7 para tramas cortas y 4 para tramas largas (dot11ShortRetryLimit, dot11LongRetryLimit) - [RFC 3481: TCP over Second (2.5G) and Third (3G) Generation Wireless Networks](https://www.rfc-editor.org/rfc/rfc3481) · IETF · En las redes móviles, gracias a los reintentos de la capa de enlace hay poca pérdida IP, pero esa recuperación aparece como jitter y picos de latencia - [Wi-Fi roaming support in Apple devices](https://support.apple.com/guide/deployment/wi-fi-roaming-support-dep98f116c0f/web) · Apple · Al cambiar de AP no se pueden enviar datos hasta que termina la autenticación con el nuevo AP, y en entornos 802.1X puede tardar unos segundos - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · Definición de RACK (detección de pérdidas basada en el tiempo) y TLP (retransmisión del paquete final) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_recovery: 0x1 por defecto (RACK); tcp_early_retrans: 3 por defecto (TLP activado); TCP_NOTSENT_LOWAT y tcp_notsent_lowat limitan la cantidad de datos aún sin enviar - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_NODELAY desactiva el algoritmo de Nagle y envía enseguida incluso los datos pequeños - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · RTO mínimo: TCP_RTO_MIN = 200 ms - [misc/ss.c](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/misc/ss.c?h=v6.12.0) · iproute2 · ss -ti muestra retrans:retransmisiones en curso/total acumulado y rtt:RTT/desviación del RTT (rttvar) #### rt-queue-drop · Desbordamiento de la cola en el cuello de botella (pérdida por congestión) · Tail drop at a congested bottleneck Cuando se llena la cola del punto más estrecho, como el router, la interconexión entre ISP o el enlace del centro de datos, los paquetes que llegan se descartan. - Por qué → Efecto → En pantalla: El video, las descargas o el tráfico de otras personas llenan el cuello de botella → Mientras la cola está llena, los paquetes que llegan se descartan uno tras otro (tail drop). Los que no se descartan también esperan al final de una cola llena → Desaparecen varios paquetes a la vez: congelamiento largo seguido de cámara rápida, frecuente por la noche - Síntomas: Congelamiento, Cámara rápida, Rubber banding / Factores: Pérdida de paquetes, Latencia - A quién: Misma casa, Una región o un ISP, Todo el servidor / Cuándo: Horas pico de la noche, Cuando se junta mucha gente - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Externo (Externo), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Mostrar en pantalla el estado de la red cuando se concentran las pérdidas o el ping se dispara (avisar de que puede haber una transferencia grande en la misma conexión). - Tareas (Equipo de infraestructura): Asegurar margen en los enlaces del centro de datos, revisar los contadores de descartes de cola (output drops) de nuestros enlaces y puertos de switch, desviar el tráfico por otros enlaces o por otro peering cuando el tramo del ISP esté congestionado. - Tareas (Externo): Indicar a los jugadores que usen SQM en el router (fq_codel, CAKE) y ECN (para que se reduzca la velocidad antes de que la cola se desborde), pedir al ISP que amplíe la capacidad del cuello de botella. - Cifras de referencia: En el momento en que la cola se desborda, desaparece de golpe buena parte de los paquetes que llegan durante decenas de ms. Como es fácil perder paquetes seguidos e incluso sus retransmisiones, a menudo se llega hasta el RTO. - En el gráfico: Alto solo a ciertas horas (Tasa de retransmisión, RTT (ping)) - Dónde mirar: Tasa de retransmisión del servidor (incremento de TcpRetransSegs ÷ TcpOutSegs con nstat ejecutado cada minuto) y RTT por conexión, desglosados por región, ISP y franja horaria, junto con los descartes de salida (ifOutDiscards) de nuestros enlaces y puertos de switch. Comparar un mtr hacia la región afectada en horas pico y en horas tranquilas - Se confirma si: La tasa de retransmisión sube solo en el pico de la noche, y el RTT sube justo antes de la pérdida (la cola llenándose). En el mtr, solo en horas pico aumentan juntas la pérdida y la latencia desde un salto concreto hasta el final - Se descarta si: Si el RTT no sube justo antes de la pérdida, apunta a “Descarte del exceso por un policer”. Si la pérdida es parecida a cualquier hora, a “Errores físicos (cables, transceptores ópticos o conectores defectuosos)” o “Cambio de ruta o ruta ECMP defectuosa” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Casos reales: riot-direct-2015 - Fuentes: - [RFC 7567: IETF Recommendations Regarding Active Queue Management](https://www.rfc-editor.org/rfc/rfc7567) · IETF · Explicación de que el tail drop mantiene la cola llena durante mucho tiempo, lo que aumenta la latencia y concentra las pérdidas, y recomendación de usar AQM - [RFC 8290: The Flow Queue CoDel Packet Scheduler and Active Queue Management Algorithm](https://www.rfc-editor.org/rfc/rfc8290) · IETF · fq_codel: reduce el bufferbloat manteniendo las colas cortas con una cola por flujo y AQM - [RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP](https://www.rfc-editor.org/rfc/rfc3168) · IETF · ECN: avisa de la congestión con una marca en la cabecera IP, sin descartar el paquete - [Smart Queue Management](https://www.bufferbloat.net/projects/cerowrt/wiki/Smart_Queue_Management/) · Bufferbloat.net · SQM: combina planificación por flujo, gestión de la longitud de la cola (AQM) y shaping - [Cake](https://www.bufferbloat.net/projects/codel/wiki/Cake/) · Bufferbloat.net · CAKE: SQM para routers que combina un shaper con una gestión de colas de la familia fq_codel - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · TcpRetransSegs y TcpOutSegs que muestra nstat (RetransSegs y OutSegs del grupo Tcp) - [nstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/nstat.8.html) · iproute2 · nstat muestra por defecto el incremento desde la ejecución anterior - [RFC 2863: The Interfaces Group MIB](https://www.rfc-editor.org/rfc/rfc2863) · IETF · ifOutDiscards: paquetes que no se enviaron y se descartaron aunque no había errores, por ejemplo, para liberar espacio de búfer - [An Internet-Wide Analysis of Traffic Policing](https://research.google/pubs/an-internet-wide-analysis-of-traffic-policing/) · Google · Distinción entre el desbordamiento de cola, en el que la espera y el RTT suben antes de la pérdida, y el policing, que descarta el exceso sin que suba el RTT (SIGCOMM 2016) #### rt-burst · Ráfagas de envío que desbordan búferes poco profundos · Sender bursts overflow shallow buffers Si el servidor envía de golpe en cada tick las actualizaciones de miles de jugadores, el pequeño búfer de un switch o el límite instantáneo de la nube se desborda en menos de 1 ms y parte de los paquetes se descarta. - Por qué → Efecto → En pantalla: Al empezar el tick se envían a la vez los paquetes para todos los jugadores → El búfer del puerto del switch donde confluye el tráfico de varios servidores (de cientos de KB a unos pocos MB por puerto) o el límite de la instancia en la nube se desborda por un instante (con una utilización media baja) → Varios jugadores sufren a la vez teletransporte y tirones; las métricas medias no muestran la causa - Síntomas: Teletransporte, Congelamiento, Cámara rápida / Factores: Pérdida de paquetes - A quién: Una zona o un canal, Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura), Infraestructura de red (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Repartir el envío de un tick a lo largo del propio tick (el pacing por conexión apenas resuelve que miles de conexiones envíen todas al inicio del tick), escalonar la hora de inicio del tick de cada servidor, limitar con SO_MAX_PACING_RATE la velocidad de las conexiones que envían datos grandes. - Tareas (Equipo de infraestructura): Servidores/SO: limitar la velocidad total de envío del servidor (shaper del SO del servidor, tc de Linux), suavizar con pacing (cola fq de Linux, BBR) las ráfagas de una sola conexión. Red: usar switches con búferes grandes, revisar a intervalos cortos los contadores de descartes de salida de los puertos del switch (la utilización media no los muestra). - Cifras de referencia: Un puerto de 10 Gbps puede enviar unos 1.25 MB en 1 ms. Si los ticks de varios servidores coinciden y confluyen en un mismo puerto, el búfer se llena en un instante. - En el gráfico: Sube con la carga (Descartes de salida del puerto del switch, tasa de retransmisión) - Dónde mirar: Recoger cada pocos segundos los descartes de salida (ifOutDiscards) del puerto del switch donde está el servidor y del puerto de nivel superior; en la nube, mirar bw_out_allowance_exceeded y pps_allowance_exceeded en ethtool -S. Recoger con bcc tcpretrans las retransmisiones del mismo momento y cruzarlas - Se confirma si: La utilización media por minuto es baja, pero suben los descartes de salida o los allowance superados, y crecen con los jugadores conectados a la vez y con la gente concentrada en un lugar. Las retransmisiones no se concentran en un rango de IP de jugadores (ISP, región) y se producen en el mismo instante en muchas conexiones de ese servidor - Se descarta si: Si en el mismo puerto también suben los errores CRC o de entrada, apunta a “Errores físicos (cables, transceptores ópticos o conectores defectuosos)”. Si suben los contadores de descartes de la NIC o el softnet dropped del servidor receptor, a “Descarte de paquetes en el host del servidor receptor” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: El pacing actúa en cada conexión por separado. Cuando miles de conexiones envían uno o dos paquetes cada una al inicio del tick, el pacing por conexión apenas suaviza la ráfaga, y es el servidor del juego el que tiene que repartir los momentos de envío. En cambio, cuando una conexión envía datos grandes, la NIC corta decenas de KB en paquetes y los envía seguidos (TSO), y ese tipo de ráfaga el pacing sí la reparte bien. - Fuentes: - [High-Resolution Measurement of Data Center Microbursts](https://research.facebook.com/publications/high-resolution-measurement-of-data-center-microbursts/) · Meta · Más del 70% de las ráfagas en los switches de rack del centro de datos terminan en decenas de µs, y la relación entre la utilización media por minuto y los descartes es débil (IMC 2017) - [tc-fq(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-fq.8.html) · iproute2 · La cola fq aplica pacing por socket (conexión), y SO_MAX_PACING_RATE fija la velocidad máxima de cada conexión - [net/ipv4/tcp_bbr.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_bbr.c?h=v6.12) · Linux kernel · BBR fija pacing_rate a partir del ancho de banda estimado del cuello de botella - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · TCP ajusta el tamaño de las tramas TSO a la velocidad del flujo (máximo 64 KB, tcp_min_tso_segs) - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · bw_out_allowance_exceeded y pps_allowance_exceeded: paquetes encolados o descartados por superar el límite de ancho de banda o de paquetes por segundo de la instancia - [RFC 2863: The Interfaces Group MIB](https://www.rfc-editor.org/rfc/rfc2863) · IETF · ifOutDiscards: paquetes que no se enviaron y se descartaron aunque no había errores, por ejemplo, para liberar espacio de búfer - [Demonstrations of tcpretrans, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/tcpretrans_example.txt) · IO Visor · Muestra una línea por retransmisión con la dirección y el puerto remotos y el estado de la conexión #### rt-policer · Descarte del exceso por un policer · Traffic policing Los planes de los ISP, los límites de las instancias en la nube y los dispositivos de protección DDoS a veces descartan al instante, sin encolarlos, los paquetes que superan una velocidad fijada. - Por qué → Efecto → En pantalla: El volumen enviado en un instante supera la velocidad permitida o la ráfaga permitida → Los paquetes que sobran se descartan en el acto, sin cola (policing) → En cada ráfaga grande desaparecen varios paquetes: congelamiento seguido de cámara rápida, aunque la velocidad media parezca estar por debajo del límite - Síntomas: Congelamiento, Cámara rápida, Teletransporte / Factores: Pérdida de paquetes - A quién: Todo el servidor, Una región o un ISP, Solo yo / Cuándo: Cuando se junta mucha gente, Horas pico de la noche - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Repartir dentro del tick lo que se envía de golpe en cada tick para bajar el volumen instantáneo por debajo de la ráfaga permitida, juntar los mensajes de un tick en un solo paquete si se topa con el límite de paquetes por segundo. - Tareas (Equipo de infraestructura): Red: revisar los contadores de exceso del policer en los dispositivos, sustituir el policer por un shaper, ampliar la ráfaga permitida. Servidores/SO: revisar las métricas de límite superado de la nube (en AWS, bw_out_allowance_exceeded y pps_allowance_exceeded en ethtool -S), subir de instancia, aplicar pacing en el servidor (cola fq de Linux). - Cifras de referencia: Un shaper (limitador que encola los paquetes y los retrasa) aumenta la latencia, y un policer (limitador que los descarta al instante) aumenta la pérdida. Una conexión TCP de juego puede detenerse cientos de ms por una sola pérdida, así que, cuando el límite se supera solo un momento, casi siempre hace más daño el policer. - En el gráfico: Topa con el límite (Volumen de envío a intervalos cortos, contadores de exceso del policer y de allowance) - Dónde mirar: Contadores de exceso (exceed) y de descartes del dispositivo donde está el policer; en la nube, bw_out_allowance_exceeded y pps_allowance_exceeded en ethtool -S. En las conexiones con pérdida, el RTT justo antes de la pérdida con el rtt de ss -ti o con una captura de paquetes - Se confirma si: Los contadores de exceso suben, y el volumen de envío visto a intervalos cortos se queda plano, como cortado en un valor. El RTT no sube justo antes de la pérdida, y solo en los momentos de ráfaga grande desaparecen varios paquetes a la vez - Se descarta si: Si el RTT sube justo antes de la pérdida, apunta a un desbordamiento de cola (“Desbordamiento de la cola en el cuello de botella (pérdida por congestión)”, “Ráfagas de envío que desbordan búferes poco profundos”). Si los contadores de exceso no cambian, es otra causa - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 2475: An Architecture for Differentiated Services](https://www.rfc-editor.org/rfc/rfc2475) · IETF · Definición: el shaping retrasa los paquetes para ajustarlos al perfil de tráfico, y el policing descarta los paquetes que superan el perfil - [An Internet-Wide Analysis of Traffic Policing](https://research.google/pubs/an-internet-wide-analysis-of-traffic-policing/) · Google · Las transferencias sometidas a policing tienen de media una tasa de pérdida 6 veces mayor, y el mismo objetivo se puede lograr con pacing o shaping. Distinción: el policing descarta el exceso sin que suba el RTT, y en el desbordamiento de cola el RTT sube antes de la pérdida (SIGCOMM 2016) - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · bw_out_allowance_exceeded y pps_allowance_exceeded de ethtool -S: paquetes encolados o descartados por superar el límite de la instancia - [tc-fq(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-fq.8.html) · iproute2 · Pacing por conexión de la cola fq de Linux - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rtt (tiempo medio de ida y vuelta) de ss -i #### rt-physical · Errores físicos (cables, transceptores ópticos o conectores defectuosos) · Bit errors: bad cable, optics, dirty fiber Los cables dañados, los conectores ópticos sucios y los transceptores ópticos al final de su vida útil producen errores de bit, y los dispositivos descartan en silencio los paquetes corruptos. - Por qué → Efecto → En pantalla: Un cable, un transceptor óptico o un conector defectuoso invierte bits → El dispositivo descarta los paquetes cuya suma de verificación (CRC) no cuadra → Solo los jugadores cuyo tráfico pasa por esa ruta sufren de forma constante tirones breves seguidos de cámara rápida, a cualquier hora - Síntomas: Congelamiento, Cámara rápida, Teletransporte / Factores: Pérdida de paquetes - A quién: Una zona o un canal, Misma casa / Cuándo: Siempre - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura), Externo (Externo) - Tareas (Equipo de infraestructura): Revisar los dos extremos, porque los errores CRC se acumulan en el lado receptor del sentido dañado. Red: revisar los contadores de errores CRC y de entrada de los puertos, comprobar la potencia de la señal óptica (información del transceptor óptico en el switch), limpiar los conectores ópticos, cambiar cables y transceptores ópticos. Servidores/SO: revisar rx_crc_errors en ethtool -S del servidor (el nombre varía un poco según el driver), comprobar la potencia de la señal óptica (ethtool -m), cambiar los cables o la NIC del lado del servidor. - Tareas (Externo): Si el problema está en el tramo de la casa del jugador, indicarle que cambie el cable de red o el router; si está en el enlace del ISP, pedir al ISP que revise la línea. - Cifras de referencia: Incluso un 0.1% de pérdida es un paquete de cada 1,000 del juego. Si por esa ruta pasan decenas de jugadores, alguno sufre un tirón cada pocos segundos. Los errores de bit afectan más a los paquetes grandes. - En el gráfico: Alto solo en algunos (Errores CRC por puerto, tasa de retransmisión por servidor/puerto) - Dónde mirar: Contadores CRC de los dos extremos del enlace. En el servidor, rx_crc_errors en ethtool -S o crc en ip -s -s link; en el switch, los errores de FCS (dot3StatsFCSErrors) y de entrada (ifInErrors) del puerto. En enlaces ópticos, la potencia óptica recibida con ethtool -m y con la información del transceptor óptico en el switch - Se confirma si: Los errores CRC de un puerto suben de forma constante a cualquier hora, y solo los servidores y conexiones que pasan por ese puerto tienen una tasa de retransmisión alta. La potencia óptica recibida es menor que en otros enlaces del mismo tipo - Se descarta si: Si los CRC no cambian y solo suben los descartes de salida, apunta a un desbordamiento de cola (“Ráfagas de envío que desbordan búferes poco profundos”, “Desbordamiento de la cola en el cuello de botella (pérdida por congestión)”). Si suben a la vez las colisiones tardías en un extremo y los CRC en el otro, a “Desajuste de dúplex” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · rx_crc_errors: paquetes que la interfaz receptora contó con error CRC; se ven con ip -s -s link y ethtool -S - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Estadísticas por NIC y driver con -S; EEPROM e información de diagnóstico óptico del transceptor (SFP+, QSFP) con -m - [RFC 3635: Definitions of Managed Objects for the Ethernet-like Interface Types](https://www.rfc-editor.org/rfc/rfc3635) · IETF · Errores de FCS del puerto del switch (dot3StatsFCSErrors), que se suman a los errores de entrada (ifInErrors) #### rt-duplex · Desajuste de dúplex · Duplex mismatch Si un extremo usa autonegociación y el otro tiene la velocidad y el dúplex fijos, un lado acaba funcionando en half-duplex (semidúplex) y pierde paquetes por colisiones cada vez que hay carga. - Por qué → Efecto → En pantalla: Solo un extremo tiene la velocidad y el dúplex fijados a mano → Un lado funciona en full-duplex y el otro en half-duplex, y se producen colisiones y colisiones tardías → Normalmente todo va bien, pero cuando sube el tráfico todos los jugadores que pasan por ese dispositivo sufren congelamiento seguido de cámara rápida - Síntomas: Congelamiento, Cámara rápida / Factores: Pérdida de paquetes - A quién: Todo el servidor, Una zona o un canal / Cuándo: Cuando se junta mucha gente, Horas pico de la noche - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Poner los dos extremos en autonegociación o fijar el mismo valor en ambos. Red: comprobar la velocidad y el dúplex en el estado del puerto del switch, y revisar en los contadores del puerto si suben las colisiones tardías en el lado half-duplex y los errores CRC y las tramas demasiado cortas (runts) en el lado full-duplex. Servidores/SO: comprobar la velocidad y el dúplex con ethtool. - Cifras de referencia: En cobre a 1 Gbps la autonegociación es obligatoria, y a 10 Gbps o más ni siquiera existe el half-duplex. Por eso hoy aparece sobre todo en dispositivos antiguos de 100 Mbps o menos, en puertos de gestión y en algunos puntos de conexión con enlaces de operadores. - En el gráfico: Sube con la carga (Colisiones tardías y errores CRC del puerto, tasa de retransmisión) - Dónde mirar: Velocidad y dúplex reales de los dos extremos del enlace. En el servidor, ethtool ejecutado solo con el nombre de la interfaz; en el switch, el estado del puerto o dot3StatsDuplexStatus por SNMP. Mirar también las colisiones tardías (tx_window_errors en el servidor, dot3StatsLateCollisions en el switch) y los errores CRC - Se confirma si: Un lado aparece en half-duplex y el otro en full-duplex. Cada vez que sube el tráfico, aumentan a la vez las colisiones tardías en el lado half-duplex y los errores CRC en el lado full-duplex - Se descarta si: Si la velocidad y el dúplex coinciden en ambos lados y solo suben los CRC, apunta a “Errores físicos (cables, transceptores ópticos o conectores defectuosos)”. Los enlaces de 10 Gbps o más no tienen half-duplex, así que se descartan como causa - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Linux Base Driver for Intel(R) Ethernet Network Connection](https://docs.kernel.org/networking/device_drivers/ethernet/intel/e1000.html) · Linux kernel · La norma 1000BASE-T exige autonegociación - [IEEE 802.3ae 10 Gigabit Ethernet: HSSG Objectives](https://www.ieee802.org/3/ae/objectives.pdf) · IEEE · 10 Gigabit Ethernet solo admite full-duplex - [IEEE P802.3ba Objectives](https://www.ieee802.org/3/ba/PAR/P802.3ba_Objectives_0709.pdf) · IEEE · 40 y 100 Gigabit Ethernet también admiten solo full-duplex - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · tx_window_errors: transmisiones fallidas por colisión tardía (late collision); rx_crc_errors: paquetes recibidos con error CRC - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · speed, duplex y autoneg de ethtool -s configuran la velocidad, el dúplex y la autonegociación; con solo el nombre de la interfaz, muestra la configuración actual - [RFC 3635: Definitions of Managed Objects for the Ethernet-like Interface Types](https://www.rfc-editor.org/rfc/rfc3635) · IETF · dot3StatsDuplexStatus (indica el dúplex actual con halfDuplex o fullDuplex), dot3StatsLateCollisions (número de colisiones tardías) #### rt-host-drop · Descarte de paquetes en el host del servidor receptor · Receiver host drops (ring, softirq, CPU) Los paquetes llegan al servidor, pero se descartan porque se desborda el búfer circular de la NIC (el búfer donde se guardan un momento los paquetes que llegan) o porque se satura el núcleo que procesa la recepción en el kernel. - Por qué → Efecto → En pantalla: Pico de conexiones, interrupciones concentradas en un solo núcleo, CPU steal en la máquina virtual o sobrecarga del switch virtual → Descarte en el búfer circular (rx_missed_errors, etc.; el nombre cambia según el driver) o en la cola de recepción del kernel (softnet dropped) → Cuando se junta mucha gente, los inputs tardan en hacer efecto en todo el servidor a la vez y hay tirones - Síntomas: Input lag, Congelamiento, Cámara rápida, Teletransporte / Factores: Pérdida de paquetes, Detención - A quién: Todo el servidor / Cuándo: Cuando se junta mucha gente - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Añadir al monitoreo los contadores de descartes como rx_missed_errors de ethtool -S y dropped de /proc/net/softnet_stat, ampliar el búfer circular (ethtool -G), repartir RSS y las interrupciones entre varios núcleos, separar los núcleos del hilo del juego de los que procesan la recepción, asegurar margen de CPU y, en máquinas virtuales, revisar el CPU steal y la carga del switch virtual. - Cifras de referencia: Los paquetes que el servidor descarta al recibirlos los reenvía el cliente. Por eso apenas aparecen en las métricas de retransmisión del servidor, y se ven antes en contadores de descartes como rx_missed_errors de ethtool -S (el nombre cambia según el driver) y en dropped de /proc/net/softnet_stat. - En el gráfico: Topa con el límite (Uso de softirq por núcleo, contadores de descartes de la NIC) - Dónde mirar: Contadores de descartes de ethtool -S (rx_missed_errors, etc.; en mlx5, rx_out_of_buffer y rx_discards_phy), missed de ip -s -s link, 2.ª columna (dropped) y 3.ª columna (time_squeeze) de /proc/net/softnet_stat, y %soft por núcleo (procesamiento de interrupciones de software) con mpstat -P ALL. En máquinas virtuales, también %steal - Se confirma si: A la hora en que se junta la gente suben los contadores de descartes o el softnet dropped, y el %soft del núcleo que procesa la recepción se queda cerca del 100% sin poder subir más. Los inputs se retrasan a la vez en todas las conexiones de ese servidor - Se descarta si: Si los contadores de descartes del servidor no cambian y las retransmisiones se concentran en conexiones de una región o un ISP, es pérdida en la ruta. Cuando se pierden en la ruta paquetes enviados por el servidor, sube TcpRetransSegs en el nstat del servidor y estos contadores no cambian - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · rx_missed_errors: paquetes que el host no pudo recibir por falta de búfer (en /proc/net/dev se suman a drop); se ve con ip -s -s link - [drivers/net/ethernet/intel/igb/igb_ethtool.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/intel/igb/igb_ethtool.c?h=v6.12) · Linux kernel · Los nombres de los contadores de ethtool -S los define el driver (p. ej., rx_missed_errors y rx_no_buffer_count en igb) - [Ethtool counters](https://docs.kernel.org/networking/device_drivers/ethernet/mellanox/mlx5/counters.html) · Linux kernel · rx_out_of_buffer (sin búfer en la cola de recepción) y rx_discards_phy (descartes por falta de búfer en el puerto) del driver mlx5 - [net/core/net-procfs.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/core/net-procfs.c?h=v6.12) · Linux kernel · /proc/net/softnet_stat tiene una línea por CPU, en hexadecimal; la 2.ª columna es dropped y la 3.ª, time_squeeze - [Documentation for /proc/sys/net/](https://docs.kernel.org/admin-guide/sysctl/net.html) · Linux kernel · netdev_max_backlog: límite de la cola de recepción donde se acumulan los paquetes cuando llegan más rápido de lo que el kernel los procesa - [Scaling in the Linux Networking Stack](https://docs.kernel.org/networking/scaling.html) · Linux kernel · RSS: la NIC reparte los paquetes entre varias colas de recepción para procesarlos en varias CPU - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · -G (--set-ring) cambia el tamaño del búfer circular - [proc_stat(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_stat.5.html) · Linux man-pages · steal de /proc/stat: tiempo de CPU que, en un entorno virtualizado, usó otro SO - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · Uso por núcleo con mpstat -P ALL; %soft es el tiempo de procesamiento de interrupciones de software, y %steal, el tiempo de espera mientras el hipervisor atendía otra CPU virtual - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · TcpRetransSegs que muestra nstat (RetransSegs del grupo Tcp) #### rt-stateful-fw · Descartes del firewall o del seguimiento de conexiones · Stateful firewall / conntrack drops Los firewalls y el seguimiento de conexiones de Linux (conntrack, la función que registra en una tabla las conexiones que pasan) descartan paquetes cuando la tabla se llena o cuando consideran que no encajan con el estado de la conexión. - Por qué → Efecto → En pantalla: La tabla de seguimiento de conexiones se llena (table full), o la ida y la vuelta van por rutas distintas y solo un sentido pasa por el firewall (ruta asimétrica) → El firewall toma los paquetes como de una “conexión desconocida” o con un “número de secuencia fuera de la ventana” y los descarta → Si la tabla se llena, no entran conexiones nuevas; si las rutas no coinciden, solo los jugadores de esa ruta acaban en desconexión tras repetidas retransmisiones - Síntomas: Congelamiento, Desconexión, No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Todo el servidor, Una región o un ISP / Cuándo: Cuando se junta mucha gente, Al conectar o tras un mantenimiento, De vez en cuando, al azar - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de servidor (Equipo de desarrollo), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: regular con un sistema de cola de inicio de sesión las conexiones que llegan de golpe, por si la tabla se llena, reutilizar conexiones para no abrir conexiones cortas una y otra vez (también en las llamadas entre servidores), cerrar primero las conexiones cuyo heartbeat se cortó. Cliente: si la conexión falla o se corta, reintentar con intervalos crecientes y repartidos al azar (para que no vuelvan todos a la vez cuando la tabla se llena). - Tareas (Equipo de infraestructura): Red: ampliar la tabla de seguimiento de conexiones del firewall, excluir del seguimiento los puertos del juego, ajustar el enrutamiento para que la ida y la vuelta pasen por el mismo firewall, revisar la configuración de comprobación de ventana TCP del firewall. Servidores/SO: ampliar la tabla en Linux (nf_conntrack_max), excluir del seguimiento los puertos del juego (NOTRACK), revisar la configuración de comprobación de ventana TCP (nf_conntrack_tcp_be_liberal) y, en AWS, revisar también conntrack_allowance_exceeded. - Cifras de referencia: El límite predeterminado de conntrack en Linux (nf_conntrack_max) va de decenas de miles a cientos de miles de entradas según la memoria. Cuando el número actual (nf_conntrack_count) llega al límite, queda en el log “nf_conntrack: table full, dropping packet”. - En el gráfico: Topa con el límite (Entradas de conntrack (nf_conntrack_count), conexiones nuevas fallidas) - Dónde mirar: En servidores Linux, nf_conntrack_count y nf_conntrack_max, “nf_conntrack: table full, dropping packet” en dmesg, y drop e invalid en /proc/net/stat/nf_conntrack (una línea por núcleo, en hexadecimal). En firewalls, el uso de la tabla de sesiones y los logs de descartes; en AWS, conntrack_allowance_exceeded en ethtool -S - Se confirma si: Las entradas se quedan planas en el límite y, a la misma hora, suben los logs de table full y drop, o conntrack_allowance_exceeded. Con una ruta asimétrica, hay margen en el límite, pero invalid y los logs de descartes del firewall suben en las conexiones de una ruta concreta - Se descarta si: Si las entradas están lejos del límite e invalid y los logs de descartes no cambian, es otra causa. Si la tabla tiene margen, pero la CPU o los paquetes por segundo del firewall están al tope, apunta a “Límite de procesamiento superado en dispositivos intermedios (firewall, IPS, protección DDoS)” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · El valor predeterminado de nf_conntrack_max es el número de buckets del hash (memoria ÷ 16384, entre 1,024 y 262,144), el número actual es nf_conntrack_count, y nf_conntrack_tcp_be_liberal solo marca como INVALID los RST fuera de la ventana - [net/netfilter/nf_conntrack_core.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_conntrack_core.c?h=v6.12) · Linux kernel · Cuando la tabla se llena, deja el log “nf_conntrack: table full, dropping packet” y descarta el paquete (sube la estadística drop); los paquetes que no encajan con el estado de la conexión suben la estadística invalid - [iptables-extensions(8) — Linux manual page](https://man7.org/linux/man-pages/man8/iptables-extensions.8.html) · netfilter · CT --notrack en la tabla raw excluye del seguimiento de conexiones - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Al superar el límite de conexiones con seguimiento de cada instancia se descartan paquetes, lo que se ve en conntrack_allowance_exceeded; recomendación de evitar las rutas asimétricas - [net/netfilter/nf_conntrack_standalone.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_conntrack_standalone.c?h=v6.12) · Linux kernel · /proc/net/stat/nf_conntrack tiene una línea por núcleo, en hexadecimal, con columnas como entries, invalid, insert_failed, drop y early_drop #### rt-appliance-pps · Límite de procesamiento superado en dispositivos intermedios (firewall, IPS, protección DDoS) · Inline appliance PPS / CPU overload Los firewalls, los sistemas de prevención de intrusiones (IPS) y los dispositivos de protección DDoS inspeccionan uno a uno los paquetes que pasan. En cuanto se supera su capacidad de inspección, descartan los paquetes que no alcanzan a procesar. - Por qué → Efecto → En pantalla: En horas pico o durante eventos llegan de golpe cientos de miles de paquetes pequeños del juego por segundo (o más), o las reglas de inspección son pesadas → Se agota la CPU o el límite de paquetes por segundo del dispositivo y este descarta paquetes. Si hay falsos positivos, bloquea también paquetes legítimos → Congelamiento y teletransporte a la vez en todos los servidores que hay detrás de ese dispositivo; solo empeora cuando se junta mucha gente - Síntomas: Congelamiento, Cámara rápida, Teletransporte, Desconexión / Factores: Pérdida de paquetes, Latencia - A quién: Todo el servidor, Una región o un ISP / Cuándo: Horas pico de la noche, Cuando se junta mucha gente - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Compartir con el equipo de infraestructura el patrón del tráfico del juego (puertos, tamaño de paquete, paquetes por segundo), juntar los mensajes pequeños de un tick y enviarlos de una vez para reducir el número de paquetes. - Tareas (Equipo de infraestructura): Mirar la CPU, los paquetes por segundo y los contadores de descartes del dispositivo junto con las métricas del juego, dimensionar los dispositivos tomando como referencia paquetes pequeños, excluir los puertos del juego de las inspecciones pesadas, adaptar las reglas de protección DDoS al patrón del tráfico del juego. - Cifras de referencia: Los “10 Gbps” de las especificaciones de un dispositivo muchas veces se refieren a paquetes grandes de 1,500 bytes. Con el mismo ancho de banda, los paquetes del juego, de unos 100 bytes, son más de 10 veces más numerosos, así que el límite de paquetes por segundo se alcanza antes aunque el enlace parezca desahogado. - En el gráfico: Topa con el límite (Paquetes por segundo y uso de CPU del dispositivo, descartes del dispositivo) - Dónde mirar: CPU, paquetes por segundo y contadores de descartes del dispositivo, y comparar con el mismo intervalo los paquetes de los puertos de switch antes y después del dispositivo. Superponerlo en una misma pantalla con los jugadores conectados a la vez y la tasa de retransmisión del servidor - Se confirma si: En horas pico o durante eventos, los paquetes por segundo o la CPU del dispositivo se quedan en un valor sin poder subir más, salen menos paquetes de los que entran y, a la misma hora, sube la tasa de retransmisión de todos los servidores que hay detrás - Se descarta si: Si los paquetes antes y después del dispositivo coinciden y no hay descartes en el dispositivo, es otra causa. Si suben los contadores de descartes de la NIC o el softnet dropped del servidor, apunta a “Descarte de paquetes en el host del servidor receptor” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 2544: Benchmarking Methodology for Network Interconnect Devices](https://www.rfc-editor.org/rfc/rfc2544) · IETF · El rendimiento de un dispositivo debe probarse con varios tamaños de trama, incluidos el mínimo y el máximo (la capacidad de procesamiento cambia con el tamaño del paquete) #### rt-mtu · Agujero negro de MTU (solo los paquetes grandes se pierden una y otra vez) · PMTU black hole Si un tramo intermedio pasa a aceptar paquetes más pequeños y el aviso de “demasiado grande” (ICMP) está bloqueado, los paquetes grandes siguen desapareciendo por muchas veces que se reenvíen. - Por qué → Efecto → En pantalla: El tamaño máximo se reduce en un tramo con VPN o túnel, y un firewall bloquea los avisos de tamaño excedido → El emisor, sin saber por qué, retransmite una y otra vez el mismo paquete grande, y el RTO se duplica cada vez → Todo va bien normalmente, pero en cuanto se mueven datos grandes (inventario, zonas con mucha gente, carga al entrar) se detiene todo, incluidos los paquetes pequeños que vienen detrás (congelamiento); al final, desconexión o carga infinita - Síntomas: Congelamiento, Desconexión, No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Una región o un ISP, Solo yo / Cuándo: Al hacer ciertas acciones, Al conectar o tras un mantenimiento - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Para bajarlo directamente desde el servidor, configurar en el socket el tamaño máximo de segmento (TCP_MAXSEG); partir los mensajes en trozos más pequeños en el código del juego no basta para evitarlo (TCP vuelve a agrupar los datos en bloques del tamaño del MSS). - Tareas (Equipo de infraestructura): Red: aplicar ajuste de MSS (clamping) en los dispositivos de borde, permitir el ICMP de tamaño excedido (tipo 3 código 4, fragmentation needed) en los firewalls y las ACL de red en la nube. Servidores/SO: configurar la MTU de la ruta, comprobar que el ICMP de tamaño excedido tampoco quede bloqueado en los firewalls de los servidores ni en los grupos de seguridad en la nube y, como última red de seguridad, poner tcp_mtu_probing=1 en Linux. - Cifras de referencia: Normalmente 1,500 bytes; al pasar por un túnel, unos 1,400. Si el mismo paquete se retransmite 5–6 veces, la pausa supera los 10 segundos. - En el gráfico: Alto solo en algunos (RTO y backoff por conexión, desconexiones por región/ISP) - Dónde mirar: Retransmisiones de la conexión afectada con una captura de paquetes en el servidor o con bcc tcpretrans -s (muestra el número de secuencia), y mss, pmtu y backoff de esa conexión con ss -ti. Desde el servidor, enviar a la dirección del jugador un ping pequeño y otro de 1,500 bytes con DF activado (ping -M do -s 1472) y comparar - Se confirma si: Los paquetes llenos hasta el MSS se retransmiten una y otra vez con el mismo número de secuencia, duplicando el intervalo cada vez, mientras que los paquetes más pequeños sí pasan. No llega el ICMP de tamaño excedido (filtro de Wireshark icmp.type == 3 and icmp.code == 4), y el ping pequeño responde, pero el ping grande con DF desaparece sin respuesta - Se descarta si: Si también desaparecen los paquetes pequeños, es una pérdida que no depende del tamaño (“Desbordamiento de la cola en el cuello de botella (pérdida por congestión)”, “Cambio de ruta o ruta ECMP defectuosa”). Si llega el ICMP de tamaño excedido y baja el pmtu de ss -ti, el descubrimiento de la MTU de la ruta funciona bien - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Con tcp_mtu_probing=1, Linux solo da por hecho que hay un agujero negro después de varios segundos de timeouts de retransmisión (lo que equivale a tcp_retries1=3), y entonces baja el MSS a 1,024 bytes. Mientras tanto la conexión se queda parada, así que esta opción es la última red de seguridad; lo primero es el ajuste de MSS, que evita el problema de antemano. - Fuentes: - [RFC 1191: Path MTU discovery](https://www.rfc-editor.org/rfc/rfc1191) · IETF · Descubrimiento de la MTU de la ruta: los paquetes demasiado grandes se notifican con el ICMP “fragmentation needed and DF set” (tipo 3 código 4) - [RFC 2923: TCP Problems with Path MTU Discovery](https://www.rfc-editor.org/rfc/rfc2923) · IETF · El problema del agujero negro de PMTU, en el que el ICMP está bloqueado y solo los paquetes grandes desaparecen una y otra vez - [RFC 4821: Packetization Layer Path MTU Discovery](https://www.rfc-editor.org/rfc/rfc4821) · IETF · Método para que la capa de transporte sondee el tamaño de paquete sin ICMP (base de tcp_mtu_probing en Linux) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_mtu_probing: 0 desactivado, 1 solo cuando se detecta un agujero negro, 2 siempre (el MSS inicial es tcp_base_mss). tcp_retries1: 3 por defecto - [net/ipv4/tcp_timer.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · Si las retransmisiones por RTO se repiten tcp_retries1 veces, se considera detectado un agujero negro y se activa el sondeo de MTU para bajar el MSS - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · TCP_BASE_MSS = 1,024 bytes - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · El RTO se duplica cada vez que expira el temporizador de retransmisión - [iptables-extensions(8) — Linux manual page](https://man7.org/linux/man-pages/man8/iptables-extensions.8.html) · netfilter · TCPMSS --clamp-mss-to-pmtu: evita, ajustando el MSS en el SYN, que los paquetes grandes se atasquen por tramos que bloquean el ICMP - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_MAXSEG: tamaño máximo de segmento de los paquetes salientes; si se configura antes de conectar, también cambia el MSS que se anuncia al otro extremo - [Network maximum transmission unit (MTU) for your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html) · AWS · Los gateways de internet y las VPN usan una MTU de 1,500; PMTUD necesita el ICMP tipo 3 código 4, que no llega si lo bloquean los grupos de seguridad o las ACL de red - [MTU considerations | Cloud VPN](https://cloud.google.com/network-connectivity/docs/vpn/concepts/mtu-considerations) · Google Cloud · MTU de 1,460 bytes en el gateway de Cloud VPN y MTU de carga útil de 1,406 bytes en túneles IPv4 (al pasar por un túnel, unos 1,400) - [Demonstrations of tcpretrans, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/tcpretrans_example.txt) · IO Visor · Muestra una línea por retransmisión, y -s añade el número de secuencia del paquete retransmitido - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · mss, pmtu (MTU de la ruta) y backoff (veces que se ha duplicado el RTO) de ss -i - [ping(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ping.8.html) · iputils · -M do activa DF y no envía paquetes mayores que la MTU de la ruta que conoce el kernel; -s es el tamaño de los datos (sin contar los 8 bytes de la cabecera ICMP) - [Display Filter Reference: Internet Control Message Protocol](https://www.wireshark.org/docs/dfref/i/icmp.html) · Wireshark · Filtros de visualización icmp.type e icmp.code #### rt-mapping · Expiración del mapeo NAT o del balanceador de carga en mitad de la conexión · NAT / load balancer mapping expired mid-connection Si un dispositivo intermedio borra el mapeo de una conexión inactiva (la entrada que indica a dónde reenviar esa conexión), el siguiente paquete que se envía no llega a su destino. O bien se repiten las retransmisiones hasta que la conexión se corta, o bien el dispositivo devuelve un rechazo de conexión (RST) y se corta al momento. - Por qué → Efecto → En pantalla: Conexión sin paquetes durante un buen rato (jugador ausente, en el lobby) → El NAT del router, el CGNAT del ISP, un firewall, un balanceador de carga o un grupo de seguridad en la nube borra el mapeo inactivo → Al volver a moverse, retransmisiones seguidas y luego desconexión, o desconexión inmediata - Síntomas: Desconexión, Congelamiento / Factores: Pérdida de paquetes - A quién: Solo yo, Una región o un ISP / Cuándo: Tras un rato inactivo - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo), Infraestructura de red (Equipo de infraestructura), Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Cliente: enviar heartbeats a intervalos de como mucho la mitad del timeout por inactividad más corto (los mapeos del router del jugador y del CGNAT del ISP solo se renuevan con seguridad con paquetes que salen desde dentro, y sus timeouts no los podemos cambiar, así que los envía el cliente), reconectar automáticamente si se corta. Servidor: responder a los heartbeats y cerrar la conexión por su cuenta si no los recibe durante cierto tiempo (acortar el intervalo del keepalive TCP con opciones de socket como TCP_KEEPIDLE, detectar antes con TCP_USER_TIMEOUT), retomar la sesión con un token de sesión. - Tareas (Equipo de infraestructura): Red: reunir los timeouts por inactividad de los firewalls y balanceadores de carga de la ruta y compartirlos con el equipo de desarrollo, ampliarlos en nuestros firewalls y balanceadores si hace falta. Servidores/SO: comprobar el tiempo de seguimiento de conexiones de los grupos de seguridad en la nube y compartirlo con el equipo de desarrollo. - Cifras de referencia: El tiempo que se mantiene un mapeo TCP varía según el dispositivo, de unos minutos a varias horas. Si el grupo de seguridad en la nube hace seguimiento de la conexión, en los tipos de instancia Nitro v6 de AWS la entrada de seguimiento se borra por defecto a los 350 segundos (en los demás tipos, a los 5 días; ver la entrada “Expiración del seguimiento de conexiones en grupos de seguridad de la nube”). El keepalive TCP de Linux tiene como valor predeterminado “comprobar tras 2 horas de inactividad”, más tarde que la mayoría de los dispositivos. - En el gráfico: Desconexión masiva (Desconexiones, tiempo inactivo antes de la desconexión) - Dónde mirar: Los últimos minutos de las conexiones cortadas con una captura de paquetes en el servidor, y el tiempo inactivo de las conexiones vivas con lastsnd y lastrcv de ss -ti (ms desde el último envío y la última recepción). También TcpExtTCPAbortOnTimeout de nstat (conexiones abandonadas al agotarse el temporizador) - Se confirma si: En cada conexión cortada, el tiempo inactivo previo superó un valor parecido (el timeout por inactividad de un dispositivo de la ruta; p. ej., 350 s en el grupo de seguridad de las instancias Nitro v6 de AWS), y desde el primer paquete tras la inactividad solo hay retransmisiones sin ACK hasta el abandono, o vuelve un RST al momento - Se descarta si: Si se corta también en plena partida, sin relación con el tiempo inactivo, es otra causa (“Cambio de ruta o ruta ECMP defectuosa”, “Descartes del firewall o del seguimiento de conexiones”). Si por la conexión pasan heartbeats a intervalos de como mucho la mitad del timeout por inactividad más corto, se descarta esta causa - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 5382: NAT Behavioral Requirements for TCP](https://www.rfc-editor.org/rfc/rfc5382) · IETF · Recomendación de que el timeout por inactividad de las conexiones TCP en un NAT sea de al menos 2 horas y 4 minutos (partiendo de que los dispositivos pueden borrar antes las sesiones inactivas) - [RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP](https://www.rfc-editor.org/rfc/rfc4787) · IETF · Los mapeos NAT deben renovarse con los paquetes que salen desde dentro (REQ-6), y la renovación con paquetes que entran desde fuera es opcional (para UDP) - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Timeout por inactividad del seguimiento TCP por defecto: 350 segundos en los tipos de instancia Nitro v6 y 432,000 segundos (5 días) en los demás. Recomendación de keepalive a intervalos menores de 5 minutos - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_keepalive_time: 2 horas por defecto - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_KEEPIDLE (tiempo inactivo antes de empezar el keepalive), TCP_USER_TIMEOUT (tiempo que pueden quedar datos sin confirmar antes de que se cierre la conexión) - [RFC 5482: TCP User Timeout Option](https://www.rfc-editor.org/rfc/rfc5482) · IETF · Timeout de usuario de TCP: cuánto tiempo pueden quedar sin confirmar los datos enviados antes de cerrar la conexión - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · lastsnd y lastrcv de ss -i: tiempo transcurrido desde el último envío y la última recepción (ms) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPAbortOnTimeout: conexiones abandonadas sin RST al agotarse un temporizador TCP #### rt-path · Cambio de ruta o ruta ECMP defectuosa · Route change / bad ECMP member Se pierden paquetes durante los segundos en que cambia una ruta de internet, o en las conexiones asignadas a una ruta defectuosa entre varias rutas ECMP. - Por qué → Efecto → En pantalla: Recálculo de rutas BGP, o un dispositivo o enlace defectuoso en una de varias rutas (ECMP, LAG) → Pérdida temporal durante el cambio de ruta, o pérdida constante solo en las conexiones que van por esa ruta → De repente, congelamiento de unos segundos seguido de cámara rápida, o “al reconectar se arregla” (se asigna otra ruta) - Síntomas: Congelamiento, Cámara rápida, Teletransporte / Factores: Pérdida de paquetes - A quién: Una región o un ISP / Cuándo: De vez en cuando, al azar - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo), Externo (Externo) - Tareas (Equipo de desarrollo): Guardar estadísticas de retransmisión por conexión (TCP_INFO) para poder sacar la IP, el puerto y la hora de quienes lo sufren, no cortar enseguida las conexiones que se detienen unos segundos. - Tareas (Equipo de infraestructura): Monitorear la tasa de retransmisión por región e ISP, comprobar si la ruta cambia al reconectar, contratar enlaces con varios ISP, revisar si hay enlaces defectuosos entre las rutas ECMP y LAG de nuestros dispositivos, medir la ruta también con el mismo puerto TCP que el juego (mtr --tcp --port; como la ruta depende de la dirección y el puerto, un ping normal puede ir por otra ruta y salir limpio). - Tareas (Externo): Reportar al ISP la ruta defectuosa adjuntando mediciones de ruta hechas con el mismo puerto TCP y la comparación antes y después de reconectar. - En el gráfico: Salto en escalón (RTT (ping), tasa de retransmisión por región/ISP) - Dónde mirar: Agrupar las retransmisiones por conexión con bcc tcpretrans -c para sacar la dirección y el puerto de los jugadores afectados, y comparar mtr (mtr -T -P PORT) con el mismo puerto TCP que el juego, del servidor al jugador y del jugador al servidor. Comparar también los resultados antes y después de reconectar - Se confirma si: A partir de un momento concreto, el RTT de una región o un ISP cambia en escalón y la pérdida se concentra durante unos segundos; o bien, dentro de un mismo ISP, solo algunas conexiones (combinaciones de dirección y puerto) retransmiten de forma constante y mejoran al reconectar. A veces el ping normal sale limpio y la pérdida solo aparece en el mtr por TCP - Se descarta si: Si todas las conexiones de ese ISP empeoran juntas en el pico de la noche, apunta a “Desbordamiento de la cola en el cuello de botella (pérdida por congestión)”. Si solo un jugador va mal y la pérdida empieza ya en el ping al router, a “Pérdida en el tramo inalámbrico” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Casos reales: cloudflare-2020 - Fuentes: - [RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection](https://www.rfc-editor.org/rfc/rfc2991) · IETF · Con múltiples rutas, los resultados de herramientas de diagnóstico como ping y traceroute son poco confiables; explica cómo fijar la ruta aplicando un hash a cada flujo - [RFC 2992: Analysis of an Equal-Cost Multi-Path Algorithm](https://www.rfc-editor.org/rfc/rfc2992) · IETF · ECMP elige el siguiente salto con un hash de los campos de cabecera que identifican el flujo (un mismo flujo, una misma ruta) - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_INFO: consulta del estado de cada socket (struct tcp_info) - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · -T (--tcp) envía las sondas como TCP SYN, sin ICMP, y -P (--port) indica el puerto de destino - [Demonstrations of tcpretrans, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/tcpretrans_example.txt) · IO Visor · Muestra una línea por retransmisión con la dirección y el puerto remotos, y -c agrega el número de retransmisiones por flujo #### rt-spurious-delay · Retransmisiones espurias por picos de latencia · Spurious RTO from delay spikes El paquete no se pierde; solo llega muy tarde por un momento. Pero si ese retraso supera el RTO, el emisor lo da por perdido y lo retransmite. - Por qué → Efecto → En pantalla: Por bufferbloat, el ahorro de energía del Wi-Fi, un cambio de estado de la radio móvil o una pausa de la máquina virtual, la latencia sube de golpe a cientos de ms → El RTO expira antes y se retransmite, y el original también llega enseguida (el receptor lo recibe duplicado) → El congelamiento y la cámara rápida se deben al propio pico de latencia. La retransmisión espuria apenas los alarga, pero sube las métricas de retransmisión y se confunde con pérdida - Síntomas: Congelamiento, Cámara rápida, Input lag / Factores: Latencia, Jitter - A quién: Solo yo, Todo el servidor / Cuándo: De vez en cuando, al azar, Tras un rato inactivo - Responsable principal: Externo (Externo) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): En clientes con Android 10 o posterior, pedir durante la partida el modo Wi-Fi de baja latencia (bloqueo de Wi-Fi WIFI_MODE_FULL_LOW_LATENCY, que solo se aplica con la pantalla encendida y el juego en primer plano) para reducir los picos de latencia que causa el ahorro de energía. - Tareas (Equipo de infraestructura): Evitar las instancias de rendimiento ampliable (burstable), no bajar demasiado el RTO mínimo, mantener F-RTO y las marcas de tiempo (tcp_frto, tcp_timestamps), mirar las métricas de retransmisión junto con TCPSpuriousRTOs y TCPDSACKRecv de nstat para no confundirlas con pérdida. - Tareas (Externo): Para reducir los propios picos de latencia, indicar a los jugadores que usen SQM en el router y desactiven el ahorro de energía del Wi-Fi. - Cifras de referencia: Linux detecta los RTO espurios con F-RTO y a veces deshace la reducción del ritmo de envío. Se comprueba con TCPSpuriousRTOs (veces que un RTO se juzgó espurio) y TCPDSACKRecv (veces que el receptor avisó de que “eso ya lo tenía”) de nstat. - En el gráfico: Picos aleatorios (RTT (ping), RTO espurios) - Dónde mirar: Ejecutar nstat cada minuto y ver juntos los incrementos de TcpExtTCPTimeouts (expiraciones del RTO), TcpExtTCPSpuriousRTOs, TcpExtTCPDSACKRecv y TcpExtTCPLostRetransmit. Con una captura de paquetes, usar el filtro de Wireshark tcp.analysis.spurious_retransmission - Se confirma si: Cuando suben los RTO, también suben TcpExtTCPSpuriousRTOs o TcpExtTCPDSACKRecv, y a la misma hora el RTT salta a cientos de ms. En la captura del receptor llegan tanto el original como la retransmisión - Se descarta si: Si TcpExtTCPSpuriousRTOs y DSACK no cambian, pero sube TcpExtTCPLostRetransmit (se pierde también lo retransmitido), es pérdida real. Si el RTT no salta y solo hay muchos DSACK de forma constante, apunta a “Retransmisiones rápidas espurias por reordenamiento de paquetes” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 5682: Forward RTO-Recovery (F-RTO): An Algorithm for Detecting Spurious Retransmission Timeouts with TCP](https://www.rfc-editor.org/rfc/rfc5682) · IETF · F-RTO: usa los ACK que llegan tras un RTO para saber si el RTO fue espurio - [RFC 3481: TCP over Second (2.5G) and Third (3G) Generation Wireless Networks](https://www.rfc-editor.org/rfc/rfc3481) · IETF · Los picos de latencia de las redes móviles (handover, recuperación del enlace, etc.) provocan timeouts y retransmisiones TCP espurias, y reducciones de la ventana de congestión - [RFC 2883: An Extension to the Selective Acknowledgement (SACK) Option for TCP](https://www.rfc-editor.org/rfc/rfc2883) · IETF · DSACK: el receptor avisa de que ha recibido datos duplicados, lo que permite al emisor detectar las retransmisiones espurias - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPSpuriousRTOs (RTO espurios detectados por F-RTO), TcpExtTCPDSACKRecv (DSACK recibidos), TcpExtTCPLostRetransmit (veces que SACK indicó que un paquete retransmitido se volvió a perder) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_frto activado por defecto (ventajoso en redes inalámbricas con un RTT inestable), tcp_timestamps: 1 por defecto - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · Fundamento de que hace falta un RTO mínimo grande para evitar retransmisiones espurias (recomienda un mínimo de 1 segundo) - [WifiManager](https://developer.android.com/reference/android/net/wifi/WifiManager#WIFI_MODE_FULL_LOW_LATENCY) · Android (Google) · WIFI_MODE_FULL_LOW_LATENCY (API 29, Android 10): bloqueo de Wi-Fi de baja latencia que solo se aplica con conexión a un AP, la pantalla encendida y la app en primer plano - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nombres de contador que muestra nstat: TCPTimeouts, TCPSpuriousRTOs, TCPDSACKRecv y TCPLostRetransmit - [net/ipv4/tcp_timer.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · TCPTimeouts sube cuando expira el temporizador de retransmisión (RTO) - [nstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/nstat.8.html) · iproute2 · nstat muestra por defecto el incremento desde la ejecución anterior - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtro de visualización tcp.analysis.spurious_retransmission #### rt-reorder · Retransmisiones rápidas espurias por reordenamiento de paquetes · Reordering triggers spurious fast retransmit Cuando los paquetes cambian de orden al pasar por varias rutas o por enlaces agregados, el receptor avisa con ACK duplicados de que “falta un paquete”, y el emisor reenvía paquetes que estaban bien. - Por qué → Efecto → En pantalla: Los dispositivos que reparten el tráfico entre rutas paquete a paquete, los LAG (agregación de enlaces) que reparten paquete a paquete o el instante de un cambio de ruta desordenan los paquetes → Los paquetes posteriores llegan antes y se acumulan 3 ACK duplicados → retransmisión rápida → Los paquetes del juego, que van espaciados, casi no se ven afectados. Las actualizaciones grandes en zonas con mucha gente y las descargas de parches se vuelven lentas, y a veces hay tirones - Síntomas: Tirones, Input lag / Factores: Jitter - A quién: Una región o un ISP, Todo el servidor / Cuándo: Siempre, Cuando se junta mucha gente - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Red: repartir el tráfico por conexión, nunca paquete a paquete (ECMP y LAG con hash de dirección y puerto). Servidores/SO: usar RACK (detección de pérdidas basada en el tiempo, resistente al reordenamiento; si detecta retransmisiones espurias con DSACK, amplía automáticamente el margen de reordenamiento), revisar el grado de reordenamiento que Linux estima automáticamente para cada conexión (valor reordering de ss -ti, que parte de tcp_reordering=3). - En el gráfico: Siempre alto (Reordenamientos detectados, DSACK recibidos) - Dónde mirar: TcpExtTCPSACKReorder y TcpExtTCPTSReorder (reordenamientos detectados) y TcpExtTCPDSACKRecv de nstat; por conexión, reordering (aparece si no vale 3) y reord_seen de ss -ti. En la captura de paquetes, el filtro de Wireshark tcp.analysis.out_of_order - Se confirma si: Los contadores de reordenamiento y los DSACK suben de forma constante a cualquier hora, y el valor reordering de las conexiones que pasan por una ruta o un dispositivo concreto es mayor que 3. En la captura del receptor, los paquetes posteriores llegan antes y los anteriores llegan enseguida - Se descarta si: Si los contadores de reordenamiento no cambian y sube TcpExtTCPLostRetransmit, es pérdida real. Si los DSACK solo suben cuando salta el RTT, apunta a “Retransmisiones espurias por picos de latencia” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection](https://www.rfc-editor.org/rfc/rfc2991) · IETF · Repartir entre rutas paquete a paquete cambia el orden, y si llegan antes 3 o más paquetes posteriores, TCP hace una retransmisión rápida espuria - [RFC 2992: Analysis of an Equal-Cost Multi-Path Algorithm](https://www.rfc-editor.org/rfc/rfc2992) · IETF · ECMP que elige la ruta con un hash de los campos de cabecera que identifican el flujo (reparto por flujo) - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Retransmisión rápida al tercer ACK duplicado - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · RACK detecta las pérdidas por tiempo, lo que lo hace resistente al reordenamiento, y al recibir DSACK amplía el margen de tiempo para el reordenamiento (reo_wnd) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_reordering: valor inicial 3 (se ajusta automáticamente en cada conexión hasta tcp_max_reordering); configuración de RACK en tcp_recovery - [misc/ss.c](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/misc/ss.c?h=v6.12.0) · iproute2 · ss -ti muestra reordering:valor cuando el reordering de la conexión difiere del valor predeterminado 3, y reord_seen:veces si alguna vez hubo reordenamiento - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPSACKReorder y TcpExtTCPTSReorder (reordenamiento detectado), TcpExtTCPDSACKRecv (DSACK recibidos), TcpExtTCPLostRetransmit (un paquete retransmitido se vuelve a perder) - [include/uapi/linux/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/tcp.h?h=v6.12) · Linux kernel · tcpi_reord_seen de tcp_info: veces que la conexión sufrió reordenamiento - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtro de visualización tcp.analysis.out_of_order #### rt-ack-path · ACK retrasados o perdidos (subida saturada) · ACK path congestion on asymmetric links Los datos llegaron bien, pero si el ACK que confirma la recepción se retrasa o se pierde en una cola de subida llena, el emisor lo da por perdido y retransmite. - Por qué → Efecto → En pantalla: En casa, una subida de video o una copia de seguridad en la nube satura la subida → Los ACK se retrasan cientos de ms en la cola del router, o la cola se desborda y se descartan → Los paquetes del juego que envía el servidor suelen llegar a tiempo. Tus inputs, acumulados en la misma cola de subida, se retrasan: input lag y rubber banding, y a veces retransmisiones espurias - Síntomas: Input lag, Rubber banding / Factores: Latencia, Pérdida de paquetes - A quién: Misma casa / Cuándo: De vez en cuando, al azar, Horas pico de la noche - Responsable principal: Externo (Externo) / También: Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Mostrar en pantalla el estado de la red cuando el ping se dispara, mostrar el aviso “Revisa si hay programas subiendo archivos”. - Tareas (Externo): Indicar a los jugadores que acorten la cola de subida con SQM en el router, prioricen los paquetes pequeños (ACK) y limiten la velocidad de subida (subidas de video, copias de seguridad en la nube). - Cifras de referencia: Como cada ACK posterior confirma también los anteriores, que se pierdan unos pocos normalmente no es un problema. El problema es el retraso en la cola. - En el gráfico: Alto solo en algunos (RTT (ping) por conexión) - Dónde mirar: Desde la computadora del jugador, comparar el ping al servidor del juego con la subida (subida de video, copia de seguridad en la nube) activa y detenida. En el servidor, el rtt de la conexión de ese jugador con ss -ti - Se confirma si: Solo durante la subida el ping sube a cientos de ms y aparecen input lag y rubber banding, que desaparecen enseguida al detener la subida. Desde el servidor, el rtt de esa conexión también sube en ese momento - Se descarta si: Si hay pérdida y latencia sin relación con la subida, apunta a “Pérdida en el tramo inalámbrico” o a una causa en la ruta. Si solo va lento el sentido servidor → jugador y no tiene que ver con la subida, a “Desbordamiento de la cola en el cuello de botella (pérdida por congestión)” - Se verifica con: En el entorno del jugador - Fuentes: - [RFC 3449: TCP Performance Implications of Network Path Asymmetry](https://www.rfc-editor.org/rfc/rfc3449) · IETF · En conexiones asimétricas con poca subida, si los ACK se retrasan o se pierden, el rendimiento de TCP cae; como los ACK son acumulativos, aunque se pierdan algunos, los posteriores los sustituyen; medidas como la planificación con prioridad para los ACK - [Smart Queue Management](https://www.bufferbloat.net/projects/cerowrt/wiki/Smart_Queue_Management/) · Bufferbloat.net · Mantener cortas las colas del router con gestión de colas y shaping - [tc-cake(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-cake.8.html) · iproute2 · CAKE separa los flujos y minimiza la latencia de los que envían poco y de forma espaciada (sparse flows) - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rtt (tiempo medio de ida y vuelta) y rttvar (desviación) de ss -i #### rt-rto-setting · RTO mal ajustado al entorno · RTO min too low or too high Si se baja demasiado el RTO mínimo, cualquier pequeño retraso provoca retransmisiones espurias; y el valor predeterminado (200 ms) es demasiado largo para un juego, así que cada pérdida detiene la conexión mucho tiempo. - Por qué → Efecto → En pantalla: Se baja mucho el RTO mínimo pensando en el centro de datos, o se deja el valor predeterminado tal cual en los tramos de internet → Si es bajo, hay avalanchas de retransmisiones con cualquier pico de latencia; si es alto, cada pérdida implica una espera larga → Con el valor predeterminado, cada pérdida provoca un congelamiento de cientos de ms seguido de cámara rápida; si se baja demasiado, los congelamientos se acortan, pero las retransmisiones espurias se disparan y desperdician el enlace - Síntomas: Congelamiento, Cámara rápida, Input lag / Factores: Latencia - A quién: Todo el servidor / Cuándo: Siempre - Responsable principal: Infraestructura de servidores (Equipo de infraestructura) / También: Desarrollo de servidor (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Con Linux 6.15 o posterior, estudiar bajar el máximo del RTO en las conexiones del juego con TCP_RTO_MAX_MS (como también se acorta el tiempo hasta abandonar la conexión, fijar a la vez con TCP_USER_TIMEOUT cuándo se da por desconectada), bajar el RTO mínimo solo en las conexiones internas entre servidores con la opción de socket TCP_RTO_MIN_US (6.15 o posterior), estudiar la opción de socket TCP_THIN_LINEAR_TIMEOUTS para que los RTO seguidos no se dupliquen, solo en las conexiones del juego. - Tareas (Equipo de infraestructura): Bajar rto_min por ruta solo para las conexiones internas entre servidores, mantener el valor predeterminado en los tramos de internet y compensar con RACK-TLP y la configuración para thin streams (tcp_thin_linear_timeouts). - Cifras de referencia: En Linux, RTO = tiempo de ida y vuelta + max(200 ms, desviación del RTT × 4). Se duplica con cada fallo, hasta un máximo de 120 segundos. Desde Linux 6.15, TCP_RTO_MAX_MS permite bajar ese máximo hasta 1 segundo. - En el gráfico: Siempre alto (RTO por conexión, RTO espurios) - Dónde mirar: Configuración del RTO mínimo del servidor (rto_min en ip route show; desde Linux 6.11, sysctl net.ipv4.tcp_rto_min_us), rto y rtt de ss -ti, e incremento de TcpExtTCPSpuriousRTOs en nstat - Se confirma si: En el servidor con el mínimo bajado, el rto de las conexiones de internet está pegado al rtt y TcpExtTCPSpuriousRTOs sube mucho. Con el valor predeterminado, el rto de las conexiones del juego supera al rtt en 200 ms o más, y cada pérdida detiene la conexión ese tiempo - Se descarta si: Si el rto sigue el cálculo predeterminado (unos rtt + 200 ms), hay pocos RTO espurios y aun así las pausas son especialmente largas, apunta a pérdidas seguidas o al método de recuperación (“Recuperación lenta en thin streams”, “Eliminación de opciones TCP en dispositivos intermedios”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · RTO = SRTT + max(G, 4·RTTVAR); recomienda un mínimo de 1 segundo; se duplica con cada fallo; si se fija un máximo, de al menos 60 segundos - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · En Linux, TCP_RTO_MIN es 200 ms y TCP_RTO_MAX, 120 segundos - [net/ipv4/tcp_input.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_input.c?h=v6.12) · Linux kernel · En Linux, RTO = SRTT + rttvar, y rttvar no baja del RTO mínimo (200 ms por defecto) - [tcp: add the ability to control max RTO](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=54a378f43425085d0684679d99735696b69165bc) · Linux kernel · Se añade la opción de socket TCP_RTO_MAX_MS (1–120 segundos), desde Linux 6.15 - [tcp: add sysctl_tcp_rto_min_us](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f086edef71be7174a16c1ed67ac65a085cda28b1) · Linux kernel · Se añade tcp_rto_min_us, el RTO mínimo predeterminado para todo el servidor, desde Linux 6.11 - [tcp: support TCP_RTO_MIN_US for set/getsockopt use](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f38805c5d26fe4af97837c10d58074a7496638bf) · Linux kernel · Se añade la opción de socket TCP_RTO_MIN_US, que fija el RTO mínimo de cada socket, desde Linux 6.15 - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us: 200000 por defecto (tienen prioridad la opción de ruta rto_min y la opción de socket TCP_RTO_MIN_US); tcp_rto_max_ms: 1,000–120,000 (120,000 por defecto); tcp_thin_linear_timeouts - [ip-route(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ip-route.8.html) · iproute2 · Opción rto_min por ruta: RTO mínimo al comunicarse con ese destino - [Thin-streams and TCP](https://docs.kernel.org/networking/tcp-thin.html) · Linux kernel · TCP_THIN_LINEAR_TIMEOUTS permite desactivar el backoff exponencial solo en las conexiones thin stream - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_USER_TIMEOUT: tiempo que pueden quedar datos sin confirmar antes de que se cierre la conexión - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rto (ms) y rtt de ss -i - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPSpuriousRTOs: RTO espurios detectados por F-RTO #### rt-thin · Recuperación lenta en thin streams · Thin streams fall back to RTO Cuando se envían paquetes pequeños y espaciados, como en un juego, el RTO llega antes de que se junten los “3 paquetes posteriores”. Ante la misma pérdida, la conexión se detiene mucho más tiempo que en una transferencia grande. - Por qué → Efecto → En pantalla: Con paquetes cada 100 ms más o menos, hay muy pocos paquetes todavía sin ACK (in-flight) → Juntar 3 ACK duplicados lleva más de 300 ms, así que antes salta el RTO (ping + 200 ms), que se duplica si hay pérdidas seguidas → Cada pérdida provoca un congelamiento de unos 0.3 s; si se pierde también la retransmisión, congelamiento de casi 1 segundo seguido de cámara rápida - Síntomas: Congelamiento, Cámara rápida / Factores: Pérdida de paquetes, Detención - A quién: Solo yo, Todo el servidor / Cuándo: De vez en cuando, al azar - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: activar TCP_NODELAY (con Nagle activado, RACK no tiene paquetes posteriores en los que basarse), mover los paquetes en tiempo real a una retransmisión propia sobre UDP. Cliente: activar TCP_NODELAY, enviar los paquetes en tiempo real con el mismo modelo que el servidor (UDP). - Tareas (Equipo de infraestructura): Usar RACK-TLP (predeterminado en los Linux recientes), evitar con tcp_thin_linear_timeouts que los RTO seguidos se dupliquen. - Cifras de referencia: Con paquetes cada 100 ms y un ping de 60 ms, la retransmisión rápida llega a los 360 ms aproximadamente (hasta que llegan 3 paquetes posteriores y vuelve su confirmación), y el RTO, a los 260 ms. Con RACK, se reenvía en cuanto vuelve la confirmación del paquete siguiente, a los 160 ms aproximadamente. Si los paquetes van separados más de 200 ms, RACK tampoco es más rápido que el RTO. - En el gráfico: Hueco y luego ráfaga (Datos recibidos por conexión, expiraciones del RTO) - Dónde mirar: Comparar los incrementos de TcpExtTCPTimeouts (expiraciones del RTO), TcpExtTCPFastRetrans (retransmisiones rápidas), TcpExtTCPLossProbes y TcpExtTCPLossProbeRecovery (TLP) en nstat, y mirar rto y backoff de las conexiones del juego con ss -ti. Comprobar también los valores de net.ipv4.tcp_recovery, tcp_early_retrans y tcp_sack del servidor - Se confirma si: Entre las retransmisiones, las expiraciones del RTO superan a las retransmisiones rápidas, y en las conexiones del juego se ve a menudo un backoff mayor que 0 (un RTO en curso). Mientras dura la pausa no se recibe nada, y al recuperarse llega todo de golpe - Se descarta si: Si las transferencias grandes del mismo servidor también se detienen igual de tiempo, es un problema de pérdida que no depende del tipo de conexión. Si se concentra en conexiones sin SACK ni marcas de tiempo, apunta a “Eliminación de opciones TCP en dispositivos intermedios” - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: Linux tuvo en su día una opción para thin streams que retransmitía con un solo ACK duplicado (tcp_thin_dupack), pero se eliminó en 2017, y hoy RACK cumple esa función. Con Nagle activado (TCP_NODELAY desactivado), mientras se espera la confirmación del paquete perdido tampoco se envían paquetes nuevos, así que RACK no tiene paquetes posteriores en los que basarse y hay que esperar al RTO. - Fuentes: - [Thin-streams and TCP](https://docs.kernel.org/networking/tcp-thin.html) · Linux kernel · Los thin streams, que envían de forma espaciada como los juegos, no aprovechan bien la retransmisión rápida y dependen de timeouts largos; el criterio es tener menos de 4 paquetes todavía sin ACK (in-flight) - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Retransmisión rápida al tercer ACK duplicado - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · RACK da un paquete por perdido cuando se ha entregado otro enviado después; la espera de TLP es 2·SRTT (si solo queda un paquete sin confirmar, se añade margen para el ACK retardado) - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · TCP_RTO_MIN 200 ms, criterio de thin stream (menos de 4 paquetes in-flight) y 6 reintentos lineales - [tcp: remove thin_dupack feature](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4a7f6009441144783e5925551c72e3f2e1b0839b) · Linux kernel · En enero de 2017 se eliminó thin_dupack (Linux 4.11), con la explicación de que RACK cumple esa función - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_thin_linear_timeouts: en thin streams, el RTO no se duplica durante un máximo de 6 expiraciones (desactivado por defecto) - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_NODELAY desactiva el algoritmo de Nagle - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nombres de contador que muestra nstat: TCPTimeouts, TCPFastRetrans, TCPLossProbes y TCPLossProbeRecovery - [net/ipv4/tcp_timer.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · TCPTimeouts sube cuando expira el temporizador de retransmisión (RTO) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPFastRetrans (retransmisiones fuera del estado Loss), TcpExtTCPLossProbes (TLP enviados) y TcpExtTCPLossProbeRecovery (pérdidas recuperadas con TLP) - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rto (ms) y backoff (veces que se ha duplicado el RTO) de ss -i #### rt-sack-stripped · Eliminación de opciones TCP en dispositivos intermedios · Middlebox strips TCP options Si algunos firewalls o aceleradores eliminan o modifican las opciones TCP, cuando se pierden varios paquetes solo se recupera uno por cada ida y vuelta, o la ventana (lo que se puede enviar de una vez) se reduce, y todo va más lento. - Por qué → Efecto → En pantalla: La “normalización TCP” de un firewall o un acelerador antiguo elimina las opciones de SACK, marcas de tiempo (timestamps) y escalado de ventana → Si se pierden varios paquetes, se recupera uno por cada ida y vuelta, y la ventana queda limitada a 64 KB → Cada pérdida provoca un congelamiento mucho más largo (sin SACK tampoco se puede usar RACK-TLP), seguido de cámara rápida al liberarse. Las transferencias grandes, como los parches, también van lentas - Síntomas: Congelamiento, Cámara rápida / Factores: Detención, Latencia - A quién: Una región o un ISP, Todo el servidor / Cuándo: Siempre - Responsable principal: Infraestructura de red (Equipo de infraestructura) / También: Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de infraestructura): Red: desactivar la normalización TCP en ese dispositivo, revisar también la aleatorización de números de secuencia del firewall, comparar las opciones del SYN con capturas de paquetes en los dos extremos. Servidores/SO: comprobar en ss -ti si las conexiones sin sack ni wscale se concentran en una ruta concreta (en Windows, ts puede estar desactivado según la configuración, así que si solo falta ts puede ser normal), comprobar que net.ipv4.tcp_sack del servidor vale 1. - En el gráfico: Siempre alto (Recuperaciones iniciadas sin SACK (TcpExtTCPRenoRecovery)) - Dónde mirar: Si cada conexión muestra sack y wscale en ss -ti, la proporción entre TcpExtTCPRenoRecovery (recuperaciones iniciadas sin SACK) y TcpExtTCPSackRecovery en nstat, y TcpExtTCPSACKDiscard (bloques SACK descartados por incoherentes). En las rutas sospechosas, capturar el SYN en los dos extremos y comparar las opciones (tcp.options.sack_perm de Wireshark, etc.) - Se confirma si: Solo las conexiones que pasan por una ruta o un dispositivo concreto carecen de sack y wscale, y TcpExtTCPRenoRecovery pesa mucho. La opción de SACK permitido que llevaba el SYN del emisor no aparece en el SYN que recibe el otro extremo. Si la causa es la aleatorización de números de secuencia, las opciones siguen ahí, pero sube TcpExtTCPSACKDiscard - Se descarta si: Si sack falta en todas las conexiones, revisar primero el valor de net.ipv4.tcp_sack del servidor. Si las opciones están intactas y TcpExtTCPSACKDiscard no cambia, la lentitud de la recuperación viene de otro lado (“Recuperación lenta en thin streams”) - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Para saber más: SACK puede romperse aunque las opciones sigan presentes. Si la aleatorización de números de secuencia (sequence randomization) del firewall cambia solo el número de secuencia de la cabecera y deja intactos los números dentro del SACK, el emisor descarta esos SACK incoherentes. El resultado es el mismo si en el servidor se puso tcp_sack=0 durante el problema de seguridad de SACK de 2019 y luego se olvidó volver a activarlo. - Fuentes: - [RFC 2018: TCP Selective Acknowledgment Options](https://www.rfc-editor.org/rfc/rfc2018) · IETF · Sin SACK, con solo ACK acumulativos, se puede conocer un único paquete perdido por cada ida y vuelta - [RFC 7323: TCP Extensions for High Performance](https://www.rfc-editor.org/rfc/rfc7323) · IETF · Sin la opción de escalado de ventana, la ventana es como máximo 2^16 = 64 KiB - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · RACK-TLP requiere usar SACK - [net/ipv4/tcp_output.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_output.c?h=v6.12) · Linux kernel · En Linux, TLP solo se programa en las conexiones que usan SACK - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_sack: 1 por defecto (activado) - [misc/ss.c](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/misc/ss.c?h=v6.12.0) · iproute2 · ss -ti muestra ts, sack y wscale:envío,recepción según las opciones que use la conexión - [tcp: limit payload size of sacked skbs](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3b4929f65b0d8249f19a50245cd88ed1a2f78cff) · Linux kernel · Commit que corrige la vulnerabilidad de procesamiento de SACK de 2019 (CVE-2019-11477) - [Linux and FreeBSD Kernel: Multiple TCP-based remote denial of service vulnerabilities (NFLX-2019-001)](https://raw.githubusercontent.com/Netflix/security-bulletins/master/advisories/third-party/2019-001.md) · Netflix · Como medida temporal, en su momento se recomendó tcp_sack=0 (desactivar el procesamiento de SACK) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPRenoRecovery (recuperación iniciada sin SACK) y TcpExtTCPSackRecovery (recuperación iniciada con SACK), TcpExtTCPSACKDiscard (bloques SACK no válidos) - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtro de visualización tcp.options.sack_perm (opción de SACK permitido en el SYN) #### rt-zero-window · Ventana cero (una detención que parece retransmisión) · Zero window, often mistaken for retransmission Cuando el programa receptor no lee el socket a tiempo y el búfer se llena, el emisor deja de enviar y solo manda sondas de ventana cero. El problema no está en la red. - Por qué → Efecto → En pantalla: El cliente deja de procesar frames o un hilo del servidor se bloquea, y nadie lee el socket → La ventana de recepción llega a 0, y el emisor deja de enviar y solo manda sondas (a intervalos cada vez más largos) → Congelamiento seguido de cámara rápida. En la captura de paquetes aparece “ZeroWindow” y no hay pérdida - Síntomas: Congelamiento, Cámara rápida / Factores: Detención - A quién: Solo yo, Todo el servidor / Cuándo: Cuando se junta mucha gente, De vez en cuando, al azar - Responsable principal: Desarrollo de cliente (Equipo de desarrollo) / También: Desarrollo de servidor (Equipo de desarrollo), Infraestructura de servidores (Equipo de infraestructura) - Tareas (Equipo de desarrollo): Empezar por el lado que envió el ZeroWindow en la captura de paquetes (el que no lee el socket), leer la red sin parar en un hilo aparte, dar un tamaño adecuado al búfer de recepción. Cliente: resolver las causas de las paradas de frames, como la carga o el GC. Servidor: resolver lo que bloquea al hilo que lee el socket. - Tareas (Equipo de infraestructura): Añadir al monitoreo TcpExtTCPToZeroWindowAdv del nstat del servidor (veces que el servidor anunció una ventana de recepción 0; si sube, el problema está en el servidor y hay que pasarlo a desarrollo de servidor), facilitar capturas de paquetes del lado del servidor. - En el gráfico: Hueco y luego ráfaga (Datos recibidos por conexión, ventanas cero) - Dónde mirar: En la captura de paquetes, buscar con el filtro de Wireshark tcp.analysis.zero_window qué lado anunció la ventana 0. En el nstat del servidor, ver por separado TcpExtTCPToZeroWindowAdv (el servidor anunció ventana 0) y TcpExtTCPWinProbe (sondas enviadas ante la ventana 0 del otro extremo), y el Recv-Q de los sockets del servidor (bytes que el programa aún no ha leído, en ss) - Se confirma si: Durante la pausa no hay retransmisiones; solo circulan ventanas cero y sondas. Si suben TcpExtTCPToZeroWindowAdv o el Recv-Q de los sockets del servidor, es el servidor el que no lee a tiempo; si sube TcpExtTCPWinProbe, es el cliente - Se descarta si: Si en la captura no hay ventanas cero y se reenvían los mismos datos, apunta a pérdida o a retransmisiones espurias - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Casos reales: roblox-2021 - Fuentes: - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · Con la ventana de recepción en 0, el emisor envía sondas de ventana cero y alarga el intervalo entre sondas de forma exponencial - [7.5. TCP Analysis](https://www.wireshark.org/docs/wsug_html_chunked/ChAdvTCPAnalysis.html) · Wireshark · TCP ZeroWindow: paquete con el que el receptor anuncia ventana 0 y hace que el emisor deje de enviar - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtros de visualización tcp.analysis.zero_window y tcp.analysis.zero_window_probe - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPToZeroWindowAdv: veces que la ventana de recepción anunciada pasó de un valor distinto de 0 a 0 - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nombres de contador que muestra nstat: TCPToZeroWindowAdv y TCPWinProbe - [net/ipv4/tcp_output.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_output.c?h=v6.12) · Linux kernel · TCPWinProbe: sube con cada sonda (tcp_send_probe0) enviada cuando la ventana de recepción del otro extremo es 0 - [net/ipv4/tcp_diag.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · En una conexión, el Recv-Q de ss es el número de bytes recibidos que el programa aún no ha leído #### rt-syn · Retransmisión de la solicitud de conexión (SYN) · SYN retransmission on connect Si una solicitud de conexión se pierde porque se desborda la cola de conexiones pendientes (backlog) o porque la bloquea un firewall, el SO del cliente la reenvía al cabo de 1 segundo y luego a intervalos cada vez más largos. - Por qué → Efecto → En pantalla: Justo después de un mantenimiento, una avalancha de conexiones desborda la cola de conexiones pendientes del servidor, o un firewall o la protección DDoS descarta los SYN → El SO del cliente retransmite el SYN a intervalos predefinidos a partir de 1 segundo (en los Linux antiguos, 1 s → 2 s → 4 s) → Tras presionar el botón de conexión, la espera es de segundos exactos, como 1 o 3 s, y si sigue fallando, el juego no conecta o se queda en carga infinita - Síntomas: No conecta / carga infinita / Factores: Pérdida de paquetes - A quién: Todo el servidor, Una región o un ISP / Cuándo: Al conectar o tras un mantenimiento - Responsable principal: Desarrollo de servidor (Equipo de desarrollo) / También: Infraestructura de servidores (Equipo de infraestructura), Infraestructura de red (Equipo de infraestructura), Desarrollo de cliente (Equipo de desarrollo) - Tareas (Equipo de desarrollo): Servidor: aumentar el argumento backlog de listen (junto con somaxconn), hacer que el servidor del juego llame a accept a tiempo, implantar un sistema de cola de inicio de sesión. Cliente: alargar el intervalo entre reintentos de conexión (repartidos al azar). - Tareas (Equipo de infraestructura): Servidores/SO: detectar el desbordamiento de la cola de conexiones pendientes con TcpExtListenOverflows y TcpExtListenDrops de nstat y con el aviso “Possible SYN flooding” del log, aumentar somaxconn (junto con el argumento de listen), usar SYN cookies. Red: relajar los límites de SYN del firewall y de la protección DDoS. - Cifras de referencia: En Linux (Android incluido), la primera retransmisión del SYN es al cabo de 1 segundo. Los kernels antiguos duplican después el intervalo cada vez, así que reenvían a los 1, 3, 7, 15 s …; los 6.5 y posteriores reenvían cinco veces, a los 1, 2, 3, 4 y 5 s, y después duplican el intervalo (7, 11, 19 s …) (tcp_syn_linear_timeouts=4). Muchos teléfonos Android siguen usando el kernel con el que salieron aunque se actualice el SO, así que puede variar entre dispositivos con la misma versión de Android. En cualquier caso, si todo falla, se abandona al cabo de unos 2 minutos. En Windows, según la versión y la configuración, el intervalo empieza en 1 o 3 segundos y va creciendo, y como se reenvía de 2 a 4 veces, se abandona en 20–30 segundos (el valor de esa computadora se ve en Max SYN Retransmissions de netsh int tcp show global). - En el gráfico: Avalancha tras la apertura (Intentos de conexión, desbordamientos de la cola de conexiones pendientes) - Dónde mirar: TcpExtListenOverflows y TcpExtListenDrops en el nstat del servidor y el aviso “Possible SYN flooding on port” en dmesg, y si con ss -lnt el Recv-Q (conexiones esperando accept) del socket de escucha llega al Send-Q (límite del backlog). Con una captura en el servidor, comprobar si llegan los SYN y si se devuelve el SYN-ACK - Se confirma si: En la avalancha de conexiones justo después del mantenimiento, sube TcpExtListenOverflows y el Recv-Q se queda pegado al Send-Q. En la captura, los SYN del mismo cliente vuelven a llegar a intervalos de segundos y el servidor no responde - Se descarta si: Si los SYN no llegan al servidor y sus contadores no cambian, los descartó el firewall o la protección DDoS de delante: revisar los límites de SYN y los logs de descartes de ese dispositivo. Si el servidor envió el SYN-ACK y aun así la conexión tarda, hay pérdida en el sentido de vuelta - Se verifica con: Con herramientas de infraestructura (no hace falta código del juego) - Fuentes: - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · Primer RTO: TCP_TIMEOUT_INIT = 1 segundo (valor inicial de RFC 6298) - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · RTO inicial de 1 segundo, que se duplica con cada retransmisión - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_syn_retries: 6 por defecto; tcp_syn_linear_timeouts: 4 por defecto (RTO del SYN 1, 1, 1, 1, 1, 2, 4 …); última retransmisión a los 67 s y abandono a los 131 s; somaxconn: 4096 por defecto; tcp_syncookies: 1 por defecto - [tcp: make the first N SYN RTO backoffs linear](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ccce324dabfe2143519daf50ed8b1ef1d0c542f7) · Linux kernel · Commit que convierte las primeras retransmisiones del SYN en intervalos fijos, desde Linux 6.5 (el valor predeterminado 4 sigue el comportamiento de macOS e iOS) - [Android common kernels](https://source.android.com/docs/core/architecture/kernel/android-common) · Android (Google) · Se mantienen a la vez los kernels comunes 5.10 a 6.18, y un kernel de una plataforma anterior (p. ej., android14-6.1) puede usarse para lanzar o actualizar dispositivos Android nuevos - [TcpMaxConnectRetransmissions](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc938209(v=technet.10)) · Microsoft · Valor predeterminado de los Windows antiguos: 2 retransmisiones del SYN, empezando con una espera de 3 segundos que se duplica cada vez; tras la última, espera el doble y abandona (3+6+12=21 segundos) - [TCP/IP connectivity issues troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/tcp-ip-connectivity-issues-troubleshooting) · Microsoft · El número de retransmisiones del SYN varía según el SO y se ve en Max SYN Retransmissions de netsh int tcp show global - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · El argumento backlog de listen se recorta a somaxconn (4096 por defecto desde Linux 5.4; antes, 128) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · Cuando la cola de accept se llena, se descartan los SYN y suben a la vez TcpExtListenOverflows y TcpExtListenDrops; TcpExtTCPSynRetrans - [net/ipv4/tcp_input.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_input.c?h=v6.12) · Linux kernel · Mensaje de log “Possible SYN flooding on port …” - [net/ipv4/tcp_diag.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · En un socket de escucha, el Recv-Q de ss es el número de conexiones que esperan accept, y el Send-Q, el límite del backlog ## Fuentes por capítulo ### #l-client-game - [Slow rendering](https://developer.android.com/topic/performance/vitals/render) · Android (Google) · Para llegar a 60 FPS hay que dibujar cada frame en 16 ms; si tarda más, se saltan frames y se ven tirones - [Interpolation and extrapolation (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/interpolation.html) · Unity · Interpolación, que dibuja la transición entre snapshots que llegan espaciados, y extrapolación, que continúa con la misma dirección y velocidad cuando los datos se retrasan, con su límite - [Introduction to prediction (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/intro-to-prediction.html) · Unity · Predicción: el cliente se mueve primero con sus propios inputs, sin esperar el resultado del servidor, y corrige si difiere del servidor - [Peeking into VALORANT's Netcode](https://technology.riotgames.com/news/peeking-valorants-netcode) · Riot Games · Igualar con un búfer los datos que llegan de forma irregular da suavidad, pero añade esa misma latencia; si la estimación falla, el personaje salta o se desliza - [Garbage collection modes](https://docs.unity3d.com/Manual/performance-incremental-garbage-collection.html) · Unity · Pico de GC de la simulación: sin el GC incremental, el hilo principal se detiene mientras se recorre todo el heap y supera el límite de 16 ms por frame - [Scripting.GarbageCollector.CollectIncremental](https://docs.unity3d.com/ScriptReference/Scripting.GarbageCollector.CollectIncremental.html) · Unity · Porción de tiempo de 3 ms del GC incremental en la simulación: valor predeterminado de incrementalTimeSliceNanoseconds, 3 ms - [Shader loading](https://docs.unity3d.com/Manual/shader-loading.html) · Unity · Carga de una zona nueva en la simulación: la primera vez que se usa una variante de shader, puede haber una detención mientras el driver la prepara para la GPU - [Frame Pacing library](https://developer.android.com/games/sdk/frame-pacing) · Android (Google) · Límite de V-Sync en la simulación: una pantalla de 60 Hz vuelve a mostrar el frame anterior si no hay uno nuevo - [Set fixed timestep to optimize physics simulation frequency](https://docs.unity3d.com/Manual/physics-optimization-cpu-frequency.html) · Unity · Recuperación con paso fijo en la simulación: si un frame dura más que el intervalo del paso, se ejecutan varios pasos en un mismo frame y la carga aumenta - [Handling variation in time](https://docs.unity3d.com/Manual/time-handling-variations.html) · Unity · Límite de recuperación de la simulación (allí, hasta 5 pasos por frame): Unity limita el tiempo de juego de un frame a 1/3 de segundo como máximo para evitar la espiral de recuperación, y el reloj del juego se retrasa lo que exceda ### #l-client-os - [Multitasking](https://learn.microsoft.com/en-us/windows/win32/procthread/multitasking) · Microsoft · Multitarea apropiativa (preemptive): cada hilo recibe una porción de tiempo (unos 20 ms, según el SO y la CPU) y, cuando la agota, pasa el turno al siguiente hilo - [Scheduling Priorities](https://learn.microsoft.com/en-us/windows/win32/procthread/scheduling-priorities) · Microsoft · Entre los hilos listos para ejecutarse, los de mayor prioridad reciben por turnos (round robin) las porciones de tiempo - [Priority Boosts](https://learn.microsoft.com/en-us/windows/win32/procthread/priority-boosts) · Microsoft · Sube la prioridad del proceso de la ventana en primer plano a un nivel igual o superior al de los procesos en segundo plano - [socket(7) — Linux manual page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux man-pages · Cada socket tiene un búfer de recepción (SO_RCVBUF), cuyo tamaño predeterminado y máximo fija la configuración del sistema - [Wi-Fi low-latency mode](https://source.android.com/docs/core/connect/wifi-low-latency) · Android (Google) · En el modo Wi-Fi de baja latencia de Android 10 o posterior, el framework desactiva explícitamente el ahorro de energía del Wi-Fi (doze) cuando la app está en primer plano y la pantalla encendida - [Cached apps freezer](https://source.android.com/docs/core/perf/cached-apps-freezer) · Android (Google) · Android 14 o posterior congela a los 10 segundos las apps en estado de caché y les impide usar la CPU - [Extending your app’s background execution time](https://developer.apple.com/documentation/uikit/extending-your-app-s-background-execution-time) · Apple · iOS suspende unos segundos después las apps que pasan a segundo plano - [_WDF_TIMER_CONFIG (wdftimer.h)](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdftimer/ns-wdftimer-_wdf_timer_config) · Microsoft · Temporizador de 15.6 ms de la simulación: intervalo predeterminado del tick del reloj del sistema de Windows, 15.6 ms - [timeBeginPeriod function (timeapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod) · Microsoft · Temporizador de 1 ms de la simulación: un programa puede pedir más resolución del temporizador con timeBeginPeriod - [Customize the Windows performance power slider](https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/customize-power-slider) · Microsoft · Modo de ahorro de energía de la simulación: el modo de energía de Windows cambia la configuración de energía y de CPU para alargar la batería a costa del rendimiento - [Thermal API](https://developer.android.com/games/optimize/adpf/thermal) · Android (Google) · Calentamiento del teléfono en la simulación: el dispositivo mantiene el alto rendimiento solo durante un tiempo limitado y después aplica throttling por temperatura ### #l-memory - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Base de la tabla “Cifras de latencia”: caché L1 0.5 ns, L2 7 ns, memoria principal 100 ns, ida y vuelta dentro del mismo centro de datos 0.5 ms, búsqueda en disco 10 ms (datos de 2009; las cifras de caché de la tabla son aproximaciones algo distintas) - [Solidigm™ D7-P5520 and D7-P5620 Product Brief](https://www.solidigm.com/products/data-center/product-briefs/d7-p5520-p5620-product-brief.html) · Solidigm · Latencia del 99.99% (four-nines latency) de 130 µs en un SSD NVMe para servidores: fundamento de que la lectura de SSD y la relectura desde swap de la tabla rondan los 100 µs - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us: 200,000 µs por defecto, es decir, una espera mínima de retransmisión TCP de 200 ms en Linux (fila de retransmisión TCP de la tabla) - [What is NUMA?](https://docs.kernel.org/mm/numa.html) · Linux kernel · La memoria del lado de otra CPU (remota) es más lenta de acceder y tiene menos ancho de banda que la local (fila NUMA de la tabla) - [JEP 439: Generational ZGC](https://openjdk.org/jeps/439) · OpenJDK · Las pausas de G1 van de varios ms a varios segundos, y las de ZGC, 1 ms o menos (GC de todo el heap de cientos de ms a varios segundos en el texto; GC de heap grande de 1 segundo en la tabla) - [Available Collectors](https://docs.oracle.com/en/java/javase/25/gctuning/available-collectors.html) · Oracle · ZGC cede un poco de throughput a cambio de pausas máximas menores de 1 ms, que no dependen del tamaño del heap - [Garbage Collector Implementation](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-collector-implementation.html) · Oracle · Recolección generacional: la recolección minor, que solo recorre la generación joven, es corta, y la major, que recorre todo el heap, tarda mucho más (modo generacional de la simulación del GC) - [The Z Garbage Collector](https://docs.oracle.com/en/java/javase/25/gctuning/z-garbage-collector1.html) · Oracle · ZGC hace el trabajo costoso de forma concurrente y no se detiene más de 1 ms, pero si no libera lo suficiente, la aplicación puede detenerse esperando al GC (modo concurrente de la simulación del GC) - [A Guide to the Go Garbage Collector](https://go.dev/doc/gc-guide) · Go · La fase de marcado del GC usa el 25% de la CPU y el programa va más lento mientras dura; si se asigna mucho, las goroutines se retrasan porque ayudan al GC (assist) (modo concurrente de la simulación del GC) - [Go 1.8 Release Notes](https://go.dev/doc/go1.8) · Go · Las pausas del GC de Go suelen ser menores de 100 µs - [Debug a memory leak in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-memory-leak) · .NET · Aunque haya GC, si se siguen referenciando objetos que ya no hacen falta, hay fugas - [Concepts overview](https://docs.kernel.org/admin-guide/mm/concepts.html) · Linux kernel · Cuando falta memoria, se liberan la caché de páginas y las páginas que se pueden enviar a swap y, si aun así no alcanza, el OOM killer termina procesos a la fuerza (simulación de fuga de memoria) ### #l-disk - [Exos X18 Data Sheet](https://www.seagate.com/www-content/datasheets/pdfs/exos-x18-mango-DS2045-1N-2007US-en_US.pdf) · Seagate · HDD de 7,200 rpm: 170 IOPS en lectura aleatoria de 4K, latencia rotacional media de 4.16 ms (base de la cifra del HDD en el texto, algo más de 150 por segundo, y del HDD de la simulación de disco) - [D3-S4520 SSD](https://www.solidigm.com/products/data-center/d3/s4520.html) · Solidigm · SSD SATA: lectura/escritura aleatoria de 4 KB de hasta 92K/48K IOPS (las “decenas de miles” del SSD en el texto) - [Solidigm™ D7-P5520 and D7-P5620 Product Brief](https://www.solidigm.com/products/data-center/product-briefs/d7-p5520-p5620-product-brief.html) · Solidigm · SSD NVMe: lectura/escritura aleatoria de 1,000K/200K IOPS (los “cientos de miles” del texto) - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · gp3: 3,000 IOPS de base; gp2 usa créditos de E/S para hacer ráfagas de hasta 3,000 IOPS y, cuando se agotan, vuelve al rendimiento base - [Amazon EBS-optimized instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html) · AWS · Las instancias pequeñas solo dan el rendimiento máximo de EBS durante 30 minutos una vez cada 24 horas y luego vuelven al rendimiento base (p. ej., t4g.2xlarge: base de 4,000 IOPS y máximo de 15,700; supuesto de la opción “En la nube (con ráfaga)” de la simulación de disco) - [Managed disk bursting](https://learn.microsoft.com/en-us/azure/virtual-machines/disk-bursting) · Microsoft Azure · Los discos y VM pequeños pueden hacer ráfagas de hasta 30 minutos con créditos - [Concepts overview](https://docs.kernel.org/admin-guide/mm/concepts.html) · Linux kernel · Los datos escritos en un archivo van primero a la caché de páginas, se marcan como dirty y se escriben en disco más tarde - [Documentation for /proc/sys/vm/](https://docs.kernel.org/admin-guide/sysctl/vm.html) · Linux kernel · Cuando las escrituras pendientes llegan a dirty_ratio, el propio proceso que escribe tiene que hacer la escritura en disco (límite de escritura del SO en la simulación de disco) - [fsync(2) — Linux manual page](https://man7.org/linux/man-pages/man2/fsync.2.html) · Linux man-pages · fsync se bloquea hasta que el dispositivo confirma que terminó la escritura ### #l-db - [How MySQL Uses Indexes](https://dev.mysql.com/doc/refman/8.4/en/mysql-indexes.html) · MySQL · Sin índice, se lee toda la tabla desde la primera fila (escaneo completo) - [InnoDB Locking](https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html) · MySQL · Las solicitudes que quieren modificar la misma fila esperan hasta que termina la transacción que tiene el bloqueo de fila (fila caliente) - [Number Of Database Connections](https://wiki.postgresql.org/wiki/Number_Of_Database_Connections) · PostgreSQL · Una vez agotados los recursos de la BD, añadir conexiones reduce el throughput (fundamento de que en la simulación de BD, si faltan núcleos de CPU, todo va lento aunque se amplíe el pool) - [WAL Configuration (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-configuration.html) · PostgreSQL · El checkpoint es una operación costosa que escribe de golpe las páginas sucias (dirty) cada 5 minutos o cada 1 GB de WAL por defecto; repartir las escrituras evita avalanchas de E/S - [Semisynchronous Replication](https://dev.mysql.com/doc/refman/8.4/en/replication-semisync.html) · MySQL · Con replicación asíncrona, si cae la BD principal, puede que las transacciones confirmadas (commit) no estén en la BD de reserva (rollback tras el failover) - [Log-Shipping Standby Servers (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/warm-standby.html) · PostgreSQL · La replicación en streaming es asíncrona por defecto, así que hay un retraso entre el commit y su aplicación en la réplica (lo recién escrito no se ve en la réplica) - [Asynchronous Commit (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-async-commit.html) · PostgreSQL · Agrupar las escrituras y volcarlas más tarde es más rápido, a cambio de perder los cambios recientes si hay un fallo (la misma estructura que un servidor de juego que guarda cada pocos minutos) ### #judge - [Service Level Objectives (Site Reliability Engineering, ch. 4)](https://sre.google/sre-book/service-level-objectives/) · Google · Ver con percentiles (50, 95 y 99) la forma y la cola de la distribución de latencia, que la media oculta - [The Tail at Scale](https://research.google/pubs/the-tail-at-scale/) · Google · Las latencias largas ocasionales (latencia de cola) dominan la experiencia del servicio completo a medida que crece la escala - [RFC 3550: RTP, A Transport Protocol for Real-Time Applications](https://www.rfc-editor.org/rfc/rfc3550) · IETF · Definición y cálculo del jitter entre llegadas (interarrival jitter) - [RFC 1812: Requirements for IP Version 4 Routers](https://www.rfc-editor.org/rfc/rfc1812) · IETF · Los routers deben poder limitar la frecuencia de los mensajes de error ICMP, como Time Exceeded, y también pueden limitar los Echo Reply (cuidado al interpretar mtr y ping) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · icmp_ratelimit e icmp_ratemask: Linux limita por defecto respuestas ICMP como Time Exceeded y Destination Unreachable - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · Campos rtt (tiempo medio de ida y vuelta)/rttvar de ss -ti - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · pidstat -t: uso de CPU por hilo - [bcc tools: runqlat examples](https://raw.githubusercontent.com/iovisor/bcc/master/tools/runqlat_example.txt) · IO Visor · Medición de la distribución de la latencia de la cola de ejecución (tiempo que un hilo esperó CPU) - [RIPE Atlas documentation](https://atlas.ripe.net/docs/) · RIPE NCC · Herramienta pública de monitoreo sintético que ejecuta ping y traceroute desde puntos de medición de todo el mundo - [GeoLite2 Free Geolocation Data](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data) · MaxMind · Base de datos pública que asocia país y ASN a cada dirección IP - [View CloudWatch metrics for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · Monitoreo básico cada 5 minutos y monitoreo detallado cada minuto (el intervalo de agregación oculta los picos cortos) ### #l-nic - [NAPI](https://docs.kernel.org/networking/napi.html) · Linux kernel · Cuando el dispositivo avisa de paquetes nuevos con una interrupción, el kernel los saca y procesa con NAPI; la agrupación (coalescencia) de interrupciones suele hacerla el dispositivo - [Scaling in the Linux Networking Stack](https://docs.kernel.org/networking/scaling.html) · Linux kernel · Estructura en la que RSS reparte varias colas de recepción entre varios núcleos, con una interrupción por cola y un hash para elegir la cola - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · Paquetes descartados por el dispositivo por falta de búfer (rx_missed_errors) y estadísticas por driver de ethtool -S - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Configuración y consulta del búfer circular (-G), la coalescencia de interrupciones (-C), el hash de recepción (-N) y las estadísticas (-S) - [How to receive a million packets per second](https://blog.cloudflare.com/how-to-receive-a-million-packets/) · Cloudflare · Medición en la que una sola cola y un solo núcleo se atascan en unos 350,000–430,000 paquetes por segundo, y hacen falta más colas y núcleos para recibir 1 millón de pps (la simulación supone un throughput por núcleo más holgado, de 700,000 pps) - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · Al superar los límites de ancho de banda, PPS y seguimiento de conexiones de una instancia en la nube, los paquetes se encolan fuera de la instancia y luego se descartan; contadores de límite superado ### #l-server-os - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · Cola de conexiones pendientes (backlog) y límite somaxconn (4,096 por defecto desde la 5.4; antes, 128) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · Cuando la cola de accept se llena, Linux descarta las solicitudes de conexión (SYN) y sube TcpExtListenOverflows - [listen function (winsock2.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen) · Microsoft · Cuando la cola se llena, Windows devuelve WSAECONNREFUSED al cliente - [getrlimit(2) — Linux manual page](https://man7.org/linux/man-pages/man2/getrlimit.2.html) · Linux man-pages · RLIMIT_NOFILE: límite de fd que puede abrir un proceso; al superarlo, EMFILE - [systemd-system.conf(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd-system.conf.5.html) · systemd · Límite de fd predeterminado de los servicios, 1024:524288 (el error de configuración de 1,024 fd en la simulación) - [The /proc Filesystem](https://docs.kernel.org/filesystems/proc.html) · Linux kernel · El OOM killer elige el proceso que va a terminar por una puntuación (badness) basada en la proporción de memoria usada, que se ajusta con oom_score_adj - [Control Group v2](https://docs.kernel.org/admin-guide/cgroup-v2.html) · Linux kernel · Si se llega a memory.max y no se puede reducir, el OOM killer actúa dentro de ese cgroup; cpu.max limita la CPU - [proc_stat(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_stat.5.html) · Linux man-pages · steal: tiempo de CPU que, en un entorno virtualizado, se llevó otro sistema operativo - [Exponential Backoff And Jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/) · AWS · Con solo backoff exponencial los reintentos se concentran; mezclar aleatoriedad (jitter) reduce la contención (método de reintento de la simulación) ### #l-socket - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · TCP es un flujo de bytes confiable y en orden; definiciones de Nagle y del ACK retardado - [RFC 768: User Datagram Protocol](https://www.rfc-editor.org/rfc/rfc768) · IETF · UDP no garantiza la entrega ni evita los duplicados - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Las apps UDP que necesitan confiabilidad u orden tienen que implementarlos por su cuenta - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · Opciones de socket TCP como TCP_NODELAY, TCP_USER_TIMEOUT y keepalive - [socket(7) — Linux manual page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux man-pages · Opciones de socket SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE y SO_LINGER - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Retransmisión rápida con 3 ACK duplicados; tras una retransmisión por temporizador, la ventana de congestión vuelve a 1 segmento (la regla de manual de la simulación) - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · RACK, que detecta la pérdida por la hora de envío, sin contar ACK duplicados - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · Recomienda un RTO mínimo de 1 segundo; backoff que lo duplica en cada expiración - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us de Linux: 200 ms por defecto; la detección de pérdidas usa RACK (tcp_recovery) - [include/net/tcp.h (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · ACK retardado de 40 ms en Linux en la simulación: TCP_DELACK_MIN (HZ/25 = 40 ms), máximo TCP_DELACK_MAX (HZ/5 = 200 ms) - [Design issues - Sending small data segments over TCP with Winsock](https://learn.microsoft.com/en-us/previous-versions/troubleshoot/windows/win32/data-segment-tcp-winsock) · Microsoft · ACK retardado de 200 ms en Windows en la simulación: al recibir datos se activa un temporizador de ACK retardado de 200 ms y, combinado con Nagle, los paquetes pequeños esperan al ACK - [RFC 896: Congestion Control in IP/TCP Internetworks](https://www.rfc-editor.org/rfc/rfc896) · IETF · Propósito original de la regla de Nagle: el problema de los terminales remotos, que enviaban un paquete de 41 bytes por cada byte tecleado - [send(2) — Linux manual page](https://man7.org/linux/man-pages/man2/send.2.html) · Linux man-pages · Si el búfer de envío está lleno, un send() bloqueante no retorna ### #journey - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Latencia de transmisión en fibra óptica de 5 µs/km (5 ms en un sentido para 1,000 km); con 150 ms en un sentido o menos, la mayoría de las aplicaciones apenas lo notan, aunque las tareas muy interactivas se ven afectadas incluso por debajo de 100 ms - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Escala del tramo de internet según la ubicación del servidor en la simulación: desde Seúl, región de Busan 8 ms, Tokio 30 ms, Singapur 68 ms, costa oeste de EE. UU. 124–136 ms, Europa 234–244 ms (medianas de ida y vuelta) - [The Internet at the Speed of Light (HotNets 2014)](https://conferences.sigcomm.org/hotnets/2014/papers/hotnets-XIII-final111.pdf) · ACM · Factor de ruta 1.5 de la simulación: las rutas reales entre routers miden una mediana de 1.5 veces la línea recta de fibra - [Report ITU-R M.2134: Requirements related to technical performance for IMT-Advanced radio interface(s)](https://www.itu.int/pub/R-REP-M.2134-2008) · ITU · Requisito de latencia en un sentido del tramo de radio de LTE-Advanced: menos de 10 ms (sin carga y con paquetes pequeños; el valor de LTE de la simulación supone que se le suman la carga y la espera de planificación) - [Report ITU-R M.2410: Minimum requirements related to technical performance for IMT-2020 radio interface(s)](https://www.itu.int/pub/R-REP-M.2410-2017) · ITU · Requisito de latencia en un sentido del tramo de radio de 5G (IMT-2020): 4 ms (eMBB, sin carga) - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · Cola del router en la simulación: en los routers domésticos, cuando coinciden subida y bajada, la latencia de cola puede subir a cientos de ms (hasta unos 400 ms) - [Maximum transmission unit and maximum segment size](https://developers.cloudflare.com/magic-transit/reference/mtu-mss/) · Cloudflare · Paso por la protección DDoS en la simulación: solo el tráfico entrante pasa por la red de protección, y las respuestas del servidor salen directas a internet (DSR) ### #l-home - [RFC 7567: IETF Recommendations Regarding Active Queue Management](https://www.rfc-editor.org/rfc/rfc7567) · IETF · La acumulación en las colas de los dispositivos es una de las principales causas de latencia en internet; recomendación de usar gestión de colas (AQM) por defecto - [RFC 8289: Controlled Delay Active Queue Management](https://www.rfc-editor.org/rfc/rfc8289) · IETF · Objetivo de espera de 5 ms e intervalo de observación de 100 ms de CoDel (la cola SQM de unos 5 ms de la simulación) - [RFC 8290: The Flow Queue CoDel Packet Scheduler and Active Queue Management Algorithm](https://www.rfc-editor.org/rfc/rfc8290) · IETF · FQ-CoDel: separa una cola por flujo según dirección y puerto, y da salida primero a los flujos pequeños que no forman cola - [What Can I Do About Bufferbloat?](https://www.bufferbloat.net/projects/bloat/wiki/What_can_I_do_about_Bufferbloat/) · Bufferbloat.net · Usar un router compatible con SQM como cake o fq_codel, y ajustar la velocidad del SQM midiendo la latencia bajo carga - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · Medición de 34 routers domésticos: latencia de cola de hasta unos 400 ms cuando coinciden subida y bajada; el mapeo UDP se mantiene una mediana de 90 segundos - [Ending the Anomaly: Achieving Low Latency and Airtime Fairness in WiFi (USENIX ATC 2017)](https://www.usenix.org/system/files/conference/atc17/atc17-hoiland-jorgensen.pdf) · USENIX · También en la cola de radio del Wi-Fi hay cientos de ms de latencia bajo carga, y un dispositivo lento se come el tiempo de transmisión de los demás - [RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP](https://www.rfc-editor.org/rfc/rfc4787) · IETF · Requisito del temporizador de mapeo UDP en NAT (2 minutos o más; se recomiendan 5 minutos o más por defecto) y renovación con los paquetes que salen desde dentro - [RFC 8325: Mapping Diffserv to IEEE 802.11](https://www.rfc-editor.org/rfc/rfc8325) · IETF · El Wi-Fi usa CSMA/CA: si el canal está ocupado, espera y transmite tras un backoff aleatorio - [Resolve Wi-Fi and Bluetooth issues caused by wireless interference](https://support.apple.com/en-us/102319) · Apple · Interferencias de microondas en la simulación: los hornos de microondas, el Bluetooth y otros interfieren con el Wi-Fi de 2.4 GHz, y pasar a 5 GHz mejora la situación - [RFC 9438: CUBIC for Fast and Long-Distance Networks](https://www.rfc-editor.org/rfc/rfc9438) · IETF · Control de la velocidad de subida en la simulación: ante una pérdida, CUBIC reduce la ventana de envío a 0.7 veces (un 30% menos, aprox.) y luego la vuelve a ampliar ### #l-isp - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Latencia de transmisión en fibra óptica de 5 µs/km: la luz viaja por la fibra a unos 200,000 km/s, y 1,000 km de ida y vuelta llevan al menos 10 ms - [The Internet at the Speed of Light (HotNets 2014)](https://conferences.sigcomm.org/hotnets/2014/papers/hotnets-XIII-final111.pdf) · ACM · Las rutas reales entre routers miden una mediana de 1.5 veces la línea recta de fibra, y el ping mínimo es 3.2 veces el que permitiría la velocidad de la luz (unas 2 veces la línea recta de fibra) - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Medianas de ida y vuelta medidas desde Seúl: Tokio 30 ms, costa oeste de EE. UU. 124–136 ms, Europa 234–244 ms (Corea–Europa es unas 2.8 veces la línea recta de fibra) - [AAE-1 & SMW5 cable cuts impact millions of users across multiple countries](https://blog.cloudflare.com/aae-1-smw5-cable-cuts/) · Cloudflare · El tráfico entre Europa y Asia suele pasar por Egipto, y reparar un cable submarino lleva de días a semanas - [Quantifying the Causes of Path Inflation (SIGCOMM 2003)](https://conferences.sigcomm.org/sigcomm/2003/papers/p113-spring.pdf) · ACM · Las políticas de peering entre ISP y el enrutamiento entre dominios alargan mucho las rutas - [Inferring Persistent Interdomain Congestion (SIGCOMM 2018)](https://www.caida.org/catalog/papers/2018_inferring_persistent_interdomain_congestion/inferring_persistent_interdomain_congestion.pdf) · ACM · Algunas interconexiones entre ISP muestran congestión recurrente, con subidas de latencia y pérdida en las horas pico de cada día - [RFC 4271: A Border Gateway Protocol 4 (BGP-4)](https://www.rfc-editor.org/rfc/rfc4271) · IETF · BGP, que intercambia la información de rutas de internet; hold time predeterminado recomendado de 90 segundos - [BGP updates in 2024](https://blog.apnic.net/2025/01/07/bgp-updates-in-2024/) · APNIC · Tiempo medio diario hasta que el enrutamiento se estabiliza tras un cambio de ruta: 25–35 segundos en IPv4 y 40–50 segundos en IPv6 - [Delayed Internet Routing Convergence (SIGCOMM 2000)](https://conferences.sigcomm.org/sigcomm/2000/conf/paper/sigcomm2000-5-2.pdf) · ACM · Tras un fallo de ruta, la convergencia puede tardar hasta varios minutos, y mientras tanto aumentan la pérdida y la latencia (medición del año 2000) ### #l-dc-net - [High-Resolution Measurement of Data Center Microbursts (IMC 2017)](https://conferences.sigcomm.org/imc/2017/papers/imc17-final60.pdf) · ACM · La latencia de extremo a extremo en la red del centro de datos es menor de 1 ms, y más del 70% de las ráfagas terminan en decenas de µs, así que la utilización media no las muestra - [Data Center TCP (DCTCP) (SIGCOMM 2010)](https://conferences.sigcomm.org/sigcomm/2010/papers/sigcomm/p63.pdf) · ACM · En los switches de uso general, varios puertos comparten búferes poco profundos, y cuando muchos flujos confluyen un instante en un puerto, el búfer se desborda y hay pérdida - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · Número máximo de entradas de la tabla de seguimiento de conexiones y tiempos de retención predeterminados (UDP 30 segundos, stream 120 segundos, TCP establecido 5 días) - [Edit attributes for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/edit-load-balancer-attributes.html) · AWS · Timeout por inactividad de ALB: 60 segundos por defecto; al cumplirse, el balanceador de carga cierra la conexión - [Network Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html) · AWS · Valores predeterminados del balanceador de carga en la simulación: NLB TCP 350 segundos, UDP 120 segundos (no modificable); tras la inactividad, deja de hacer seguimiento en silencio - [Configure load balancer TCP reset and idle timeout](https://learn.microsoft.com/en-us/azure/load-balancer/load-balancer-tcp-idle-timeout) · Microsoft Azure · Timeout por inactividad predeterminado de Azure Load Balancer: 4 minutos - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Valores predeterminados del seguimiento de conexiones de los grupos de seguridad, y explicación de que los timeouts TCP por inactividad de balanceadores de carga y firewalls suelen ser de 60–90 minutos - [Flow-Based Sessions](https://www.juniper.net/documentation/us/en/software/junos/flow-packet-processing/topics/topic-map/security-flow-based-session-for-srx-series-devices.html) · Juniper Networks · Firewall corporativo de la simulación: timeout de sesión predeterminado del firewall SRX, TCP 1,800 segundos (30 minutos), UDP 60 segundos - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · TCP de 1 hora del router doméstico en la simulación: mediana del mapeo TCP de unos 60 minutos. El mapeo UDP variaba entre 30 y 691 segundos según el dispositivo, con una mediana de 90 segundos en un sentido y de unos 180 segundos en ambos sentidos - [A Multi-perspective Analysis of Carrier-Grade NAT Deployment (IMC 2016)](https://www.icir.org/vern/papers/cgn-imc16.pdf) · ACM · UDP de 30 segundos del CGNAT y de 1 minuto del router doméstico en la simulación: mediana del mapeo UDP de CGN de 35 segundos en redes fijas y 65 segundos en redes móviles; el 74% de los NAT medidos, 1 minuto o menos; la mayoría de los NAT de los routers domésticos (CPE), 65 segundos - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · Keepalive TCP de la simulación: tras 2 horas (7,200 segundos) de inactividad por defecto, comprueba 9 veces cada 75 segundos y, si no hay respuesta, corta - [Cached apps freezer](https://source.android.com/docs/core/perf/cached-apps-freezer) · Android (Google) · Segundo plano en móviles de la simulación: Android 14 o posterior congela a los 10 segundos los procesos de apps que pasan al estado de caché - [RFC 5880: Bidirectional Forwarding Detection (BFD)](https://www.rfc-editor.org/rfc/rfc5880) · IETF · BFD, que detecta fallos de ruta más rápido que los Hello (del orden de segundos) de los protocolos de enrutamiento - [RFC 2923: TCP Problems with Path MTU Discovery](https://www.rfc-editor.org/rfc/rfc2923) · IETF · Agujero negro de MTU de la ruta: el ICMP está bloqueado y solo desaparecen los paquetes grandes ### #basics - [Teletraffic Engineering Handbook (ITU-D Study Group 2 Question 16/2)](https://www.itu.int/dms_pub/itu-d/opb/stg/D-STG-SG02.16.2.1-2002-PDF-E.pdf) · ITU · Espera media en M/M/1, W = A·s/(1−A): con una utilización del 50%, 80% y 90%, 1, 4 y 9 veces el tiempo de servicio. Con la misma utilización, la espera es más corta cuantos más workers (servidores) haya y cuanto más regulares sean las llegadas - [CloudWatch metrics that are available for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · CPUUtilization de EC2 es un valor de toda la instancia y se agrega cada 5 minutos por defecto, o cada minuto con el monitoreo detallado - [Designs, Lessons and Advice from Building Large Distributed Systems (Jeff Dean, LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Referencia a memoria principal 100 ns, ida y vuelta dentro del mismo centro de datos 500,000 ns (0.5 ms) - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Retardo de propagación en fibra óptica de 5 µs/km (base del cálculo del límite de la velocidad de la luz) - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Valores predeterminados de Half-Life: 20 actualizaciones por segundo, interpolación de 100 ms. Con 10 por segundo, una interpolación de 200 ms aguanta una pérdida - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us: 200000 por defecto (200 ms) - [Factors influencing the latency of simple reaction time (Frontiers in Human Neuroscience, 2015)](https://doi.org/10.3389/fnhum.2015.00131) · Frontiers · Tiempo medio de reacción simple de unos 231 ms (213 ms corrigiendo la latencia de los dispositivos de medida) - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · Incluso latencias menores de 100 ms afectan al rendimiento en tareas de juego, y en tareas como arrastrar se notan unos 10 ms - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Los jugadores expertos notan diferencias de unos 10 ms en pruebas a ciegas - [Latency and Player Actions in Online Games (Communications of the ACM, 2006)](https://web.cs.wpi.edu/~claypool/papers/precision-deadline/final.pdf) · ACM · Tolerancia a la latencia por género: primera persona, unos 100 ms; tercera persona (RPG, MMO), unos 500 ms; RTS, unos 1,000 ms - [JEP 333: ZGC: A Scalable Low-Latency Garbage Collector](https://openjdk.org/jeps/333) · OpenJDK · G1, con un heap de 128 GB: pausas de 157 ms de media y 544 ms como máximo; ZGC: unos 1–2 ms, sin importar el tamaño del heap ni de los datos vivos - [CommonNetworkParametersExtensions (Unity Transport 2.5)](https://docs.unity3d.com/Packages/com.unity.transport@2.5/api/Unity.Networking.Transport.CommonNetworkParametersExtensions.html) · Unity · disconnectTimeoutMS: si no se recibe nada durante este tiempo, se corta la conexión (30,000 ms por defecto) ### #lab - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · La interpolación es suave a cambio de dibujar el pasado, y la extrapolación no prevé los cambios de dirección y salta cuando falla. Los errores de predicción se corrigen con el resultado del servidor - [UDP vs. TCP](https://gafferongames.com/post/udp_vs_tcp/) · Gaffer On Games · Cuando TCP pierde un paquete, no entrega los datos nuevos que llegan hasta que se retransmite (normalmente 2×RTT o más) - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · Si los inputs sin confirmar se repiten en cada paquete, no hay que esperar retransmisiones (en el peor caso, 2 segundos de inputs) - [Snapshot Interpolation](https://gafferongames.com/post/snapshot_interpolation/) · Gaffer On Games · Dibujar en cuanto llega produce tirones por el jitter; el búfer de interpolación añade algo de latencia a cambio de suavidad - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · Si el movimiento del cliente se pierde o llega mal por problemas de conexión, el servidor corrige la posición (rubber banding) - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Un presupuesto de comandos que se acumula en cada tick limita los comandos que llegan de golpe. Si es demasiado estricto, hasta los jugadores normales sufren tirones - [Introducing Time Dilation (TiDi)](https://www.eveonline.com/news/view/introducing-time-dilation-tidi) · CCP Games · Diseño que, con el servidor sobrecargado, ralentiza el reloj del juego (Time Dilation) para que todo transcurra más despacio - [CommonNetworkParametersExtensions (Unity Transport 2.5)](https://docs.unity3d.com/Packages/com.unity.transport@2.5/api/Unity.Networking.Transport.CommonNetworkParametersExtensions.html) · Unity · Timeout por inactividad que corta la conexión si no se recibe nada durante cierto tiempo ### #symptoms - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Si faltan actualizaciones, la entidad se queda quieta en su última posición (tirones) o se extrapola y salta (teletransporte). Hay que limitar el tiempo de extrapolación - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · Si el movimiento del cliente se pierde o difiere del cálculo del servidor, el servidor envía una corrección y devuelve la posición atrás (rubber banding) - [UDP vs. TCP](https://gafferongames.com/post/udp_vs_tcp/) · Gaffer On Games · TCP retiene los datos posteriores hasta recibir la retransmisión del paquete perdido y luego los entrega todos (cámara rápida) - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · Cuando los inputs acumulados llegan todos juntos, se calculan varios frames de golpe para ponerse al día - [Introducing Time Dilation (TiDi)](https://www.eveonline.com/news/view/introducing-time-dilation-tidi) · CCP Games · Time Dilation (TiDi), que ralentiza el reloj del juego cuando el servidor está sobrecargado; con sobrecarga, las acciones se retrasan varios segundos - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · El tiempo de búfer depende del tick rate del servidor y de los frames de renderizado del cliente - [Using Gameplay Abilities in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-gameplay-abilities-in-unreal-engine) · Epic Games · El servidor puede revertir una habilidad ejecutada con predicción (acciones perdidas o rollback) - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · Los actores que el servidor considera irrelevantes no se replican o se borran en el cliente (entidades invisibles o fantasma) - [CommonNetworkParametersExtensions (Unity Transport 2.5)](https://docs.unity3d.com/Packages/com.unity.transport@2.5/api/Unity.Networking.Transport.CommonNetworkParametersExtensions.html) · Unity · Pasado el timeout por inactividad, se corta la conexión (desconexión) ### #sync - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Principios del servidor autoritativo, la predicción y la reconciliación en el cliente, la interpolación y la compensación de lag, y concesiones como “recibir el impacto ya detrás de la esquina” - [What Every Programmer Needs To Know About Game Networking](https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/) · Gaffer On Games · Evolución del netcode, del lockstep P2P al modelo cliente/servidor y a la predicción en el cliente - [Using Gameplay Abilities in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-gameplay-abilities-in-unreal-engine) · Epic Games · Equilibrio entre capacidad de respuesta y precisión de Local Predicted y Server Initiated - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Autoridad del servidor, predicción, búfer y registro de impactos con rebobinado, y límite del rebobinado - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Cómo programar eventos según la hora del servidor y reproducirlos - [1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond](https://www.gamedeveloper.com/programming/1500-archers-on-a-28-8-network-programming-in-age-of-empires-and-beyond) · Game Developer · Lockstep: los comandos se programan para dos turnos después, la duración del turno se ajusta a la computadora más lenta, y una latencia constante de 500 ms es aceptable, pero una latencia irregular molesta - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · El lockstep solo avanza cuando llegan todos los inputs; un búfer de retardo de reproducción absorbe el jitter - [GGPO Rollback Networking SDK](https://www.ggpo.net/) · GGPO · Rollback: se avanza prediciendo los inputs del rival y, si la predicción falla, se rebobina y se recalcula - [8 Frames in 16ms: Rollback Networking in 'Mortal Kombat' and 'Injustice 2'](https://www.gdcvault.com/play/1025471/8-Frames-in-16ms-Rollback) · GDC · El rollback elimina el retardo de input local del lockstep; recalcula hasta 8 frames - [Latency and Player Actions in Online Games (Communications of the ACM, 2006)](https://web.cs.wpi.edu/~claypool/papers/precision-deadline/final.pdf) · ACM · Una misma latencia afecta de forma distinta según la precisión y el plazo de la acción y la perspectiva (primera persona, tercera persona, omnisciente) - [Networking Overview for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-overview-for-unreal-engine) · Epic Games · Ventajas y carga del anfitrión en un listen server - [Factors influencing the latency of simple reaction time (Frontiers in Human Neuroscience, 2015)](https://doi.org/10.3389/fnhum.2015.00131) · Frontiers · Tiempo de reacción simple humano de unos 0.23 segundos ### #partial - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Si un jugador se desvía, solo se le corrige a él, y los otros nueve lo ven todo fluido. El registro de impactos con rebobinado tiene un límite - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Los paquetes llegan agrupados, 2 en un frame y 0 en otro, y el búfer de jitter los reparte de forma uniforme - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Presupuesto de comandos que reparte entre ticks los comandos que llegan de golpe; efectos secundarios de un límite estricto - [Source SDK 2013: player_lagcompensation.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player_lagcompensation.cpp) · Valve · Límite de rebobinado del motor Source: sv_maxunlag, 1 segundo por defecto - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · “Recibir el impacto ya detrás de la esquina” por la compensación de lag, y retardo de input para igualar los inputs de todos - [send(2) — Linux manual page](https://man7.org/linux/man-pages/man2/send.2.html) · Linux man-pages · Si el búfer de envío se llena, send() espera en modo bloqueante y, en modo no bloqueante, vuelve enseguida con EAGAIN - [Networking Overview for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-overview-for-unreal-engine) · Epic Games · El anfitrión de un listen server tiene ventaja sobre los demás jugadores - [Authority (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/authority.html) · Unity · Autoridad distribuida: cada cliente se encarga de calcular algunas entidades - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · El servidor solo envía a cada conexión los actores relevantes y, cuando dejan de serlo, los borra en el cliente - [NetworkConfig class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkConfig.html) · Unity · Los mensajes de entidades que aún no se han creado se retienen y, pasado un tiempo, se descartan (SpawnTimeout) - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Un paquete UDP fragmentado desaparece entero si se pierde un solo fragmento - [Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE](https://learn.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse) · Microsoft · Si dos sockets comparten el mismo puerto, no se puede saber cuál recibirá los paquetes - [RFC 6269: Issues with IP Address Sharing](https://www.rfc-editor.org/rfc/rfc6269) · IETF · Si varios abonados comparten una dirección IP, la IP por sí sola no permite distinguirlos - [Application.runInBackground](https://docs.unity3d.com/ScriptReference/Application-runInBackground.html) · Unity · Comportamiento predeterminado por el que las apps se suspenden en segundo plano - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Cuando el ancho de banda se satura, solo se replican algunos actores, según su prioridad ### #retrans - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · RTO = SRTT + max(G, 4·RTTVAR); inicial de 1 segundo; recomienda un mínimo de 1 segundo; se duplica en cada expiración; si se fija un máximo, de al menos 60 segundos; los paquetes retransmitidos se excluyen de las muestras de RTT (Karn) - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Retransmisión rápida al tercer ACK duplicado; tras un RTO, se reinicia desde una ventana de congestión de 1 segmento (ventana de pérdida) - [RFC 6675: A Conservative Loss Recovery Algorithm Based on Selective Acknowledgment (SACK) for TCP](https://www.rfc-editor.org/rfc/rfc6675) · IETF · Recuperación de pérdidas que deduce los paquetes que faltan a partir de la información SACK (señales de ACK duplicados y SACK para la retransmisión rápida) - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · Margen de reordenamiento de RACK (min_RTT/4) y su ajuste según DSACK; espera de TLP de 2·SRTT (con un solo paquete sin confirmar, se añade margen para el ACK retardado); reinicio del RTO tras enviar el TLP; SACK obligatorio - [RFC 2018: TCP Selective Acknowledgment Options](https://www.rfc-editor.org/rfc/rfc2018) · IETF · SACK: el receptor informa de los huecos (datos que faltan) - [RFC 2883: An Extension to the Selective Acknowledgement (SACK) Option for TCP](https://www.rfc-editor.org/rfc/rfc2883) · IETF · DSACK: avisa de que se recibió otra vez algo que ya se tenía, lo que deja ver las retransmisiones espurias - [RFC 5682: Forward RTO-Recovery (F-RTO): An Algorithm for Detecting Spurious Retransmission Timeouts with TCP](https://www.rfc-editor.org/rfc/rfc5682) · IETF · F-RTO: detección de RTO espurios - [RFC 3522: The Eifel Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc3522) · IETF · Con las marcas de tiempo se determina a posteriori si la recuperación era innecesaria (la vuelta atrás de la ventana de congestión en la simulación) - [RFC 7323: TCP Extensions for High Performance](https://www.rfc-editor.org/rfc/rfc7323) · IETF · Opciones de marcas de tiempo y escalado de ventana; sin escalado, la ventana es como máximo 64 KiB - [RFC 6937: Proportional Rate Reduction for TCP](https://www.rfc-editor.org/rfc/rfc6937) · IETF · PRR: durante la recuperación, ajusta lo que se envía a lo que se acaba de entregar (el límite de envío durante la recuperación en la simulación) - [RFC 9438: CUBIC for Fast and Long-Distance Networks](https://www.rfc-editor.org/rfc/rfc9438) · IETF · CUBIC reduce la ventana de congestión a 0.7 veces ante una pérdida (la reducción del 30% de la simulación) - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · Sonda de ventana cero: aunque la ventana sea 0, se envían sondas, con intervalos que crecen de forma exponencial - [RFC 9000: QUIC: A UDP-Based Multiplexed and Secure Transport](https://www.rfc-editor.org/rfc/rfc9000) · IETF · En QUIC, una pérdida solo bloquea los streams que iban en ese paquete, y los demás siguen avanzando (separación de flujos) - [RFC 2475: An Architecture for Differentiated Services](https://www.rfc-editor.org/rfc/rfc2475) · IETF · Definición: el shaping retrasa los paquetes y el policing descarta el exceso - [RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP](https://www.rfc-editor.org/rfc/rfc3168) · IETF · ECN: avisa de la congestión sin descartar paquetes - [Smart Queue Management](https://www.bufferbloat.net/projects/cerowrt/wiki/Smart_Queue_Management/) · Bufferbloat.net · SQM en el router: reduce el desbordamiento de colas y el bufferbloat con planificación por flujo, AQM y shaping - [RFC 1191: Path MTU discovery](https://www.rfc-editor.org/rfc/rfc1191) · IETF · Se descubre la MTU de la ruta con el aviso ICMP de tamaño excedido (tipo 3 código 4) - [RFC 1812: Requirements for IP Version 4 Routers](https://www.rfc-editor.org/rfc/rfc1812) · IETF · Los routers pueden limitar la frecuencia de los mensajes de error ICMP (resultados de mtr en los que un solo salto intermedio parece tener pérdida) - [RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection](https://www.rfc-editor.org/rfc/rfc2991) · IETF · Con múltiples rutas, los resultados de diagnósticos como ping y traceroute son poco confiables; método para fijar la ruta con un hash de flujo - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_recovery (0x1 RACK por defecto; desde la 6.17 RACK es la única detección de pérdidas, así que ponerlo a 0 no tiene efecto), tcp_early_retrans (3 por defecto; con 0 se desactiva TLP), tcp_sack, tcp_dsack y tcp_timestamps (activados por defecto), tcp_thin_linear_timeouts (menos de 4 paquetes in-flight, hasta 6 veces lineal), tcp_rto_max_ms, tcp_mtu_probing y tcp_base_mss, tcp_rto_min_us, tcp_retries2 (15 por defecto, unos 924.6 segundos), tcp_syn_linear_timeouts, tcp_notsent_lowat - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpOutSegs no incluye las retransmisiones; significado de TCPLossProbes, TCPLossProbeRecovery, TCPLostRetransmit, TCPSpuriousRTOs, TCPDSACKRecv y TCPSynRetrans - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nombres de contador que muestra nstat (RetransSegs, TCPTimeouts, TCPLossProbes, TCPSpuriousRTOs, TCPDSACKRecv, etc.) - [Thin-streams and TCP](https://docs.kernel.org/networking/tcp-thin.html) · Linux kernel · Los thin streams, como los de los juegos, no aprovechan bien la retransmisión rápida y dependen de timeouts largos; TCP_THIN_LINEAR_TIMEOUTS - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · TCP_RTO_MIN 200 ms, TCP_RTO_MAX 120 segundos, TCP_TIMEOUT_INIT 1 segundo, ACK retardado de 40–200 ms (TCP_DELACK_MIN y MAX), TCP_BASE_MSS 1,024, criterio de thin stream (menos de 4 paquetes in-flight) - [net/ipv4/tcp_input.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_input.c?h=v6.12) · Linux kernel · RTO = SRTT + rttvar (no menor que el RTO mínimo); RACK solo se aplica a conexiones con SACK; PRR para reducir la ventana de congestión durante la recuperación - [net/ipv4/tcp_output.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_output.c?h=v6.12) · Linux kernel · TLP solo en conexiones con SACK, espera de 2·RTT; si solo queda un paquete sin confirmar, se suma el RTO mínimo - [net/ipv4/tcp_timer.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · Si el RTO se repite tcp_retries1 veces, se considera detectado un agujero negro y se activa el sondeo de MTU; timeouts lineales de thin streams y SYN - [net/ipv4/tcp_recovery.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_recovery.c?h=v6.12) · Linux kernel · Margen de tiempo de RACK = min(min_RTT/4 × pasos, SRTT); las retransmisiones confirmadas en menos tiempo que el RTT mínimo no se usan como referencia - [net/ipv4/tcp_ipv4.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_ipv4.c?h=v6.12) · Linux kernel · Inicialización de valores predeterminados: tcp_early_retrans 3, tcp_recovery RACK, tcp_syn_linear_timeouts 4, tcp_base_mss 1,024 (tcp_mtu_probing no se fija aparte, así que queda en 0) - [net/ipv4/tcp_bbr.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_bbr.c?h=v6.12) · Linux kernel · pacing_rate de BBR = pacing_gain × ancho de banda del cuello de botella (envía de forma uniforme con pacing) - [tcp: use RACK to detect losses](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f41b1c58a32537542f14c1150099131613a5e8a) · Linux kernel · Introducción de RACK y tcp_recovery (Linux 4.4); al principio funcionaba como complemento del método anterior - [tcp: disable RFC6675 loss detection](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b38a51fec1c1f693f03b1aa19d0622123634d4b7) · Linux kernel · RACK pasa a ser la detección de pérdidas predeterminada (2018, Linux 4.18) - [tcp: remove obsolete and unused RFC3517/RFC6675 loss recovery code](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1c120191dcec510cc17d587ece48a7ae875a90c5) · Linux kernel · Eliminación del código de recuperación de pérdidas de RFC6675 (Linux 6.17), con la explicación de que RACK-TLP era el predeterminado desde 2018 - [tcp: make the first N SYN RTO backoffs linear](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ccce324dabfe2143519daf50ed8b1ef1d0c542f7) · Linux kernel · Los 4 primeros backoffs del RTO del SYN no se duplican (tras el primer RTO de 1 segundo, cuatro más de 1 segundo cada uno y, a partir de ahí, 2, 4 s …; Linux 6.5) - [tcp: add sysctl_tcp_rto_min_us](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f086edef71be7174a16c1ed67ac65a085cda28b1) · Linux kernel · tcp_rto_min_us, RTO mínimo para todo el servidor (Linux 6.11) - [tcp: add the ability to control max RTO](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=54a378f43425085d0684679d99735696b69165bc) · Linux kernel · Opción de socket TCP_RTO_MAX_MS, 1–120 segundos (Linux 6.15) - [tcp: support TCP_RTO_MIN_US for set/getsockopt use](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f38805c5d26fe4af97837c10d58074a7496638bf) · Linux kernel · Opción de socket TCP_RTO_MIN_US, que fija el RTO mínimo de cada conexión (Linux 6.15) - [Android common kernels](https://source.android.com/docs/core/architecture/kernel/android-common) · Android (Google) · Los kernels comunes de Android con soporte son 5.10 o posteriores (más nuevos que la 4.18, en la que RACK pasó a ser el predeterminado) - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_NODELAY (desactiva Nagle), TCP_USER_TIMEOUT (solo fija cuándo se abandona, sin cambiar cuándo se retransmite), TCP_KEEPIDLE, TCP_INFO - [ip-route(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ip-route.8.html) · iproute2 · Opción rto_min por ruta - [tc-fq(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-fq.8.html) · iproute2 · Pacing por conexión de la cola fq y SO_MAX_PACING_RATE - [iptables-extensions(8) — Linux manual page](https://man7.org/linux/man-pages/man8/iptables-extensions.8.html) · netfilter · TCPMSS --clamp-mss-to-pmtu: evita los tramos con ICMP bloqueado ajustando el MSS en el SYN - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rto (ms), backoff (número de backoffs exponenciales), rtt/rttvar y cwnd de ss -i - [misc/ss.c](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/misc/ss.c?h=v6.12.0) · iproute2 · Salida de ss -ti: retrans:en curso/acumuladas, lost, reordering, bytes_sent y bytes_retrans - [nstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/nstat.8.html) · iproute2 · nstat muestra por defecto el incremento desde la ejecución anterior - [Demonstrations of tcpretrans, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/tcpretrans_example.txt) · IO Visor · Una línea por retransmisión con dirección, puerto y estado; -c agrega por flujo, -l incluye los intentos de TLP - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · Ver hasta los errores detallados con ip -s -s link; significado de rx_missed_errors y rx_crc_errors; estadísticas por driver de ethtool -S - [drivers/net/ethernet/intel/igb/igb_ethtool.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/intel/igb/igb_ethtool.c?h=v6.12) · Linux kernel · Ejemplos de nombres de contador por driver: rx_missed_errors, rx_no_buffer_count, rx_crc_errors - [Ethtool counters](https://docs.kernel.org/networking/device_drivers/ethernet/mellanox/mlx5/counters.html) · Linux kernel · rx_out_of_buffer y rx_discards_phy de mlx5 - [net/core/net-procfs.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/core/net-procfs.c?h=v6.12) · Linux kernel · /proc/net/softnet_stat: una línea por CPU, en hexadecimal; 2.ª columna dropped, 3.ª columna time_squeeze - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · Significado de bw_in, bw_out, pps, conntrack y linklocal_allowance_exceeded; para verlos en CloudWatch hay que instalar el agente de CloudWatch - [High-Resolution Measurement of Data Center Microbursts](https://research.facebook.com/publications/high-resolution-measurement-of-data-center-microbursts/) · Meta · La mayoría de las ráfagas terminan en decenas de µs, así que la utilización media por minuto no muestra la causa de los descartes (IMC 2017) - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · TCP SYN con -T (--tcp) y puerto de destino con -P (--port) - [pathping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/pathping) · Microsoft · Comando de diagnóstico de rutas de Windows que envía muchas sondas y calcula la pérdida y la latencia de cada salto - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtros de visualización tcp.analysis.retransmission, fast_retransmission, spurious_retransmission, duplicate_ack, lost_segment y zero_window - [7.5. TCP Analysis](https://www.wireshark.org/docs/wsug_html_chunked/ChAdvTCPAnalysis.html) · Wireshark · Criterios con los que se marcan las retransmisiones, las retransmisiones rápidas, las retransmisiones espurias y ZeroWindow - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · TCPv4 Segments Retransmitted/sec·Segments Sent/sec, Network Interface Packets Received Discarded - [TCP/IP connectivity issues troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/tcp-ip-connectivity-issues-troubleshooting) · Microsoft · Consultar la configuración global de TCP (Max SYN Retransmissions) con netsh int tcp show global; confirmar las pérdidas intermedias con capturas simultáneas en ambos extremos - [Packet Monitor (Pktmon)](https://learn.microsoft.com/en-us/windows-server/networking/technologies/pktmon/pktmon) · Microsoft · Herramienta integrada que muestra dónde y por qué se descartan paquetes en varios puntos de la pila de red de Windows - [Pktmon command formatting](https://learn.microsoft.com/en-us/windows-server/networking/technologies/pktmon/pktmon-syntax) · Microsoft · Integrada como pktmon.exe en Windows 10 y Windows Server 2019 (1809 o posterior) - [TCP improvements in the Windows network stack (IETF 98 TCPM)](https://datatracker.ietf.org/meeting/98/materials/slides-98-tcpm-tcp-improvements-in-windows-01) · Microsoft · Windows 10 Anniversary Update (1607) y Server 2016 activan TLP y RACK por defecto (en conexiones con un RTT superior a 10 ms); con un solo paquete pendiente, TLP tiene en cuenta el ACK retardado de 200 ms - [Algorithmic improvements boost TCP performance on the Internet](https://techcommunity.microsoft.com/blog/networkingblog/algorithmic-improvements-boost-tcp-performance-on-the-internet/2347061) · Microsoft · TLP está activado por defecto desde Windows Server 2016; el nuevo RACK, que recupera incluso las retransmisiones perdidas, llegó con Server 2022; PRR está activado por defecto desde Windows 10 1903 - [TcpMaxConnectRetransmissions](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc938209(v=technet.10)) · Microsoft · SYN en los Windows antiguos: 2 retransmisiones, a partir de 3 segundos y duplicando cada vez ### #owners - [RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP](https://www.rfc-editor.org/rfc/rfc4787) · IETF · Los mapeos NAT se renuevan siempre con los paquetes que salen desde dentro (REQ-6), y la renovación con paquetes que entran desde fuera es opcional (para UDP). Por eso el heartbeat lo envía el cliente - [RFC 5382: NAT Behavioral Requirements for TCP](https://www.rfc-editor.org/rfc/rfc5382) · IETF · Un NAT puede borrar las sesiones TCP inactivas; el timeout por inactividad recomendado es de al menos 2 horas y 4 minutos (la configuración puede variar según el dispositivo) - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Timeout TCP por inactividad del seguimiento de conexiones de los grupos de seguridad (350 segundos en los tipos de instancia Nitro v6, 5 días en los demás, ajustable entre 60 segundos y 5 días), recomendación de keepalive cada menos de 5 minutos, 350 segundos para TCP a través de NLB - [Control subnet traffic with network access control lists](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html) · AWS · Las ACL de red no guardan estado (no hacen seguimiento de conexiones), así que el tráfico de respuesta también hay que permitirlo con reglas propias - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · Contadores de límite superado de seguimiento de conexiones y de paquetes por segundo de la instancia (conntrack_allowance_exceeded, pps_allowance_exceeded) - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · El argumento backlog de listen es el tamaño real de la cola, y si es mayor que somaxconn se recorta a ese valor (4096 por defecto desde la 5.4) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · somaxconn (límite del backlog de listen), tcp_max_syn_backlog, tcp_syncookies (1 por defecto, recurso para cuando se desborda la cola de SYN), tcp_keepalive_time (2 horas por defecto) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · Cuando la cola de accept se llena, se descartan los SYN y suben TcpExtListenOverflows y TcpExtListenDrops - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · Cálculo del uso de conntrack con nf_conntrack_count y nf_conntrack_max - [Control Group v2](https://docs.kernel.org/admin-guide/cgroup-v2.html) · Linux kernel · nr_throttled de cpu.stat: veces que el límite de CPU del contenedor aplicó throttling - [proc_stat(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_stat.5.html) · Linux man-pages · steal de /proc/stat: tiempo de CPU que, en un entorno virtualizado, usó otro SO - [RFC 2992: Analysis of an Equal-Cost Multi-Path Algorithm](https://www.rfc-editor.org/rfc/rfc2992) · IETF · ECMP elige la ruta con un hash de los campos de cabecera que identifican el flujo (un mismo flujo, una misma ruta; flujos distintos pueden ir por rutas distintas) - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · Medir la ruta con el mismo protocolo y puerto que el juego (-T, -u, -P) ### #l-server-proc - [VALORANT's 128-Tick Servers](https://www.riotgames.com/en/news/valorants-128-tick-servers) · Riot Games · Presupuesto del tick: a 128 ticks, cada frame debe terminar en 7.8125 ms; se mide el tiempo de frame por subsistema y se reparte el presupuesto - [Introducing Time Dilation (TiDi)](https://www.eveonline.com/news/view/introducing-time-dilation-tidi) · CCP Games · La simulación física de EVE Online se actualiza una vez por segundo y, con sobrecarga, ralentiza el reloj del juego para reducir en proporción la carga ligada al tiempo - [HED-GP Technical Retrospective: What a HED-ache](https://www.eveonline.com/news/view/what-a-hed-ache) · CCP Games · Límite inferior de Time Dilation del 10%; el envío O(n²), en el que n jugadores notifican cada acción a n jugadores, es el factor que limita las batallas masivas - [Handling variation in time](https://docs.unity3d.com/Manual/time-handling-variations.html) · Unity · Modelo de la simulación del tick: si el avance a intervalos fijos se atrasa, se ejecutan de golpe los pasos de recuperación (cámara rápida), y el tiempo que supera el límite se descarta, así que el tiempo del juego se ralentiza (cámara lenta) - [Comparing Interest Management Algorithms for Massively Multiplayer Games](https://www.sable.mcgill.ca/~clump/papers/boulanger-06-comparing.pdf) · ACM · Artículo de NetGames 2006 (versión publicada por los autores). Comparar las distancias de todos los pares deja de ser viable al crecer el número de jugadores; dividiendo en una cuadrícula, solo se revisan las celdas vecinas - [Replication Graph in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/replication-graph-in-unreal-engine) · Epic Games · Dividir el mundo en una cuadrícula y elegir los destinatarios con listas por celda ahorra CPU del servidor aunque haya muchos jugadores y actores - [Amdahl's Law in the Multicore Era](https://research.cs.wisc.edu/multifacet/papers/ieeecomputer08_amdahl_multicore.pdf) · IEEE · Límite de throughput de la simulación de locks: si la fracción que solo puede hacerse de uno en uno es 1−f, la aceleración no supera 1/(1−f) - [Runtime locking correctness validator](https://docs.kernel.org/locking/lockdep-design.html) · Linux kernel · Deadlock de la simulación de locks: dos locks adquiridos en orden inverso provocan una espera circular y un deadlock - [Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/workloads/pods/probes/) · Kubernetes · Watchdog de la simulación de locks: una sonda de liveness detecta el deadlock y reinicia; por defecto comprueba cada 10 segundos y reinicia tras 3 fallos seguidos (unos 30 segundos) - [ASP.NET Core Best Practices](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/best-practices) · Microsoft · Llamadas síncronas: el acceso a datos y la E/S deben hacerse con llamadas asíncronas; las llamadas bloqueantes agotan el pool de hilos y retrasan las respuestas ### #l-infra - [Site Reliability Engineering, Chapter 22: Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/) · Google · Fallo en cascada: cómo un backend lento retiene hilos y recursos de las capas de delante y el fallo se extiende por reintentos, health checks fallidos y reinicios con la caché vacía, y cómo responder - [Circuit Breaker Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) · Microsoft Azure · Estados cerrado, abierto y semiabierto del circuit breaker y umbral de fallos; con timeouts largos, los hilos quedan atrapados hasta que se corta el paso - [Bulkhead Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead) · Microsoft Azure · Aislar los recursos por función o por destino de llamada para que el fallo de uno no se extienda - [Timeouts, retries, and backoff with jitter](https://d1.awsstatic.com/builderslibrary/pdfs/timeouts-retries-and-backoff-with-jitter.pdf) · AWS · Amazon Builders' Library. Liberar recursos con timeouts, limitar el número de reintentos y añadirles jitter - [The Unique Architecture behind Amazon Games’ Seamless MMO New World](https://aws.amazon.com/blogs/gametech/the-unique-architecture-behind-amazon-games-seamless-mmo-new-world/) · AWS · Ejemplo de arquitectura de servidores MMO: servidores de entrada, servidores de simulación por cuadrícula (hubs), pool de servidores compartidos para sesiones, BD de estado - [Working with DB instance read replicas](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html) · AWS · Retraso de replicación en la simulación de arquitectura de servidores: las réplicas de lectura se actualizan de forma asíncrona y pueden devolver datos antiguos - [Site Reliability Engineering, Chapter 20: Load Balancing in the Datacenter](https://sre.google/sre-book/load-balancing-datacenter/) · Google · Despliegues y reinicios: pasar a estado lame duck para desviar las solicitudes nuevas antes de terminar, y precalentar justo después de reiniciar - [Amazon EC2 Auto Scaling lifecycle hooks](https://docs.aws.amazon.com/autoscaling/ec2/userguide/lifecycle-hooks.html) · AWS · Al escalar hacia arriba o hacia abajo, las instancias quedan en espera para terminar las tareas de preparación o limpieza (hasta 1 hora por defecto) - [systemd.service(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd.service.5.html) · systemd · Watchdog de la simulación de arquitectura de servidores: termina y reinicia automáticamente un servicio que deja de enviar señales de vida ## Formas de gráfico - **Picos periódicos** (`periodic`): Normalmente bajo, pero se dispara a intervalos fijos: cada pocos segundos, cada pocos minutos o a cada hora en punto. - **Picos aleatorios** (`random`): Se dispara de forma irregular, sin patrón, y enseguida vuelve a su nivel. - **Salto en escalón** (`step`): Sube un escalón a partir de un momento concreto (un parche, un cambio de configuración, un cambio de ruta) y se queda ahí. - **Subida gradual** (`ramp`): Sube poco a poco a lo largo de horas o días. Crece con el tiempo que lleva encendido. - **Diente de sierra** (`sawtooth`): Sube despacio y cae de golpe al reiniciar o limpiar, una y otra vez. - **Alto solo a ciertas horas** (`peak`): Forma una loma a la misma hora cada día, como en el pico de la noche. - **Sube con la carga** (`load`): Cuando aumentan los jugadores conectados o los que se juntan en un mismo lugar, sube todavía más rápido que ellos. - **Topa con el límite** (`ceiling`): El throughput o el número de conexiones llega a un valor y ya no sube más; a partir de ahí aumentan las esperas y los errores. - **Siempre alto** (`high`): No tiene picos: se mantiene alto todo el tiempo. Pasa cuando la causa es estructural, como la distancia, la ruta o el diseño. - **Alto solo en algunos** (`outlier`): La mayoría está normal y solo algunos jugadores, regiones, ISP o dispositivos dan valores altos. - **Hueco y luego ráfaga** (`gap`): Durante un rato no se recibe nada y luego llega todo de golpe. - **Desconexión masiva** (`drop`): El número de conexiones cae de golpe o el de desconexiones se dispara en un instante. - **Avalancha tras la apertura** (`surge`): Se dispara justo al abrir el servidor o al empezar un evento y luego baja poco a poco. ## Procedimientos por situación ### Lag tras un parche Cuando aumentan los reportes de lag a partir de un parche o despliegue concreto. Se usa cuando se acumulan reportes del tipo “desde esta actualización va raro” o cuando un gráfico sube en escalón en cierto momento y se queda arriba. 1. **Fijar la hora de inicio y reunir todos los cambios cercanos**: Hay que localizar el momento en que se concentraron los primeros reportes y el momento en que el gráfico subió en escalón, y anotar sin excepción todos los cambios que salieron antes y después. Se revisan a la vez los parches del cliente, los despliegues del servidor, los cambios de configuración, los cambios de esquema de la BD (DDL) y los reinicios, los trabajos de red y de firewall, y los cambios de infraestructura (tipo de instancia, kernel, drivers). Si en cada despliegue se marca una línea vertical en todos los gráficos con la función de anotaciones (annotations) de la herramienta de monitoreo, este paso se resuelve enseguida. Si un parche del juego y un trabajo de infraestructura salieron en la misma ventana de mantenimiento, hay que mantener los dos como candidatos. A quién llamar primero: a los dos equipos que hicieron cambios, el de desarrollo y el de infraestructura. (causas: in-deploy, so-os-update, db-ddl-lock, db-plan-flip, db-cold-cache) 2. **Acotar el alcance: build, dispositivo, servidor y región**: Hay que ver en qué dimensión se concentra el problema. Si solo van mal quienes usan la build nueva, se sospecha primero del cliente; si solo ciertos SO, tarjetas gráficas o dispositivos, del rendimiento del cliente o de los drivers; si solo ciertos servidores, canales o zonas, del servidor; si solo ciertos países o ISP, de la ruta de red, y si todos van mal a la vez, de los recursos compartidos (BD, balanceadores de carga, gateways) o del despliegue de servidor que acaba de salir. Si la telemetría del cliente incluye el número de build, se ponen lado a lado el ping, los FPS, los picos de frametime y el número de desconexiones de la build antigua y de la nueva. Si el ping sigue igual y solo empeoraron los FPS, apunta al rendimiento del cliente antes que a la red. A quién llamar primero: si se concentra en una build o un dispositivo, al equipo de desarrollo (cliente); si se concentra en servidores o canales, al equipo de desarrollo (servidor) cuando las métricas del host son normales, o al equipo de infraestructura (servidores/SO) cuando no lo son; si se concentra en países o ISP, al equipo de infraestructura (red). (causas: cg-hitch, cg-sync-load, co-vram, cg-crash) 3. **Comparar la versión nueva y la antigua en la misma franja horaria**: Si solo se compara antes y después del despliegue, se mezclan los cambios debidos al día de la semana, la hora y los eventos, y el diagnóstico se enturbia. Si es posible, conviene subir primero la versión nueva a unos pocos servidores (canario) y comparar lado a lado el tiempo de tick p50 y p99, el número de ticks excedidos, la CPU, la memoria y la tasa de errores con los de servidores de la versión antigua en la misma franja horaria (grupo de control). Si ya se desplegó en todos, se compara con el mismo día y la misma franja horaria de la semana anterior. La media de todo el servidor esconde los problemas de algunos servidores o zonas, así que hay que desglosar por servidor y por zona. A quién llamar primero: al equipo de desarrollo (servidor). (causas: sp-tick-overrun, mem-alloc, mem-leak, sp-broadcast) 4. **Comparar la huella del tráfico antes y después**: Sin conocer el código del servidor, se puede comprobar con valores visibles desde la red si el parche cambió la forma del tráfico. Hay que comparar antes y después los paquetes por segundo (pps) y los bytes por jugador, el tamaño medio y máximo de los paquetes, el número de conexiones y el tamaño de la ráfaga de envío que sale de golpe en cada tick. Si los paquetes UDP empezaron a superar la MTU de la ruta (normalmente 1,500 bytes), se produce fragmentación IP. Basta con perder un fragmento para perder el paquete entero, y algunos NAT y firewalls descartan los fragmentos sin más. Los jugadores cuya ruta pasa por un tramo con una MTU menor (túnel, VPN) pierden solo los paquetes grandes. Si subieron los pps, hay que comprobar que no se esté llegando al límite de PPS de la instancia en la nube ni al límite de procesamiento de los firewalls o de los dispositivos de protección DDoS. A quién llamar primero: si la huella cambió, al equipo de desarrollo (servidor), con las pruebas adjuntas; si la huella es la misma y solo aumentaron la pérdida y las retransmisiones, al equipo de infraestructura (red). (causas: sp-patch-traffic, sk-fragment, rt-mtu, nic-cloud-pps, rt-appliance-pps, rt-burst) 5. **Comparar los tipos y el número de consultas a la BD antes y después**: Si subió la latencia de la BD, lo primero es ver si también subió el número de consultas (QPS). Tanto pg_stat_statements de PostgreSQL como los resúmenes por digest de Performance Schema de MySQL agrupan como un solo tipo las consultas que solo se diferencian en los valores y acumulan su número de ejecuciones y su tiempo total. Al comparar la lista de las consultas principales antes y después del parche, salen a la luz las consultas nuevas, las que multiplicaron su número de ejecuciones (N+1) y las que leen la tabla entera sin índice (en MySQL, la columna SUM_NO_INDEX_USED). A quién llamar primero: si cambiaron las QPS o la forma de las consultas, al equipo de desarrollo (servidor); si las consultas son las mismas y solo aumentó la latencia, al equipo de infraestructura (BD: plan de ejecución, IOPS, bloqueos). (causas: db-no-index, db-login-storm, db-plan-flip, db-cache-stampede) 6. **Identificar la capa con las métricas del host y del proceso del servidor**: Con valores visibles desde el SO, sin necesidad del código, se distingue entre lo que pasa dentro del proceso del servidor y lo que pasa en el host. Si se acumula la cola de recepción (Recv-Q) del socket del servidor, el proceso del servidor no está leyendo a tiempo (tick detenido, GC, locks); si un solo hilo está al 100%, hay un cuello de botella de un solo hilo, y si aumentó el tiempo de pausa en el log del GC, cambió el patrón de uso de memoria. También hay que comprobar que no se haya desplegado con un nivel de log más alto que aumente las escrituras de logs. En cambio, si aumentaron el CPU steal, el throttling o los descartes de la NIC, hay que mirar la infraestructura que cambió en el mismo momento (tipo de instancia, kernel, límites del contenedor). A quién llamar primero: si las señales están dentro del proceso, al equipo de desarrollo (servidor); si son del host, al equipo de infraestructura (servidores/SO). (causas: mem-gc, sp-hotzone, dk-sync-log, so-cpu-quota, so-steal, so-os-update) 7. **Revertir para confirmar y dejar constancia**: Hay que revertir el cambio más probable solo en algunos servidores o para algunos jugadores (rollback, desactivar un feature flag), o devolver la configuración a su valor anterior, y ver si el síntoma desaparece con él. Si solo mejora la parte revertida, la causa queda confirmada. Revertir también puede provocar una lentitud breve por los reinicios y la caché fría, así que, si no es urgente, conviene hacerlo en horas de poca actividad. El resultado se anota en el registro de incidentes junto con el ID de la causa, y los límites de tamaño de paquete, número de consultas y tiempo de tick pasan a la lista de comprobación previa al despliegue del siguiente parche. A quién llamar primero: al equipo que hizo el cambio. (causas: in-deploy, db-cold-cache) ### Lanzamiento en un nuevo país o región Cuando se abre el servicio en un país nuevo o se añade una región o un centro de datos nuevos. Se usa tanto para las comprobaciones previas a la apertura como para distinguir reportes del tipo “en Corea va bien, pero los jugadores del nuevo país tienen lag”. 1. **Medir la calidad de la ruta de cada ISP local antes de abrir**: Para cada ISP principal (ASN) del país de destino, hay que medir la distribución del tiempo de ida y vuelta (RTT), el jitter y la pérdida de paquetes hasta cada ubicación candidata para los servidores del juego. Una sola media esconde las diferencias entre ISP, así que se mira la mediana y el percentil 95 de cada ISP, por separado en las horas pico de la noche y de madrugada. La red de medición pública RIPE Atlas permite elegir país y ASN y lanzar ping y traceroute desde sondas de todo el mundo; también se puede medir levantando VM temporales en las regiones candidatas. Algunos dispositivos intermedios limitan las respuestas ICMP, así que, si es posible, también hay que medir con el mismo protocolo y puerto que el juego. Si solo un ISP pasa por ciudades especialmente lejanas, es un problema de peering o de ruta. Como los ISP priorizan el costo sobre la latencia al elegir rutas, incluso un destino cercano puede acabar dando un gran rodeo. A quién llamar primero: al equipo de infraestructura (red) y, si la ruta depende del ISP, a partes externas (ISP, IX). (causas: isp-distance, isp-routing, isp-peak, isp-cable) 2. **Comparar las mediciones con los límites que tolera el diseño del juego**: El RTT y el jitter medidos se comparan con las ventanas de tiempo del juego (tiempos de reacción como esquivar o hacer parry), el límite de la compensación de lag, la longitud del búfer de interpolación y el tamaño del búfer de inputs. Por ejemplo, si la ventana de parry es de 0.2 s, los jugadores de un ISP cuyo retardo de ida y vuelta más el búfer de interpolación supere ese valor llegan tarde aunque reaccionen a tiempo. Si se amplía la compensación de lag para cubrir ese margen, entonces aumentan los reportes del tipo “me dieron detrás de una pared” por parte de quien recibe el golpe. Si muchos ISP superan los límites, el equipo de infraestructura debe estudiar acercar las regiones o los PoP de edge, y el equipo de desarrollo, revisar los valores de las ventanas de tiempo, la interpolación y la compensación de lag. La tabla de referencia está en el capítulo “Mismo ping, distinta sensación: modelos de netcode” de este libro blanco. A quién llamar primero: al equipo de desarrollo (servidor y cliente: límites del diseño) y al equipo de infraestructura (red: ubicación de regiones y PoP). (causas: sy-short-window, sy-no-lagcomp, sy-lagcomp-overreach, cg-no-buffer) 3. **Comprobar la MTU y si el UDP pasa**: Hay que comprobar que el paquete más grande del juego atraviesa entero las redes locales. Se mide la MTU de la ruta enviando pings de distintos tamaños con el bit de no fragmentar (DF) activado y se busca si hay tramos de menos de 1,500 bytes, como PPPoE, túneles o redes móviles. El estándar para transportes de datagramas como UDP (RFC 8899) recomienda 1,200 bytes como tamaño base capaz de atravesar la mayoría de las rutas en IPv4, así que, si el paquete más grande del juego lo supera, hay que decidir con el equipo de desarrollo si se reduce o se divide. También hay que comprobar si en redes Wi-Fi públicas, redes corporativas o algunos ISP se bloquea o se limita la velocidad del UDP o de los puertos del juego, y si existe una ruta alternativa (TCP, puerto 443) para cuando estén bloqueados. A quién llamar primero: al equipo de infraestructura (red) y al equipo de desarrollo (servidor: tamaño de los paquetes). (causas: dc-mtu, rt-mtu, sk-fragment, isp-udp-block, hn-captive, isp-shaping) 4. **Medir el timeout por inactividad de NAT y CGNAT y ajustar el intervalo del heartbeat**: Hay que medir cuánto tardan los routers domésticos y las redes móviles (CGNAT) del país en borrar el mapeo de una conexión UDP inactiva. En cada prueba, el dispositivo de prueba envía un paquete al servidor para crear el mapeo y después no envía nada más, y el servidor le envía un paquete cuando pasa el tiempo fijado (30 s, 60 s, 120 s…). El tiempo a partir del cual el dispositivo deja de recibir ese paquete es el timeout por inactividad de esa red. El estándar (RFC 4787) establece que un mapeo UDP no debe expirar antes de 2 minutos y recomienda un valor predeterminado de 5 minutos o más, pero el valor varía mucho de un dispositivo a otro y algunos lo borran antes. El mapeo solo se renueva con seguridad con los paquetes que salen del dispositivo, así que el heartbeat lo debe enviar el cliente, y hay que comprobar que su intervalo sea como máximo la mitad del valor más corto entre el medido y los timeouts por inactividad del balanceador de carga y de los grupos de seguridad de la nube. A quién llamar primero: al equipo de desarrollo (cliente: intervalo del heartbeat; servidor: valores de timeout) y al equipo de infraestructura (configuración del balanceador de carga y de los grupos de seguridad). (causas: hn-nat, isp-cgnat, rt-mapping, dc-lb-idle, dc-cloud-conntrack) 5. **Comprobar los servicios externos y los dispositivos de seguridad que intervienen en el país**: Hay que comprobar que el inicio de sesión de las plataformas locales, los pagos y la verificación de identidad responden a la velocidad normal, que el DNS local resuelve bien las direcciones de los servidores de login y de parches, y que la CDN sirve los parches desde un PoP cercano a ese país. También hay que comprobar que los rangos de IP del nuevo país no caigan en las reglas de bloqueo por país ni en los límites de velocidad de la protección DDoS y los firewalls; en especial, que no se bloqueen de golpe los rangos de CGNAT, donde muchos abonados comparten una misma IP. A quién llamar primero: al equipo de infraestructura (dispositivos de seguridad, DNS, CDN) y a partes externas (plataformas, proveedores de pago, ISP). (causas: in-external, isp-dns, dc-ddos, isp-cgnat) 6. **Tras la apertura, desglosar por país y ASN**: Se añaden el país y el ASN a la IP del cliente en los logs de conexión y del balanceador de carga, y se revisan por país e ISP el RTT, las retransmisiones, el número de desconexiones y sus motivos (timeout de heartbeat, RST, expulsión por el servidor). Con bases de datos gratuitas como MaxMind GeoLite ASN se puede convertir una IP en su ASN y el nombre de la organización; para cumplir la normativa local de privacidad, las IP se guardan reducidas a /24 o al ASN. Si los problemas se concentran en un solo ASN, hay que mirar primero la ruta de ese ISP (equipo de infraestructura, partes externas); si va mal todo el país nuevo, la distancia y los límites del diseño (equipo de infraestructura, equipo de desarrollo), y si solo empeora por la noche, la congestión del peering. Si algunos jugadores tienen siempre el ping alto, hay que revisar con el equipo de desarrollo (servidor) si se les está asignando una región lejana por errores de GeoIP, por una VPN o por asignar la región según el líder del grupo. Si el monitoreo sintético es normal y solo los jugadores van mal, apunta al entorno del jugador o al cliente. (causas: isp-peak, isp-routing, rt-queue-drop, pt-isp-validation, in-region-match) 7. **Comprobar cómo afectan los jugadores lejanos a los demás**: Cuando aumentan los jugadores que se conectan desde lejos, el problema no se queda en su propia pantalla. Los inputs del jugador lento llegan amontonados, así que en la pantalla de los demás ese personaje se mueve en cámara rápida, y las comprobaciones de velocidad y de cooldown del servidor lo detectan, lo que provoca rubber banding o habilidades rechazadas. En las mecánicas de grupo, la reacción tardía de un solo jugador lento puede hacer fracasar a todo el grupo, y en lockstep todos esperan al más lento. Hay que revisar si, tras abrir el nuevo país, aumentaron entre los jugadores actuales los reportes del tipo “solo un personaje se ve raro”, y definir con el equipo de desarrollo el búfer de inputs, las tolerancias de validación y la separación de regiones de matchmaking. A quién llamar primero: al equipo de desarrollo (servidor). (causas: pt-slow-burst, pt-isp-validation, pt-raid-member, sy-lockstep) ## Incidentes reales ### eve-hedgp-2014 · CCP Games 2014: Sobrecarga del servidor en la gran batalla de flotas de HED-GP en EVE Online - Qué pasó: En la gran batalla de flotas del sistema HED-GP, analizada en una retrospectiva de enero de 2014, el servidor sufrió una sobrecarga grave. Time Dilation (función que ralentiza el tiempo del juego cuando hay sobrecarga) llegó a su mínimo del 10% y todo el campo de batalla pasó a cámara lenta, pero aun así la carga siguió acumulándose. El retraso acumulado en el procesamiento de las desactivaciones y los ciclos repetidos de los módulos (Dogma Lateness) llegó a un máximo de 193 segundos de tiempo de juego, unos 32 minutos en tiempo real. En la batalla de 6VDT de julio de 2013, de un tamaño casi igual, el máximo fue de 42 segundos (unos 7 minutos en tiempo real). - Causa: CCP advirtió que no podía tener certeza, porque sus herramientas de perfilado añaden carga por sí mismas y no se ejecutan en situaciones así, y señaló dos causas probables. La primera fue la carga sin procesar que siguió acumulándose a medida que la batalla se alargaba. La segunda fue el mayor uso de drones: el número de drones desplegados durante la batalla (sin contar duplicados) fue de 21,123 en 6VDT y de 38,852 en HED-GP, un 84% más. Los envíos que comunican la acción de un jugador a todos los que la ven crecen con el cuadrado del número de jugadores (O(n²)), y los drones generan más mensajes por cada ataque. Además, el código con el que los drones eligen objetivo a menudo recorre todos los objetivos atacables del mismo campo de batalla, así que su costo crece casi como n². - Lecciones: Cuando la carga de procesamiento de una zona abarrotada supera su límite, toda esa zona pasa a cámara lenta, y cuanto más dura la batalla, más trabajo pendiente se acumula y más crece el input lag. Señales que revisar: el tiempo de tick y el trabajo pendiente del servidor (nodo) que atiende esa zona, junto con el número de jugadores y de entidades. Lo característico es que las demás zonas siguen bien. El responsable principal es el equipo de desarrollo (servidor), y lo que hay que corregir es a cuántos destinatarios se comunica cada acción y el costo de la búsqueda de objetivos de la IA. Ralentizar el tiempo del juego no elimina la sobrecarga, pero hace que todos vayan más lentos al mismo ritmo, y así evita que solo algunas acciones se retrasen sin límite. - Causas relacionadas: sp-broadcast, sp-tick-overrun, sp-queue, sp-hotzone - Publicación original: [CCP Games](https://www.eveonline.com/news/view/what-a-hed-ache) ### riot-direct-2015 · Riot Games 2015: Rodeos en el tráfico de League of Legends y Riot Direct - Qué pasó: Es un artículo técnico en el que Riot Games explica por qué internet no se adapta bien a los juegos en tiempo real. El tráfico real que reportó un jugador de League of Legends tenía que ir directo de San Francisco a Portland, pero pasaba por Los Ángeles, Denver y Seattle, y tardaba 70 ms en un trayecto que en línea directa habría costado 14 ms. Riot explicó que, cuando los routers se desbordan y descartan paquetes, los demás campeones parecen saltar por la pantalla y los proyectiles parecen teletransportarse. - Causa: Riot señaló como causas la ruta y los routers. Los proveedores de red troncal y los ISP priorizan la ruta más barata sobre la de menor latencia, y cuando la ruta que fija BGP da un rodeo largo, también aumenta el número de routers por los que pasa el tráfico. Un router carga con un trabajo de procesamiento proporcional al número de paquetes, sea cual sea su tamaño. Los paquetes de juego rondan los 55 bytes, así que, para la misma cantidad de datos, son 27 veces más paquetes que con paquetes de 1,500 bytes, y, en la misma proporción, llenan antes los búferes de entrada de los routers. Según Riot, muchos routers descartan primero los paquetes UDP cuando se sobrecargan. Como solución, Riot creó su propia red, Riot Direct, con routers en 10 grandes nodos de internet de EE. UU. y conexiones directas (peering) con tantos ISP como fuera posible. Según la segunda parte, el porcentaje de jugadores con un ping inferior a 80 ms subió del 31% al 50% en algo más de 9 meses, y llegó al 80% de la noche a la mañana después de trasladar los servidores del juego a Chicago. - Lecciones: Si dentro de un mismo país solo los jugadores de un ISP concreto tienen un ping especialmente alto, hay que sospechar de la ruta. Señales que revisar: la distribución del RTT por ISP (ASN) y las ciudades de paso que aparecen en traceroute. El responsable principal es el equipo de infraestructura (red), y se corrige con peering directo con los ISP, conexión a IX (puntos de intercambio de internet) y la elección de la ubicación de los servidores. La política de rutas del lado del ISP hay que acordarla con partes externas (el ISP). Este caso también muestra que basta con acercar los servidores al centro de la distribución de los jugadores para lograr una gran mejora. - Causas relacionadas: isp-routing, isp-distance, rt-queue-drop - Publicación original: [Riot Games](https://www.riotgames.com/en/news/fixing-internet-real-time-applications-part-i) ### riot-edge-2020 · Riot Games 2020: Sobrecarga de hosts edge en los servidores de Europa y Brasil de League of Legends - Qué pasó: A finales de febrero de 2020, los servidores EUW, EUNE y BR de League of Legends sufrieron varias caídas, y el número de partidas nuevas que empezaban bajó mucho. Todos los servicios de backend, como el matchmaking y los servidores de juego, estaban en buen estado, pero casi no les llegaba tráfico. Riot aplazó una semana el modo torneo (Clash) para no abrirlo en clústeres que podían ser inestables. La retrospectiva no indica cuánto duró cada caída. - Causa: Coincidieron tres cosas. Las solicitudes a un servicio estaban mal construidas: en ciertos casos fallaban una y otra vez y se reintentaban sin parar, y el volumen de solicitudes se disparó. Un problema de compatibilidad conocido entre el sistema de contenedores y la versión del SO provocaba una fuga de memoria dentro del SO; la actualización solo se había completado en cerca del 60% de todo el entorno de contenedores de Riot y seguía en curso en los clústeres de Europa y Latinoamérica. Los contenedores edge, que reciben el tráfico de internet, lo filtran y lo pasan al backend, se repartían en hosts separados dentro de un mismo shard (grupo de servidores), pero nada impedía que coincidieran los de shards distintos, así que en cada caída había contenedores edge de al menos tres shards concentrados en un solo host. La avalancha de reintentos cayó sobre ese host, y la fuga de memoria terminó por detenerlo. - Lecciones: Si todos los servicios de backend responden que están “bien, pero no les llega tráfico”, hay que mirar lo que tienen delante (edge, gateways, balanceadores de carga). Señales que revisar: la concentración de conexiones entrantes en ciertos hosts y la tasa de fallos y reintentos de solicitudes concretas. El responsable principal es el equipo de desarrollo (servidor: la solicitud mal construida y la forma de reintentar), y el equipo de infraestructura (servidores/SO) se encarga de las reglas de ubicación de contenedores, las actualizaciones del SO y las alertas de desbalance. Riot corrigió el código de la solicitud, cambió los reintentos para que no se dispararan y, hasta implementar el reparto entre shards, configuró alertas de desbalance. - Causas relacionadas: in-gateway, in-cascade - Publicación original: [Riot Games](https://www.leagueoflegends.com/en-gb/news/riot-games/incident-report-recent-outages-in-europe-brazil/) ### riot-euw-2021 · Riot Games 2021: Caída de 5 horas en League of Legends EUW: una BD auxiliar detuvo todo el servidor - Qué pasó: El 22 de enero de 2021, el servidor EUW de League of Legends dejó de funcionar bien durante algo más de 5 horas. Las métricas de jugadores con sesión iniciada y de jugadores en partida se cortaron a la vez, y entre los dos reinicios los inicios de sesión aumentaban, pero casi no empezaban partidas. - Causa: El servidor principal de una BD que atendía una función no crítica sufrió una avería de hardware, y esa BD no tenía configurado el failover automático a un servidor de reserva. Cada BD tenía su propio pool de conexiones, pero todos los pools usaban el mismo pool de hilos; las tareas enviadas a la BD averiada no terminaban y retenían hilos, hasta que el sistema entero se quedó sin hilos disponibles. En medio de una avalancha de alertas, el equipo sospechó primero de un ataque de red malicioso sufrido poco antes y de trabajos de hardware en otra región, y la alerta de la BD averiada no se vio hasta cerca de 1 hora después. Como todos los sistemas se ejecutaban en una sola JVM, cuando el GC detuvo el proceso varios segundos cada vez bajo la carga de reconexiones posterior al reinicio, también quedaron grandes huecos en la recopilación de métricas. Además, la cola de inicio de sesión no respetó el límite configurado, y la entrada de jugadores fue irregular. - Lecciones: Una sola BD auxiliar que se consideraba poco importante puede detenerlo todo a través de un recurso compartido como un pool de hilos. Señales que revisar: el número de solicitudes en espera por BD, la utilización del pool de hilos y una proporción de partidas iniciadas demasiado baja respecto a los inicios de sesión. Los responsables son el equipo de desarrollo (servidor: aislamiento de los pools de hilos, timeouts) y el equipo de infraestructura (BD: failover automático). Cuando llueven alertas, es fácil sospechar primero del último problema sufrido (un ataque, por ejemplo), así que conviene descartar una cosa tras otra siguiendo el orden de diagnóstico (alcance → momento → capa). Después de un reinicio, también hay que comprobar que la cola de inicio de sesión limita la entrada según lo configurado. - Causas relacionadas: sp-threadpool, db-failover, in-cascade, mem-gc - Publicación original: [Riot Games](https://www.riotgames.com/en/news/keeping-legacy-software-alive-case-study) ### roblox-2021 · Roblox 2021: Caída de 73 horas en Roblox: contención en el clúster de descubrimiento de servicios (Consul) - Qué pasó: Empezó la tarde del 28 de octubre de 2021 (hora del Pacífico) con una carga de CPU alta en un servidor de Consul. A las 16:35, el número de jugadores conectados cayó a la mitad de lo normal y después todo el servicio se detuvo. Hasta las 16:45 del 31 de octubre no pudieron volver a entrar todos los jugadores: habían pasado 73 horas desde el inicio de la caída. Roblox indicó que lo usan 50 millones de personas al día. - Causa: Roblox usa HashiCorp Consul para el descubrimiento de servicios (la función con la que los servicios encuentran las direcciones de los demás), los health checks y un almacén KV, y un mismo clúster de Consul atendía varias cargas de trabajo a la vez. Hubo dos causas raíz. La primera: la nueva función de streaming de Consul, que se había ido extendiendo durante meses, se activó el día anterior a la caída también para el servicio de enrutamiento de tráfico, y el número de nodos de ese servicio se aumentó un 50%; con una carga muy alta tanto de lecturas como de escrituras, esta función provocó contención en un único recurso compartido (un canal de Go). En los servidores de doble socket (NUMA) con más núcleos que se instalaron como reemplazo durante la caída, la contención fue aún peor. La segunda: la gestión de la lista de páginas libres (freelist) de BoltDB, que Consul usa para guardar el log de Raft, se volvió patológicamente lenta y escribía 7.8 MB en disco por cada adición de 16 kB o menos. La mediana de la latencia de escritura KV, normalmente inferior a 300 ms, subió a 2 segundos, y en el servidor líder lento también se observó ventana cero (búfer TCP lleno). Como la telemetría dependía de Consul, también desaparecieron las métricas necesarias para encontrar la causa. - Lecciones: Cuando un sistema base del que dependen muchos servicios (descubrimiento de servicios, almacén de configuración, autenticación) se vuelve lento, todas las funciones se detienen a la vez. Señales que revisar: la latencia de escritura, los cambios de líder y la CPU de ese sistema, además de los cambios de configuración hechos justo antes de la caída. Los responsables son ambos: el equipo de desarrollo (servidor) y el equipo de infraestructura (servidores/SO). El monitoreo debe estar separado del sistema que vigila y no depender de él; así, durante una caída, las métricas siguen disponibles. En la recuperación, las cachés están vacías y dejar entrar a todos de golpe puede provocar otra caída, por eso Roblox reguló con DNS el porcentaje de jugadores que podían entrar y lo fue subiendo de un 10% en un 10% aproximadamente. - Causas relacionadas: in-cascade, sp-lock, rt-zero-window, db-cold-cache - Publicación original: [Roblox](https://about.roblox.com/newsroom/2022/01/roblox-return-to-service-10-28-10-31-2021) ### ffxiv-2021 · Square Enix 2021: Congestión en el lanzamiento de la expansión de FINAL FANTASY XIV y errores en la cola de inicio de sesión - Qué pasó: Desde el acceso anticipado de la expansión Endwalker, en diciembre de 2021, todos los mundos (Worlds) estuvieron extremadamente congestionados. Las colas de inicio de sesión se alargaron, y el Error 2002 aparecía a menudo al iniciar sesión desde la pantalla de selección de personaje o mientras se esperaba en la cola. También hubo caídas de algunos mundos y zonas (Error 3001) y timeouts de la cola (Error 4004). En el aviso del 11 de diciembre, el octavo día del acceso anticipado, la congestión aún continuaba. - Causa: El Error 2002 se produce en dos casos. El primero, cuando hay más de 17,000 jugadores esperando en un mismo centro de datos lógico: es un tope para evitar que una cola demasiado larga haga caer el servidor de login, y cuando se alcanza, el cliente se cierra por completo. El 7 de diciembre se destinó hardware de reserva del entorno de desarrollo a los servidores de lobby para subir el tope; este error disminuyó, pero las colas se hicieron todavía más largas. El segundo, cuando la conexión del jugador en espera es inestable. Al alargarse la espera, aumentaron los cortes breves de conexión por pérdida de paquetes en la ruta por internet o por un Wi-Fi inestable. El servidor de lobby espera la reconexión entre unas decenas de segundos y 1 minuto aproximadamente: quien se reconecta dentro de ese plazo conserva su posición en la cola, y quien tarda más vuelve al final. Square Enix indicó que la mayoría de los reportes correspondían a este caso. Por la escasez de semiconductores, tampoco se podían añadir mundos de inmediato. - Lecciones: Cuanto más larga es la cola, más a menudo un corte breve de la conexión de un jugador en espera se convierte en un error de conexión. Con la misma congestión, los errores se concentran en quienes usan Wi-Fi o conexiones inestables: es uno de esos problemas que “solo afectan a algunos”. Señales que revisar: la longitud de la cola y el tiempo de espera y, entre los motivos de desconexión, la proporción de cortes durante la espera en la cola. El responsable principal es el equipo de desarrollo (servidor: tope de la cola y periodo de gracia para reconectar), y el equipo de infraestructura colabora añadiendo servidores de lobby y de mundo. Un periodo de gracia para reconectar generoso reduce los casos en que un corte breve de la conexión del jugador termina costándole su posición en la cola. - Causas relacionadas: in-login-queue, hn-wifi, rt-wireless - Publicación original: [Square Enix](https://na.finalfantasyxiv.com/lodestone/news/detail/6a94b30182b6d963994fdc0b789264ac9f24986f) ### cloudflare-2020 · Cloudflare 2020: Pérdida de tráfico en algunas ciudades por un error de configuración en la red troncal de Cloudflare - Qué pasó: Muchos juegos confían su web, sus API y su protección DDoS a proveedores de CDN, así que este es un tipo de caída de infraestructura que también afecta a los juegos. El 17 de julio de 2020, durante 27 minutos, de 21:12 a 21:39 (UTC), el tráfico de toda la red de Cloudflare cayó cerca de un 50%. El impacto se limitó a los puntos de presencia (PoP) de algunas ciudades de EE. UU., Europa, Rusia y Brasil conectados a la red troncal; los demás PoP funcionaron con normalidad. - Causa: Una avería en el tramo de red troncal Newark–Chicago congestionó el tramo Atlanta–Washington, y un ingeniero cambió la configuración de un router para quitarle tráfico de la red troncal a Atlanta. Tenía que desactivar todo un término de la política (term), pero solo desactivó la condición que contenía (prefix-list), y el router de Atlanta difundió todas sus rutas BGP por toda la red troncal con una prioridad más alta (local-preference 200). Cada PoP asignaba prioridad 100 a las rutas hacia sus propios servidores, así que todo el tráfico de los PoP conectados a la red troncal se fue a Atlanta. Atlanta se sobrecargó y los PoP afectados se quedaron casi sin tráfico que procesar. El servicio se recuperó al retirar el router de Atlanta de la red troncal. Cloudflare aclaró que la caída no tuvo relación con ningún ataque ni intrusión. - Lecciones: Si los jugadores de ciertas ciudades o regiones sufren todos a la vez desconexiones, o el juego no les conecta o se queda en carga infinita, y los demás van bien, hay que sospechar primero de un cambio reciente en la configuración de rutas. En el gráfico, la CPU y el tráfico se disparan en un solo PoP, mientras que los PoP afectados caen casi a 0. El responsable principal es el equipo de infraestructura (red); si la caída es del lado del proveedor, es externo. Cloudflare decidió fijar un tope de rutas aceptadas (maximum-prefix) en las sesiones BGP de la red troncal y ajustó las prioridades para que un PoP no pueda atraer el tráfico de los demás. - Causas relacionadas: isp-bgp, rt-path - Publicación original: [Cloudflare](https://blog.cloudflare.com/cloudflare-outage-on-july-17-2020/) ### fastly-2021 · Fastly 2021: Errores en todo el mundo en la CDN de Fastly - Qué pasó: Muchos juegos distribuyen archivos de parche, launchers y páginas web a través de una CDN, así que este es un tipo de caída de infraestructura que también afecta a los juegos. El 8 de junio de 2021, a partir de las 09:47 (UTC), el 85% de la red de Fastly empezó a devolver errores. En 49 minutos, el 95% de la red volvió a la normalidad, y el incidente quedó resuelto a las 12:35. - Causa: Un despliegue de software iniciado el 12 de mayo contenía un bug que se activaba cuando una configuración concreta de un cliente cumplía ciertas condiciones. El 8 de junio, un cliente publicó un cambio de configuración válido que cumplía justo esas condiciones. Fastly detectó la anomalía en 1 minuto, y la recuperación empezó cuando localizó y desactivó la configuración del cliente que la había provocado. El despliegue de la corrección del bug empezó ese mismo día a las 17:25. - Lecciones: Un código desplegado semanas antes puede provocar en un instante una caída mundial cuando se encuentra con una condición poco frecuente. Del lado del juego, las señales que revisar son una subida simultánea en todas las regiones de la tasa de errores HTTP de las solicitudes de parches, launcher y web, y la página de estado del proveedor de CDN. Lo característico es que las conexiones de juego ya establecidas siguen bien si no pasan por la CDN, y solo quedan bloqueadas las conexiones nuevas, las descargas de parches y los inicios de sesión web. El responsable principal es externo (el proveedor de CDN); el equipo de desarrollo y el de infraestructura deben tener preparada una ruta alternativa, como usar más de una CDN o descargar directamente del servidor de origen. - Causas relacionadas: in-external - Publicación original: [Fastly](https://www.fastly.com/blog/summary-of-june-8-outage) ### meta-2021 · Meta 2021: Caída de Facebook: un solo comando en la red troncal se llevó por delante hasta el DNS - Qué pasó: Es una caída de infraestructura cuyas lecciones se aplican tal cual a la red y el DNS propios de una empresa de juegos. El 4 de octubre de 2021, los servicios de Facebook (hoy Meta) quedaron inaccesibles en todo el mundo. La red troncal que une sus centros de datos se cortó por completo, y desde internet ya no se podían encontrar los servidores DNS de Facebook. La retrospectiva no indica cuánto duró la caída. - Causa: Durante un trabajo de mantenimiento rutinario, un comando lanzado para evaluar la capacidad de la red troncal global cortó por error todas las conexiones de la red troncal, y la herramienta de auditoría que debía bloquear ese tipo de comandos no lo hizo por un bug. Los servidores DNS de los PoP pequeños están diseñados para marcarse como en mal estado y retirar sus anuncios BGP cuando no pueden comunicarse con los centros de datos, así que quedaron inalcanzables desde internet aunque seguían funcionando. Se cortaron tanto las vías de acceso habituales como el acceso fuera de banda (out-of-band), y las herramientas internas también perdieron el DNS, por lo que hubo que enviar ingenieros en persona a los centros de datos, y los procedimientos de seguridad alargaron aún más el proceso. En la recuperación, como el consumo eléctrico de cada centro de datos había bajado decenas de MW, se consideró que restablecerlo todo de golpe podía poner en riesgo desde las instalaciones eléctricas hasta las cachés, y la carga se subió por etapas. - Lecciones: Si en todas las regiones y con todos los ISP el juego deja de conectar o se queda en carga infinita a la vez, hay que mirar el DNS y las rutas BGP antes que los servidores del juego. Se puede comprobar desde fuera de la empresa con consultas a DNS externos y con la información pública de rutas BGP. El responsable principal es el equipo de infraestructura (red). Conviene verificar de antemano que la vía de acceso fuera de banda y las herramientas internas que se usarán durante una caída no dependen del mismo DNS ni de la misma red, y en la recuperación hay que subir la carga por etapas para que las reconexiones no lleguen todas de golpe. - Causas relacionadas: isp-bgp, isp-dns - Publicación original: [Meta](https://engineering.fb.com/2021/10/05/networking-traffic/outage-details/) ### aws-2021 · AWS 2021: Congestión de la red interna de AWS us-east-1 - Qué pasó: Muchos juegos tienen sus servidores, su inicio de sesión y sus datos en nubes públicas, así que este es un tipo de caída de infraestructura que también afecta a los juegos. El 7 de diciembre de 2021, a las 7:30 a. m. (hora estándar del Pacífico), la red interna de la región del norte de Virginia (us-east-1) se congestionó. Desde las 7:33 a. m. aumentaron los errores y la latencia de la API de EC2, y costaba lanzar instancias nuevas (el lanzamiento de instancias se recuperó a las 2:40 p. m.); después vinieron fallos de inicio de sesión en la consola, la imposibilidad de cambiar la configuración de Route 53, y retrasos y pérdidas parciales de métricas de CloudWatch. Los dispositivos de red se recuperaron por completo a las 2:22 p. m. Las instancias EC2 que ya estaban en marcha y las respuestas DNS existentes no se vieron afectadas. - Causa: Una tarea automática para ampliar la capacidad de un servicio de la red principal provocó un comportamiento inesperado en una gran cantidad de clientes de la red interna, y los intentos de conexión se dispararon. Los dispositivos que unen la red interna con la red principal se saturaron y la comunicación se retrasó; a su vez, los retrasos aumentaron los intentos de conexión y los reintentos, y la congestión se mantuvo. Los clientes tenían un comportamiento de backoff que espacia las solicitudes en situaciones de congestión como esta, pero un defecto latente impidió que funcionara bien. El monitoreo interno también dependía de esa misma red, así que el equipo de operaciones tuvo que responder apoyándose en logs, sin métricas en tiempo real. - Lecciones: Si los reintentos no espacian sus intervalos, una congestión breve se convierte en una caída de varias horas. Desde el punto de vista del juego, aunque los servidores de juego ya en marcha sigan bien, pueden bloquearse a la vez el aumento de servidores (autoescalado), el inicio de sesión, el matchmaking y los pagos que usan la API de la nube, y el monitoreo. Señales que revisar: la página de estado del proveedor de nube, la tasa de errores de la API de la nube y los fallos al lanzar instancias. El responsable principal es externo (el proveedor de nube); el equipo de desarrollo debe aplicar a todos los reintentos un backoff exponencial con intervalos aleatorios y un límite de intentos, y el equipo de infraestructura debe preparar capacidad de reserva para aguantar aunque no se pueda escalar, además de una alternativa en otra región. - Causas relacionadas: in-cascade, in-autoscale, in-external - Publicación original: [AWS](https://aws.amazon.com/message/12721/) ### cloudflare-dns-2025 · Cloudflare 2025: Caída del DNS público 1.1.1.1 de Cloudflare - Qué pasó: Es la caída de un resolver de DNS público que los jugadores configuran por su cuenta en su dispositivo o router, un tipo de incidente que bloquea a la vez todos los juegos y servicios, pero solo para quienes usan esa configuración. El 14 de julio de 2025, durante 62 minutos, de 21:52 a 22:54 (UTC), el resolver 1.1.1.1 dejó de responder en todo el mundo. Cloudflare indicó que, para mucha gente, eso significó no poder usar prácticamente ningún servicio de internet. Se vieron afectadas las consultas por UDP, TCP y DNS over TLS, mientras que DNS over HTTPS, que se conecta por nombre de dominio, se mantuvo relativamente estable. - Causa: El 6 de junio, al preparar la topología de servicio (la configuración que decide desde qué PoP se anuncia cada rango de IP) de otro servicio que se usaría en el futuro, los rangos de IP del resolver 1.1.1.1 quedaron incluidos por error en esa configuración. El 14 de julio, al cambiar la configuración de ese servicio, los PoP que anunciaban los rangos del resolver pasaron de ser todos a uno solo, que estaba fuera de línea, y las rutas BGP se retiraron en todo el mundo. Este cambio no pasó por un despliegue canario y se propagó directamente a todos los centros de datos. Al revertir la configuración a las 22:20, el tráfico volvió a cerca del 77%, pero entretanto se había borrado una configuración de IP necesaria en cerca del 23% de los servidores edge, y como hubo que volver a configurarla, la normalidad no llegó hasta las 22:54. Cloudflare indicó que fue un error de configuración interno, sin relación con ningún ataque ni secuestro de BGP (BGP hijacking). - Lecciones: Si los servidores del juego y los demás jugadores van bien, pero algunos jugadores no consiguen conectar con los servidores de login o de parches o se quedan en carga infinita, hay que sospechar del DNS que usan esos jugadores. Lo característico es que las sesiones ya conectadas se mantienen y solo fallan las conexiones nuevas. Si se les pide que cambien su configuración de DNS o que resuelvan directamente la dirección del servidor, se distingue enseguida. El responsable principal es externo (el operador del DNS o el ISP); si el equipo de desarrollo (cliente) informa de los fallos de resolución de nombres por separado de los demás errores, atención al cliente puede diagnosticarlo de inmediato. - Causas relacionadas: isp-dns, isp-bgp - Publicación original: [Cloudflare](https://blog.cloudflare.com/cloudflare-1-1-1-1-incident-on-july-14-2025/) ### aws-2025 · AWS 2025: Fallo de DNS de DynamoDB en AWS us-east-1 y su larga recuperación - Qué pasó: Muchos juegos tienen sus servidores, su inicio de sesión y sus datos en nubes públicas, así que este es un tipo de caída de infraestructura que también afecta a los juegos. Desde las 11:48 p. m. del 19 de octubre de 2025 hasta las 2:20 p. m. del día 20 (hora de verano del Pacífico), la región del norte de Virginia sufrió un impacto en tres fases. Hasta las 2:40 a. m. del día 20 aumentaron los errores de la API de DynamoDB; de 2:25 a. m. a 10:36 a. m. falló el lanzamiento de nuevas instancias EC2 (los problemas de conectividad de algunas instancias nuevas se resolvieron a la 1:50 p. m.), y de 5:30 a. m. a 2:09 p. m. aumentaron los errores de conexión en algunos Network Load Balancer (NLB). - Causa: La automatización que gestiona el DNS de DynamoDB tenía una condición de carrera (race condition) latente. Entre los ejecutores que aplican los planes de DNS en distintas zonas de disponibilidad (DNS Enactor), uno que se había retrasado de forma inusual sobrescribió un plan nuevo con otro antiguo; justo después, la tarea de limpieza de otro ejecutor borró ese plan antiguo, y el registro DNS del endpoint regional (dynamodb.us-east-1.amazonaws.com) quedó vacío. La automatización no pudo corregirlo y hubo que restaurarlo a mano. El sistema de gestión de servidores físicos de EC2 dependía de DynamoDB, así que, mientras tanto, expiraron las concesiones (leases) que mantenía con cada servidor físico. Cuando DynamoDB volvió, había tantos servidores físicos que las tareas para restablecer las concesiones agotaban el tiempo antes de terminar, los reintentos volvían a acumularse y el sistema entró en un estado de “colapso por congestión” (congestive collapse). La configuración de red de las instancias recién lanzadas se propagaba con retraso, así que los health checks de NLB alternaban entre éxito y fallo, y hasta los nodos sanos salían del DNS y volvían a entrar una y otra vez. - Lecciones: Un error en un registro DNS de un solo lugar se extiende a los demás servicios que dependen de ese servicio, y aun después de resolver la causa, el trabajo acumulado y la inestabilidad de los health checks alargan la recuperación varias horas más. Desde el punto de vista del juego, los servidores ya en marcha pueden aguantar, pero no se pueden lanzar servidores nuevos y el autoescalado se detiene; además, si los health checks oscilan, el balanceador de carga puede sacar servidores que están bien. Señales que revisar: la página de estado de la nube, la tasa de errores de las API de servicios gestionados, los fallos al lanzar instancias y el número de destinos en buen estado del balanceador de carga. El responsable principal es externo (el proveedor de nube); el equipo de infraestructura debe limitar cuántos servidores pueden salir a la vez por fallos de health check y preparar una alternativa en otra región. - Causas relacionadas: in-external, in-cascade, in-autoscale, dc-lb-imbalance, isp-dns - Publicación original: [AWS](https://aws.amazon.com/message/101925/) ## Términos - **Ping** (Ping, RTT): Lo que tarda una señal tuya en llegar al servidor y volver (ida y vuelta). El ping que muestra el juego a veces incluye también el tiempo de espera de procesamiento en el servidor. - **Latencia** (Latency): Tiempo que tarda un paquete desde que sale hasta que llega. Como suele referirse a un solo sentido, ronda la mitad del ping. - **Jitter** (Jitter): Variación en el intervalo de llegada de los paquetes. Con el mismo ping medio, si el jitter es alto la imagen va a tirones. - **Paquete** (Packet): Bloque de datos que se envía de una vez por la red. Suele tener como máximo 1,500 bytes; las actualizaciones de un juego ocupan de decenas a cientos de bytes. - **Pérdida de paquetes** (Packet loss): Paquetes enviados que nunca llegan. En un juego con TCP, con solo un 1% ya se nota un tirón cada pocos segundos o cada diez y tantos segundos; un juego con UDP que tenga interpolación y envío redundante de inputs puede disimular pérdidas de varios puntos porcentuales. - **Ancho de banda** (Bandwidth): Cantidad máxima de datos que la conexión puede transmitir por segundo (Mbps). Es un concepto distinto de lo rápido que llegan los datos (latencia). - **Tick** (Tick): Cada actualización del estado del juego que calcula el servidor. Un servidor de 20 ticks calcula 20 veces por segundo, cada 50 ms. - **Tick rate** (Tick rate): Cuántos ticks se ejecutan por segundo. Cuanto más alto, más rápida la respuesta, pero también más costo de servidor y más tráfico. Para ahorrar tráfico, a veces la frecuencia de envío de paquetes se fija por debajo del tick rate. - **Presupuesto del tick** (Tick budget): Tiempo máximo para terminar un tick. Si se excede, el siguiente tick se retrasa y el intervalo entre ticks se alarga. - **FPS** (Frames per second): Cuántas veces por segundo se dibuja la imagen. A 60 FPS, cada frame dura 16.7 ms. - **Tiempo de frame** (Frame time): Lo que se tarda en dibujar un frame. Para la sensación de fluidez importan más los frames que se disparan de vez en cuando que los FPS medios. - **Snapshot** (Snapshot): Resumen del “estado actual del juego” que el servidor envía en cada tick: posiciones, vida, estados, etc. Normalmente solo incluye lo que cambió respecto a lo que el receptor ya tiene (compresión delta). - **Interpolación** (Interpolation): Técnica que dibuja el paso intermedio entre dos snapshots recibidos para que el movimiento se vea fluido. A cambio, muestra algo un poco atrasado. - **Búfer de interpolación** (Interpolation buffer): Retraso intencionado al dibujar para poder interpolar. Es el margen que absorbe el jitter y la pérdida de uno o dos paquetes. Suele ser el doble del intervalo entre paquetes (100 ms si se reciben 20 por segundo), y algunos juegos lo amplían solos cuando aumenta el jitter. - **Extrapolación** (Extrapolation, Dead reckoning): Técnica que, cuando no llegan paquetes nuevos, estima dónde estará la entidad según su última velocidad y la dibuja ahí. Si falla, parece un teletransporte, así que muchos juegos solo extrapolan unos 0.25 s y después dejan de hacerlo (valor por defecto del motor Source: 0.25 s). - **Predicción en el cliente** (Client-side prediction): Técnica que mueve tu personaje en pantalla sin esperar la confirmación del servidor. - **Reconciliación con el servidor** (Reconciliation): Cuando llega el resultado del servidor, se compara con la predicción y se corrige la posición de tu personaje. Se parte de la posición confirmada por el servidor y se vuelven a aplicar tus inputs aún sin confirmar. Si la diferencia es grande, se ve como rubber banding. - **Compensación de lag** (Lag compensation): Técnica con la que el servidor, al validar un ataque, rebobina al momento que veía el atacante para comprobar si acertó. Para que no sea injusto con quien recibe el golpe, se limita cuánto se puede rebobinar. En shooters competitivos lo habitual ronda 0.2–0.25 s, y hay casos que rebobinan hasta 1 s, como el valor por defecto del motor Source. - **Servidor autoritativo** (Authoritative server): Diseño en el que solo el servidor tiene la última palabra. Frena las trampas, pero todo resultado pasa por un viaje de ida y vuelta al servidor. Por eso la espera se disimula con predicción y feedback anticipado. - **Lockstep** (Deterministic lockstep): Modelo en el que todos intercambian solo los inputs y cada uno calcula lo mismo en el mismo turno. Se añade un retraso fijo a los inputs, y si el input de cualquiera llega tarde, todos esperan. - **Búfer de inputs del servidor** (Server-side input buffer): Búfer en el que el servidor acumula unos pocos inputs de cada jugador y consume uno por tick. Así, alguien con mucho jitter se ve fluido para los demás, pero sus acciones se confirman en el servidor con ese mismo retraso. - **Listen server** (Listen server): Modelo en el que uno de los jugadores juega y a la vez hace de servidor desde su PC. El anfitrión tiene ping 0, pero si su conexión o su PC van lentos, todos sufren lag. - **Phasing** (Phasing): Función que, en un mismo lugar, muestra NPC y terreno distintos según el progreso de las misiones. Si dos personajes van por puntos distintos, es normal que a uno le falte un NPC. - **Netcode de rollback** (Rollback netcode (GGPO)): Modelo que predice el input del rival y sigue adelante; si el input real es distinto, rebobina a frames anteriores y vuelve a calcular. Es muy común en juegos de lucha. No tiene relación con el rollback de una base de datos. - **Búfer de inputs** (Input buffer, spell queue): Guarda el siguiente input si lo presionas poco antes de que termine el cooldown o la animación, y lo ejecuta justo al terminar. Así no se mete el tiempo de ida y vuelta entre acciones encadenadas. - **Feedback anticipado** (Client-side feedback): Reproducir animaciones, sonidos y efectos sin esperar la confirmación del servidor. Solo los resultados que necesitan confirmación, como el daño o las recompensas, esperan su respuesta. Si el servidor rechaza la acción, hay que deshacer lo que ya se mostró. - **TCP** (Transmission Control Protocol): Protocolo que entrega los datos en orden y sin huecos. Hasta recibir de nuevo un paquete perdido, no entrega al juego los que vienen detrás. - **UDP** (User Datagram Protocol): Protocolo que entrega los datos tal como llegan, sin ninguna garantía. No hay esperas, y a cambio el propio juego se encarga de la pérdida y el orden. - **UDP confiable** (Reliable UDP (KCP, ENet…)): Retransmisión y entrega en orden implementadas sobre UDP por el propio juego, solo en la medida necesaria. - **Bloqueo HOL** (Head-of-line blocking): Bloqueo de cabeza de línea: el primero de la cola se atasca y todos los de detrás esperan. Es la causa de la cámara rápida en TCP. - **RTO** (Retransmission timeout): Temporizador de retransmisión: lo que espera TCP antes de dar un paquete por perdido y reenviarlo. En Linux, ping + 200 ms como mínimo, y se duplica con cada fallo. - **Algoritmo de Nagle** (Nagle’s algorithm): Función de TCP que reduce el número de paquetes: retiene los datos pequeños hasta recibir el acuse (ACK) de lo enviado antes y los manda juntos. En juegos casi siempre hay que desactivarla. - **TCP_NODELAY** (TCP_NODELAY): Opción de socket que desactiva el algoritmo de Nagle. Los mensajes pequeños salen al instante. - **ACK retardado** (Delayed ACK): Función que envía el acuse de recibo con un pequeño retraso, junto con otros datos. En Linux suele ser 40 ms (máximo 200 ms); en Windows, 200 ms en versiones antiguas y 40 ms en las actuales. - **Búfer de socket** (SO_SNDBUF / SO_RCVBUF): Tamaño del espacio de espera de envío y recepción que el SO reserva para cada socket. Si es muy pequeño, se desborda; si es muy grande, se acumulan datos viejos que esperan su turno. - **keepalive** (SO_KEEPALIVE): Función de TCP que comprueba si una conexión inactiva sigue viva. Viene desactivada, y aunque se active, por defecto no comprueba hasta pasadas 2 horas. - **RST** (TCP reset): Señal de TCP que corta la conexión en el acto. Los datos que aún no se enviaron se descartan. - **Heartbeat** (Heartbeat): Señal de “sigo vivo” que el propio juego envía periódicamente. Sirve para detectar conexiones caídas y para que los dispositivos intermedios mantengan la conexión. - **Timeout** (Timeout): Tiempo sin respuesta a partir del cual algo se da por fallido. Si es muy corto, hay falsas alarmas; si es muy largo, la detección llega tarde. - **NAT** (Network Address Translation): Función del router que hace salir a todos los dispositivos de la casa con una sola IP pública y anota cada conexión en la tabla NAT. - **CGNAT** (Carrier-grade NAT): NAT a gran escala con la que el ISP reparte una sola IP entre varios abonados. - **MTU** (Maximum Transmission Unit): Tamaño máximo de un paquete que se puede enviar de una vez. Suele ser 1,500 bytes, y es menor en tramos con VPN o PPPoE. - **Bufferbloat** (Bufferbloat): Fenómeno en el que un dispositivo acumula colas demasiado grandes y la latencia sube a cientos de ms. - **SQM** (Smart Queue Management (fq_codel, CAKE)): Función del router que mantiene las colas cortas y reparte la salida de forma equitativa entre flujos. Es la solución al bufferbloat. - **QoS** (Quality of Service): Función que da prioridad al tráfico importante para que salga primero. - **Peering** (Peering): Punto donde los ISP conectan sus redes entre sí. Suele congestionarse por la noche. - **BGP** (Border Gateway Protocol): Protocolo con el que los ISP se indican por qué ruta enviar el tráfico en internet. Si cambia, cambian la ruta y el ping. - **DDoS** (Distributed Denial of Service): Ataque que envía tráfico masivo desde muchos orígenes para paralizar un servicio. - **Centro de depuración** (DDoS scrubbing center): Instalación de un proveedor de protección DDoS que, durante un ataque, recibe primero el tráfico destinado al servidor, filtra el ataque y solo deja pasar el tráfico legítimo. Si está lejos, la ruta se alarga. - **Firewall** (Firewall): Dispositivo o programa que solo deja pasar las conexiones permitidas. Hace seguimiento de las conexiones con una tabla de sesiones. - **Balanceador de carga** (Load balancer): Dispositivo que reparte las conexiones entrantes entre varios servidores. - **Tabla de sesiones** (Session table, conntrack): Tabla con la que un dispositivo o el SO hace seguimiento de las conexiones activas. Tiene un tamaño máximo. - **Microrráfaga** (Microburst): Pico de tráfico concentrado en un instante muy corto, de 1 ms o menos, aunque la media sea baja. - **NIC** (Network Interface Card): Tarjeta de red del servidor. - **Búfer circular** (Ring buffer): Búfer donde la NIC guarda los paquetes recibidos hasta que la CPU los recoge. Reutiliza en círculo un número fijo de slots, y cuando todos están ocupados, los paquetes nuevos se descartan. - **Interrupción** (Interrupt): Señal con la que un dispositivo avisa a la CPU de que “hay trabajo”. - **RSS** (Receive Side Scaling): Función de la NIC que reparte los paquetes recibidos en varias colas de recepción para que los procesen varios núcleos de CPU. - **PPS** (Packets per second): Paquetes por segundo. Un servidor de juego suele llegar antes al límite de esta cifra que al del ancho de banda. - **Kernel** (Kernel): Núcleo del sistema operativo. Se encarga de la red, la memoria y el reparto de la CPU. - **backlog** (Listen backlog): Cola donde esperan las solicitudes de conexión nuevas que el servidor aún no aceptó. Si se llena, Linux descarta las nuevas sin avisar y Windows responde con un rechazo. - **TIME_WAIT** (TIME_WAIT): Estado en el que el lado que cerró primero la conexión mantiene esa combinación de puertos un tiempo (60 s en Linux) por si llegan paquetes rezagados. - **CPU steal** (Steal time): Tiempo que una máquina virtual quiso usar la CPU pero tuvo que esperar porque el servidor físico se la estaba dando a otra máquina virtual. Se ve en el valor st de top. - **Throttling de CPU** (CFS throttling): Cuando un contenedor agota su cuota de CPU (quota) dentro de un periodo fijo (CFS period, normalmente 100 ms), se le obliga a quedarse detenido hasta el siguiente periodo. - **Descriptor de archivo** (File descriptor): Número (fd) que se asigna a cada archivo o conexión que abre un proceso. Hay un límite de cuántos puede haber. - **Hilo** (Thread): Unidad de trabajo que se ejecuta de forma independiente dentro de un programa. Pueden ejecutarse varios hilos a la vez. - **Cambio de contexto** (Context switch): Cuando la CPU deja de ejecutar un hilo para pasar a otro. Tiene un costo. - **Lock** (Lock, Mutex): Mecanismo que impide que más de un hilo use a la vez unos datos compartidos. - **Deadlock** (Deadlock): Situación en la que varios hilos esperan cada uno el lock que tiene el otro y se quedan detenidos para siempre. - **Pool de hilos** (Thread pool): Conjunto de hilos de trabajo creados de antemano. Si todos están ocupados, el trabajo nuevo espera. - **E/S asíncrona** (epoll, IOCP, io_uring): Modelo en el que el programa no espera a que termine la entrada/salida: sigue con otras tareas y recibe un aviso cuando se completa. - **AOI** (Area of Interest): El “rango que puede ver” cada jugador. Solo se envían los cambios dentro de él, lo que reduce el tráfico. Para abaratar el cálculo de quién está dentro, se suele dividir el mapa en una cuadrícula (grid) y mirar solo las celdas cercanas. - **Broadcast** (Broadcast, fan-out): Enviar un cambio a todos los que pueden verlo. Si todos los presentes se ven entre sí, el volumen de envío crece con el cuadrado del número de jugadores. - **GC** (Garbage collection): Recolección de basura: recupera automáticamente la memoria que ya no se usa. Durante el GC el programa puede quedarse detenido. - **Heap** (Heap): Zona de memoria que el programa va pidiendo y usando según la necesita durante la ejecución. - **Fuga de memoria** (Memory leak): Error por el que la memoria que ya no hace falta no se libera y el uso crece sin parar. Ocurre incluso con GC si alguna parte del código sigue referenciando objetos que ya no se usan. - **Swap** (Swap, paging): Mover parte de la memoria al disco cuando falta RAM. Volver a usar esa memoria es más de 1,000 veces más lento que leerla de la RAM. - **OOM killer** (Out-of-memory killer): Función de Linux que, cuando se agota la memoria, elige el proceso que más memoria usa y lo termina a la fuerza. En contenedores actúa en cuanto se alcanza el límite de memoria. - **Fallo de caché** (Cache miss): Cuando los datos no están en la caché cercana a la CPU y hay que ir a buscarlos a la memoria, que es más lenta. - **IOPS** (I/O operations per second): Número de lecturas y escrituras que un disco puede hacer por segundo. En los discos en la nube, el límite depende de lo que pagues. - **fsync** (fsync): Llamada que espera hasta que los datos quedan escritos de verdad en el disco. Una escritura normal pasa primero por la memoria del SO y llega al disco más tarde, así que si el servidor se apaga entre medias, puede perderse. fsync es seguro pero lento. - **Créditos de ráfaga** (Burst credits): Saldo que acumulan los discos y servidores en la nube para rendir por encima de su nivel base durante un rato. Cuando se agota, el rendimiento cae al nivel base. - **Índice** (Index): Estructura de la BD que permite encontrar filas sin recorrerlo todo. Sin ella, hay que leer la tabla entera. - **Escaneo completo** (Full table scan): Consulta que revisa todas las filas de una tabla sin usar índices. - **Plan de ejecución** (Query plan): La forma en que la BD decide resolver una consulta: en qué orden y con qué índices. Aunque el código no cambie, si la BD cambia de plan, la misma consulta puede volverse lenta de repente. - **Transacción** (Transaction): Conjunto de operaciones de BD agrupadas en “todo o nada”. Los intercambios entre jugadores deben procesarse siempre en una transacción. Como bloquea las filas modificadas hasta terminar, cuanto más corta, mejor. - **Pool de conexiones** (Connection pool): Conjunto de conexiones a la BD abiertas de antemano. Si todas están en uso, las solicitudes nuevas esperan. - **Fila caliente** (Hot row): Una fila que muchas solicitudes intentan modificar a la vez. Provoca contención de bloqueos. - **Retraso de replicación** (Replication lag): Tiempo que la réplica de la BD va por detrás de la BD principal. - **Rollback** (Rollback): Cuando un guardado se cancela y todo vuelve al estado anterior. El jugador lo vive como “desapareció el objeto”. - **Caché** (Cache (Redis etc.)): Copia de los datos más usados en un lugar de acceso rápido. Reduce la carga de la BD. - **Checkpoint** (Checkpoint): Proceso periódico en el que la BD vuelca de golpe al disco los cambios acumulados en memoria. En ese momento, guardados y consultas pueden ir lentos un instante. - **Failover** (Failover): Paso al servidor o la BD de respaldo cuando cae el principal. Mientras dura el cambio no se puede guardar, y si la replicación iba atrasada, pueden perderse los últimos datos. - **MVCC** (Multi-version concurrency control): Método con el que la BD guarda temporalmente versiones antiguas de los datos para que lecturas y escrituras no se bloqueen entre sí. Si hay transacciones abiertas mucho tiempo, las versiones antiguas se acumulan y todo se ralentiza. - **Estampida de caché** (Cache stampede): La caché se vacía de golpe y todas las solicitudes se lanzan contra el origen (la BD). - **Gateway** (Gateway): Servidor intermedio que recibe las conexiones de los clientes y las reenvía a los servidores de juego que hay detrás. - **Circuit breaker** (Circuit breaker): Mecanismo que, cuando las llamadas a un servicio fallan una y otra vez, las corta temporalmente y las da por fallidas al instante para evitar un fallo en cascada. Pasado un tiempo, prueba con una o dos llamadas y, si el servicio se recuperó, vuelve a permitirlas. - **Fallo en cascada** (Cascading failure): Un fallo en un punto que se propaga a otros servicios a lo largo de la cadena de llamadas. - **Autoescalado** (Autoscaling): Función que aumenta o reduce automáticamente el número de servidores según la carga. Añadir servidores lleva su tiempo. - **Watchdog** (Watchdog): Temporizador que vigila si el servidor se quedó detenido. Si el bucle del juego lleva detenido más de cierto tiempo (de unos segundos a decenas de segundos), guarda un volcado del estado (dump) y fuerza el cierre del servidor para que se reinicie. - **Utilización** (Utilization): Porcentaje del tiempo que está ocupado un worker (lo que atiende las solicitudes: un núcleo de CPU, un hilo, una conexión de BD). Por encima del 80–90%, las esperas se disparan. - **p99** (99th percentile): Valor por debajo del cual quedan 99 de cada 100 mediciones; 1 de cada 100 es más lenta. Refleja el lag que se siente mejor que la media. - **V-Sync** (Vertical sync): Función que envía los frames al ritmo de refresco de la pantalla. Elimina el tearing, pero añade input lag, y si los FPS bajan de la tasa de refresco, pueden saltar entre 60 y 30 y provocar tirones. - **Tasa de refresco variable** (VRR, G-Sync, FreeSync): Función con la que el monitor refresca la imagen en cuanto hay un frame listo. Reduce los tirones de saltar entre 60 y 30 con V-Sync y también el input lag. - **Anti-cheat** (Anti-cheat): Módulo de seguridad contra trampas y hacks. Si fallan sus comprobaciones periódicas o su heartbeat con el servidor, puede provocar tirones o desconexiones. - **Overlay** (Overlay): Función con la que programas de chat, grabación o contador de FPS dibujan encima de la imagen del juego. Se mete en el proceso de dibujado del juego y puede provocar tirones. - **Compilación de shaders** (Shader compilation): Convertir los programas de efectos gráficos al formato de la GPU. Si no se hace de antemano, la imagen da un tirón la primera vez que aparece un efecto, y al actualizar los drivers gráficos el resultado guardado deja de valer y hay que repetirlo. - **Hilo principal** (Main thread, Game thread): Hilo central del juego que procesa por turnos la lógica del juego y la preparación de la imagen. Si una sola tarea tarda mucho en él, la imagen se detiene mientras tanto. - **Resolución del temporizador** (Timer resolution): Intervalo mínimo con el que el sistema operativo puede despertar a un programa en espera. En Windows es 15.6 ms por defecto, así que si el programa no lo cambia, aunque pida “despiértame en 1 ms” se despertará más tarde. - **Thermal throttling** (Thermal throttling): Protección por la que un dispositivo baja la velocidad de su CPU y GPU cuando se calienta. En teléfonos es habitual tras jugar de unos minutos a decenas de minutos. - **VRAM** (Video memory): Memoria propia de la tarjeta gráfica, donde se cargan las texturas y los modelos para dibujarlos. Si no alcanza, hay que intercambiar datos con la RAM del sistema por una vía lenta y aparecen tirones. - **Net graph** (Net graph): Indicador de desarrollo y depuración que muestra en pantalla gráficos en tiempo real de ping, pérdida, FPS y ticks. Si aparece en el video de un reporte de lag, encontrar la causa es mucho más fácil. - **Tasa de retransmisión** (Retransmission rate): Porcentaje de paquetes TCP enviados que hubo que reenviar. No hay un umbral oficial, pero una media de todo el servidor por debajo del 0.1% se considera sana, y por encima del 1% es fácil que muchos jugadores noten lag. También conviene ver cuántas veces supera su valor habitual. - **SACK** (Selective ACK): ACK selectivo: función de TCP con la que el receptor detalla “recibí este tramo y solo falta esta parte”. Permite recuperar varias pérdidas de una vez. - **RACK-TLP** (Recent ACK, Tail Loss Probe): Función de TCP que detecta pérdidas por tiempo y, si pasa un rato sin ACK, reenvía el último paquete para adelantar la recuperación. Viene activada por defecto en las versiones recientes de Linux y Android. En Windows, TLP y RACK están activados por defecto desde Windows 10 (1607) y Server 2016, y el RACK nuevo, que también recupera retransmisiones perdidas, llega con Server 2022. Solo funciona en conexiones con SACK activado. - **Retransmisión espuria** (Spurious retransmission): Reenvío de un paquete que no se había perdido: llegó tarde o desordenado y se tomó por perdido. Desperdicia la conexión y reduce el ritmo de envío sin motivo. - **Ventana cero** (Zero window): Estado en el que el receptor, con el búfer lleno, avisa “deja de enviar un momento”. Parece una retransmisión, pero la conexión está bien: el programa receptor no leyó los datos a tiempo. - **thin stream** (Thin stream): Conexión que envía paquetes pequeños de vez en cuando, como la de un juego. Como apenas se juntan señales para la retransmisión rápida, cuando hay pérdida se queda detenida mucho tiempo. - **Policer** (Policer): Limitador de velocidad que descarta al instante, sin encolarlos, los paquetes que superan la velocidad fijada. El que los encola y los deja salir despacio se llama shaper. - **Pacing** (Pacing): Repartir el envío de paquetes de forma uniforme en el tiempo, sin soltarlos todos de golpe. Evita que se desborden los búferes pequeños. - **ECN** (Explicit Congestion Notification): Función que, ante la congestión, marca los paquetes como “congestionado” y los deja pasar, para que el emisor reduzca la velocidad. Avisa de la congestión sin pérdidas. Solo sirve si la soportan ambos extremos y los equipos de red del tramo congestionado. - **MSS** (Maximum Segment Size): Tamaño máximo de datos que TCP mete en un paquete. Suele ser 1,460 bytes; reducirlo para los tramos con túnel evita los agujeros negros de MTU. - **Handover** (Handover): Cuando un teléfono en movimiento cambia de estación base. - **Percentil** (Percentile (p50, p95, p99)): Valor que ocupa cierta posición (en %) al ordenar las mediciones de menor a mayor. p50 es la mediana; p99 está cerca de la medición más lenta de cada 100. Muestra los picos que la media esconde. - **Latencia de cola** (Tail latency): Las esperas largas que aparecen de vez en cuando aunque casi todo vaya rápido. Apenas se notan en la media, pero son lo que el jugador recuerda como lag. - **Monitoreo sintético** (Synthetic monitoring): Medir la calidad de una ruta con dispositivos o servidores de medición que, desde puntos fijos y sin depender de jugadores reales, lanzan periódicamente ping, traceroute y similares. RIPE Atlas es la herramienta pública más conocida. - **Intervalo de agregación** (Aggregation interval): Cuántos segundos o minutos de datos resume cada punto de un gráfico. Cuanto más largo, más se diluyen los picos cortos en la media. - **Postmortem** (Postmortem): Documento que se escribe tras un incidente: qué pasó, por qué y qué se va a cambiar. Su objetivo es evitar que se repita, sin buscar culpables. - **C-state** (CPU idle state): Estado de ahorro de energía en el que entra la CPU cuando está inactiva. Cuanto más profundo, más energía ahorra, pero más tarda en despertar. - **Migración en vivo** (Live migration): Cuando el proveedor de nube mueve una máquina virtual en ejecución a otro host, por ejemplo por mantenimiento del host. En el momento del traslado puede quedarse detenida un instante. - **SNAT** (Source NAT): NAT que cambia la dirección de origen de los paquetes salientes por una dirección pública. Cada dirección pública tiene un número limitado de puertos, y cuando se agotan, las conexiones nuevas fallan. - **Gateway NAT** (NAT gateway): Servicio de la nube que permite a los servidores de una red privada salir a internet compartiendo una dirección pública. Tiene un límite de conexiones simultáneas por destino. - **Internet satelital de órbita baja** (LEO satellite internet): Internet a través de satélites a cientos o miles de km de altura. La latencia es mucho menor que con satélites geoestacionarios, pero puede dar picos cuando se cambia de satélite. - **GeoIP** (IP geolocation): Base de datos que estima el país, la ciudad y el ISP a partir de una dirección IP. Puede tener entradas erróneas o desactualizadas, y a veces por eso se asigna un servidor de una región lejana. - **Certificado TLS** (TLS certificate): Documento digital que demuestra que un servidor es quien dice ser. Tiene un periodo de validez y, si expira, la conexión cifrada falla y no se puede conectar. - **Generación de frames** (Frame generation): Técnica con la que la tarjeta gráfica intercala frames estimados entre los que dibuja de verdad para subir los FPS. La imagen se ve más fluida, pero la latencia entre el input y la pantalla puede aumentar.