Ir al contenido principal
«La aplicación ha funcionado bien durante años, pero la semana pasada se actualizó la red y pasamos de 100 Mbps a gigabit. Ahora, la última mitad de los datos de algunos mensajes es basura. Los responsables de la red juran que no es culpa de la red, pero es lo único que ha cambiado».

 

La buena noticia es que la costosa actualización de la red no ha afectado al funcionamiento de la aplicación.

 

La mala noticia es que la aplicación está dañada y siempre lo ha estado. Lo que *muchas* personas que escriben aplicaciones TCP no se dan cuenta es que TCP es un flujo de bytes, no de mensajes. El hecho de que una aplicación envíe dos mensajes de 1000 bytes no significa que la pila TCP de envío enviará dos segmentos TCP de 1000 bytes. Los mensajes de la aplicación se pueden segmentar en partes más pequeñas en función del tamaño máximo de segmento anunciado por el receptor o de alguna limitación de configuración del remitente. Las retransmisiones también pueden combinar y fragmentar los mensajes de la aplicación. Incluso si la pila TCP de envío envía realmente dos segmentos TCP de 1000 bytes, no hay garantía de que la pila TCP de recepción proporcione a la aplicación receptora dos mensajes de 1000 bytes. Por ejemplo, si el búfer de la aplicación es de solo 500 bytes, eso es todo lo que devolverá la pila TCP. Por otro lado, si el búfer es de 1500 bytes y han llegado ambos segmentos de 1000 bytes, la pila TCP devolverá 1500 bytes en la primera llamada y 500 en la segunda. Depende de la aplicación tomar el flujo de bytes y analizarlo correctamente para convertirlo en mensajes.

 

¿Qué tiene esto que ver con la actualización de la red? Bueno, el servidor OpenVOS y el cliente Linux estaban en subredes diferentes, por lo que el sistema OpenVOS anunciaba un tamaño máximo de segmento de 536 bytes. Los mensajes de la aplicación enviados por el cliente eran de 1000 bytes, por lo que los mensajes se segmentaban en dos partes. Antes de la actualización, parece que ambos segmentos llegaban al servidor OpenVOS antes de que la aplicación publicara su recepción, por lo que los 1000 bytes se leían con una sola llamada a la función de recepción. Después de la actualización, la sincronización de los segmentos cambió, de modo que, en algunas ocasiones, solo el primer segmento estaba disponible cuando la aplicación publicaba su recepción. Los últimos 464 (1000 - 536) bytes del búfer de la aplicación no fueron rellenados por la pila TCP y contenían cualquier basura que hubiera antes de que se publicara la recepción.

 

En este caso, había una solución rápida y sencilla: aumentar el valor MSS anunciado por OpenVOS a 1460 (véase Una forma sencilla de mejorar el rendimiento de TCP entre subredes). Sin embargo, eso solo es un parche temporal. La solución real será reescribir el código para analizar correctamente el flujo de bytes TCP y convertirlo en mensajes de aplicación, en lugar de simplemente asumir que una llamada de recepción devolverá un mensaje.