- Hola. Soy Sasha, trabajo en Yandex, durante los últimos tres años he estado desarrollando un balanceador de carga L7. Te contaré una forma rápida y sencilla de acelerar tu red. Comenzaremos en el séptimo nivel, HTTP, y bajamos al cuarto nivel, TCP. Hoy solo hablaremos de estos dos niveles y nos detendremos en ellos con cierto detalle.
En los últimos ocho años he estado haciendo más desarrollo de backend, y lo más probable es que mi conocimiento se mantuviera al nivel de AngularJS en las primeras versiones. Probablemente sepa mejor que yo cómo funciona todo. Ya lo tienes todo optimizado, comprimido todo, y aquí no puedo aconsejarte nada.
Pero puedo aconsejarle sobre cómo acelerar su red optimizando el servidor en sí, el sistema operativo en sí.
Para acelerar algo, necesita métricas. En este caso, usamos lo siguiente: el tiempo promedio hasta el primer byte nos muestra qué tan rápido es la capa TCP, y la segunda métrica es el tiempo para recibir HTML desde el primer byte. Experimentamos, medimos nuestras métricas y, después de activar BBR, nuestra aceleración fue de aproximadamente un diez por ciento.
Para entender qué es el diez por ciento, recurrimos al valor absoluto, que es 66 milisegundos. Si va a su juego multijugador en línea favorito, el ping a los servidores de Europa occidental será de aproximadamente 60-70 milisegundos.
Como hacerlo rapido
Todos nuestros servidores se gestionan mediante protocolos de control remoto, en este caso SSH. Si aún no ha encontrado SSH, puede pedirle al administrador del sistema que configure su servidor. Te diré cómo convencerlo de que haga esto.
¿Qué es BBR? Este es uno de los algoritmos que nos permite controlar cómo van los paquetes a la red. Y está configurado con los siguientes dos parámetros. La primera es configurar el programador de paquetes en FQ, luego le diré por qué debería usar FQ. El segundo es la inclusión del propio control de congestión, es decir, el propio BBR.
Parece que aquí es donde podríamos terminar. Pero, de hecho, existen muchas trampas y, lo más probable, su administrador de sistemas no solo activará BBR en el servidor. Por tanto, iremos más allá.
HTTP / 2 y multiplexación
Comenzaremos en el nivel 7, que es HTTP, y avanzaremos lentamente hacia abajo para revisar nuestros protocolos.
Comenzaremos con nuestros navegadores con los que interactuamos todos los días. Vemos la consola del desarrollador web. La consola tiene un campo interesante para nosotros: el protocolo.
En nuestro caso, los protocolos son HTTP / 1 y HTTP / 2. También existe el protocolo HTTP / 3, que se basa en el protocolo QUIC de Google. Pero hoy no volveremos sobre él, ya que está en desarrollo, aún no aprobado por completo. Volvamos a HTTP / 1.
En la diapositiva, vemos la utilidad Wireshark, que nos permite analizar nuestros paquetes, la forma en que interactuamos con la red. Vemos que un campo está resaltado en verde. Esta es nuestra solicitud HTTP. A continuación podemos ver los bytes, cómo se presentarán en la red.
¿Cómo se ve HTTP / 1 en la vida real? Este es un protocolo bastante simple. Está completamente basado en texto, es decir, simplemente escribimos el texto y lo enviamos a la red. Nuestros caracteres están codificados con valores hexadecimales especiales. A la derecha hay una tabla ASCII, una pequeña pieza para que pueda navegar.
Tenemos la primera parte en forma de encabezados, que está separada por los caracteres "\ r \ n \ r \ n" de nuestro cuerpo. Solo estamos solicitando un recurso regular aquí con el método GET, por lo que esta solicitud no tendrá cuerpo. Y vemos que los bytes son aproximadamente similares a lo que está en la tabla ASCII. Estamos solicitando algún tipo de JS, algún tipo de recurso. También hay un encabezado de Host que indica el dominio con el que estamos trabajando actualmente. Y - un conjunto adicional de encabezados. Pueden ser personalizados, puedes usar cualquiera.
HTTP / 2 es un protocolo más complejo. Es binario y la unidad más pequeña de intercambio de información son los marcos. Hay muchos casos especiales, tipos especiales de estos marcos. Puede ver en la diapositiva que están resaltados.
También podemos observar en la primera línea que dos marcos pueden caber en un paquete a la vez. No nos detendremos en detalles sobre qué marcos existen, hay bastantes de ellos. En este caso, nos interesará el marco de encabezados, porque solo nos permite solicitar recursos. Estuve un poco involucrado en el desarrollo de Wireshark, ayudando a mejorarlo en este campo.
Podemos ver que hay una solicitud de obtención. Vemos que en el medio hay una representación textual de esta solicitud de obtención. Pero en la columna de la derecha solo vemos un byte asignado, y será este método de obtención. A continuación, explicaré por qué sucede esto.
A continuación, tenemos el encabezado de la ruta, que indica la ruta al recurso, a nuestro JS, que solicitaremos. Y hay un conjunto de algunos encabezados adicionales que también estarán presentes en nuestra solicitud.
Entonces, ¿por qué nuestros bytes en la red no son iguales a cómo se dibuja todo esto en nuestra imagen? El caso es que Wireshark nos muestra el resultado final, cómo lo decodificó todo. Y en la red, estos bytes, estos encabezados, se comprimirán con un formato especial HPACK. Es mejor conocer más detalles en Internet. Busque información, está bien documentada.
Volvamos a nuestras picaduras. Hay un campo especial: identificador de contenido. Indica con qué recurso están trabajando actualmente estos marcos. En este caso, enviamos la primera trama, recibimos los datos. Cuando el servidor nos proporcione los bytes de contenido, el marco de datos ya se utilizará.
Nuestros protocolos HTTP / 1 y HTTP / 2 son muy diferentes. Ya hemos hablado del hecho de que HTTP / 1 es un protocolo de texto y HTTP / 2 es binario, es decir, funciona mediante marcos.
HTTP / 1, en el caso de una solicitud como una conexión única, devolverá un resultado desconocido, dependiendo de la implementación de la forma en que los desarrolladores del servidor web lo escribieron. Es decir, si hacemos dos solicitudes en una conexión, lo más probable es que se devuelva una respuesta a la primera o la segunda solicitud. Para ello, para cargar recursos en paralelo, el navegador establece varias conexiones, generalmente unas seis, y carga recursos en paralelo.
HTTP / 2, a su vez, utiliza una única conexión. Es decir, establece la conexión y en su interior carga todos los datos necesarios a través de marcos. Esta técnica de empaquetar múltiples recursos en una conexión se llama multiplexación.
Está claro por cómo funcionan nuestras conexiones: en caso de pérdida de paquetes en una de las conexiones, HTTP / 1 funcionará mejor. Lo más probable es que no toquemos otras conexiones, seguirán cargándose a la misma velocidad. Y en el caso de HTTP / 2, si nuestro paquete se pierde, la carga de todos los recursos comienza a ralentizarse.
Parece que HTTP / 2 es peor, también es sensible a la pérdida de paquetes. De hecho, cuando creamos cada una de estas seis conexiones, estamos realizando la siguiente operación.
El cliente y el servidor establecen una conexión confiable, una conexión TCP. Enviamos dos paquetes del cliente al servidor y un paquete se envía del lado del servidor al cliente. Por lo tanto, parece que estamos listos para transferir datos. Esto, por supuesto, crea recursos generales, podemos hacer esto durante mucho tiempo.
También hay cifrado. Si observa su navegador ahora, lo más probable es que vea un icono de candado. Mucha gente lo llama SSL, pero en realidad no es SSL. Esto es TLS. SSL ha estado desactualizado durante mucho tiempo, prácticamente no es compatible y debe abandonarse.
TLS también tiene intercambio de paquetes. Es decir, nosotros, al igual que en el caso de un protocolo de enlace de TCP, establecemos un cierto estado, después del cual podemos continuar trabajando. En este punto, también podemos hacer optimización, pero los navegadores aún no son compatibles con las cosas que ya hemos habilitado desde el lado del servidor. Esperaremos a que todos lo enciendan.
Érase una vez, HTTP / 1 intentó resolver el problema de la carga concurrente de recursos. El RFC lo tiene. Y una vez, se implementó la canalización. Debido a la complejidad de la implementación, Internet Explorer no lo admite, mientras que Firefox y Chrome sí, pero el soporte se ha ido reduciendo con el tiempo.
Cada una de nuestras seis conexiones que ya hemos creado, de hecho, no se cerrará. Es decir, seguirán funcionando de la misma forma que antes. Para ello, se utiliza una técnica como Keep-Alive. Es decir, creamos una conexión confiable a un servidor específico y seguimos trabajando.
A nivel HTTP, esto está controlado por el encabezado. En este caso, es conexión. Y a nivel TCP, ya usaremos el propio sistema operativo, él decidirá por nosotros qué hacer.
También hay otros problemas con HTTP / 2. En HTTP / 2, podemos priorizar paquetes y enviar más datos necesarios más rápido. En este caso, cuando intentamos enviar una gran cantidad de datos a la vez, el búfer del servidor puede desbordarse. Entonces, los paquetes de mayor prioridad simplemente se ralentizarán y se colocarán al final de la cola.
Se observa pérdida de paquetes. Ralentizan nuestra carga, y este bloqueo se llama bloqueo de cabecera.
Cómo resuelve TCP los problemas de pérdida de paquetes
Ahora hablaremos de TCP, es decir, nuestra cuarta capa. En los próximos diez minutos, cubriré cómo funciona TCP.
Cuando estamos de visita, le pedimos a alguien que nos pase la sal. Cuando una persona nos da sal, confirmamos que la sal nos ha llegado. En este caso, también tomamos un segmento, lo transmitimos y esperamos la confirmación. Transmitimos de nuevo. Y si hay una pérdida, reenviamos este segmento y, como resultado, se nos entrega. Esta técnica de enviar un segmento se llama Detener y esperar.
Pero nuestras redes se han acelerado enormemente durante los últimos 30 años. Quizás algunos de ustedes recuerden el acceso telefónico, Internet por megabytes. A estas alturas, es posible que ya pueda conectarse a Internet gigabit en casa.
Además, en este caso, podemos empezar a enviar varios paquetes a la vez. En nuestro ejemplo, hay tres. Enviamos la ventana en forma de tres paquetes y esperamos a que todos sean confirmados.
En caso de pérdida de paquetes, podemos comenzar a reenviar todos los paquetes, comenzando desde nuestra primera pérdida. Esta técnica se llama Go-Back N. De lo contrario, podemos comenzar a rastrear todos los paquetes y reenviar solo aquellos que se perdieron. Esta técnica se llama repetición selectiva. Es más caro en el lado del servidor. Cuando estábamos preparando las diapositivas, tomó mucho tiempo descubrir cómo presentarlas. Yo mismo me confundí y, por lo tanto, se me ocurrió tal analogía.
Hay conductos que todos conocemos por los que fluye el agua. Las tuberías tienen diferentes diámetros, en algún lugar pueden ser más delgadas y, en este caso, el punto más estrecho será solo con nuestro rendimiento máximo. No podremos verter más agua de la que permite este cuello de botella.
Intentaremos disparar bolas de izquierda a derecha. En el lado derecho, se nos confirmará que las bolas han volado. Estamos empezando a enviar un torrente de bolas. Echemos un vistazo a su corte. Ahora las bolas vuelan en una dirección, se confirman y el número de nuestras bolas crece exponencialmente. En algún momento, el volumen de las bolas se vuelve tan grande que se ralentizan y comienzan las pérdidas. Después de la pérdida, disminuimos un poco la velocidad, reducimos nuestra ventana a la mitad. Luego tratamos de entender lo que nos pasó. La primera etapa se llama TCP Slow Start.
Cuando hayamos cerrado la ventana dos veces, podemos restablecer la conexión y pedir a los chicos que nos envíen nuestras bolas nuevamente. Nos gritan que tenemos que enviar las bolas, les respondemos, aquí están las bolas. Esta fase se denomina recuperación rápida y retransmisión rápida.
Cuando nos dimos cuenta de que todo está bien para nosotros, comenzamos a aumentar gradualmente la cantidad de bolas enviadas, comenzando desde esa ventana colapsada. Esta fase se llama Evitación de la congestión. Es decir, intentamos evitar perder nuestros paquetes.
La fase en la que nuestra ventana se colapsa dos veces se llama disminución multiplicativa. Y la fase lenta de aumentar el número de bolas se llama aumento aditivo.
Cuando nuestra prevención de congestión pierde paquetes nuevamente, podemos dar el siguiente paso. Pero por el momento estamos más interesados en la imagen misma de este gráfico. Vemos una sierra de este tipo, y esta sierra nos será útil varias veces. Recuerda lo que parece.
Volveremos a los problemas de los protocolos TCP convencionales. Por analogía con una pipa, vertimos bolsas. Dado que hay otros usuarios en Internet además de nosotros, también comienzan a verter paquetes en la tubería. En algún momento, los búferes de nuestros enrutadores pueden desbordarse y crear problemas para que enviemos paquetes.
También existe un problema con la pérdida de paquetes en las redes inalámbricas. Lo más probable es que su computadora portátil no tenga un puerto Ethernet y esté viendo una conversación a través de Wi-Fi. La pérdida de paquetes en redes Wi-Fi y móviles no es causada por el enrutador en sí, sino por interferencias de radio. Tal métrica no nos será de mucha utilidad.
Diferencia de TCP BBR de otros algoritmos
Aquí llegamos a BBR. Significa Bottleneck Bandwidth y Round Trip Time, estas son métricas del ancho de banda cuando no obstruimos completamente nuestro canal y el tiempo de viaje del paquete desde nosotros hasta el servidor y viceversa.
Cuando enviamos datos, el estado ideal en el que los paquetes se encuentran en un estado estable, vuelan y aún no han sido reconocidos se denomina producto de retardo de ancho de banda. Podemos aumentar BDP mediante el uso de búferes de dispositivos de red. Cuando se excede este búfer, comienzan las pérdidas.
Y los algoritmos TCP habituales simplemente funcionan en el lado derecho del gráfico, es decir, donde ocurren las pérdidas: vertimos tantos paquetes que las pérdidas son inevitables. Los paquetes se ralentizan y comenzamos a colapsar la ventana.
BBR, a su vez, funciona con un principio diferente, cercano a nuestra tubería. Simplemente vertimos tantas bolsas como podamos. En la fase de inicio, es decir, al principio, vertimos las bolsas hasta que comienza la congestión.
Y a veces es posible la pérdida de paquetes. Pero BBR está tratando de evitar este momento. Cuando hemos llenado nuestra pipa, comenzamos a retroceder. Esta fase se llama drenaje.
Regresamos a nuestra conexión estable, donde estará completamente llena, pero al mismo tiempo no usaremos búferes adicionales, reservorios adicionales. Desde esta posición, BBR continúa operando.
De vez en cuando veremos qué está sucediendo con nuestra red. Realizamos un seguimiento de casi todos los paquetes que nos devuelven. Cuando los paquetes nos han regresado, empezamos a intentar acelerar un poco la cantidad de paquetes, acelerar los paquetes mismos y enviarlos a la red.
Y si no tenemos ningún problema, podemos mantenernos en este valor. Es decir, seguir trabajando al ritmo que nos resulte cómodo. Sin embargo, si hubo pérdidas, podemos retroceder.
Cuando recibimos la confirmación, vimos que la velocidad ha mejorado, podemos esperar un poco, mire el intervalo de diez segundos. Y si durante este intervalo vemos que la velocidad de envío de paquetes aumenta y los paquetes se confirman más rápido, entonces podemos entrar en la fase de sonda RTT y comprobar si todo ha mejorado.
Tales fases se alternan, es decir, revisaremos constantemente lo que tenemos con la red.
El algoritmo BBR ya no se basa en la pérdida de paquetes, sino en el ancho del canal y el tiempo de viaje del paquete.
De hecho, es inmune a la pérdida de paquetes. Prácticamente no reacciona ante ellos, y por eso tenemos algunos problemas. Google prometió que estos problemas se solucionarán en BBR v2.
Hemos examinado nuestras fases, y ante nosotros está de nuevo el peine, que ya he mostrado. Los protocolos TCP regulares están resaltados en rojo. Así que recoge, recoge, ralentiza y vuelve a perder paquetes. Y BBR marca el ritmo que necesita, con el que trabajará todo el tiempo, y comprueba constantemente nuestra red si ha mejorado un poco. Y puede que se esté acelerando.
Nuestras métricas se actualizan constantemente, rastreamos cada confirmación por parte del cliente y verificamos si nuestra red se ha acelerado o no.
¿Cómo se controla esta tasa de envío de paquetes? Controlamos el ritmo de envío mediante la técnica de marcapasos. Está implementado en el programador que mencioné anteriormente. Este es el programador FQ. También está implementado en el propio kernel, pero hablaré de esto más adelante.
Intentamos, como en una tubería, verter más datos y, al mismo tiempo, no ralentizarnos, no perder nuestros paquetes. Pero BBR no es tan simple. Lo más probable es que viva en contenedores o utilice varios servidores para bases de datos, tal vez para imágenes.
Y todos estos servidores interactúan entre sí. Hay TCP normal habilitado, no BBR. Y cuando tenga la sierra, que ya hemos visto, cuando la ventana comience a colapsar, entonces quizás BBR comenzará a tantear que la ventana se está colapsando y aumentará la velocidad de envío de paquetes. Por lo tanto, eliminará el TCP ordinario de nuestra red.
Si la red es muy mala, es posible que surjan otros problemas. El TCP normal no funcionará en absoluto y, dado que BBR es prácticamente insensible a la pérdida de paquetes, seguirá funcionando a cierta velocidad.
Podemos solucionar este problema con los centros de datos con la opción TCP_CONGESTION. Está expuesto para cada enchufe, para cada conexión. Ahora bien, hasta donde yo sé, esta opción no está implementada en casi ningún servidor web. Y nuestro equilibrador L7 lo admite. Pero volvamos a nuestro ritmo. Si está trabajando con kernels más antiguos, entonces hubo un error en la implementación del ritmo en kernels antes de la versión 4.20. En este caso, vale la pena utilizar el programador FQ.
Ahora que sabe cómo funciona TCP, puede dirigirse al administrador del sistema y decirle por qué debería habilitar BBR.
Volvamos a nuestro diez por ciento. ¿De donde pueden venir? Las redes de operadores son ahora muy grandes. Todo se reduce al dinero. Puede crear canales para 100, 200 terabits y omitir una gran cantidad de videos 4K, por ejemplo. Pero su cliente seguirá estando en el punto final.
Y lo más probable es que esta última milla para el cliente sea la fuente de problemas. Todos nuestros Wi-Fi y LTE perderán paquetes. Veremos ralentizaciones cuando usemos TCP normal. BBR resuelve este problema. Puede encenderlo con solo los dos comandos que indiqué. Gracias a todos.