A continuación se presenta un resumen de los problemas al implementar un componente socket de alto rendimiento; si solo necesitas lidiar con miles de aplicaciones concurrentes, puedes prestar atención a la escritura del código, pero tendrás que enfrentarte a decenas de miles o decenas de miles de aplicaciones concurrentes. Se considera que el resumen de las siguientes preguntas será de gran ayuda para la redacción de esta solicitud.
SocketAsyncEventArgs
Este objeto se proporciona después de .NET 2.0 sp1 y se utiliza principalmente para implementar procesamiento de envío y recepción de datos de socket de alto rendimiento (para una introducción más detallada, puedes ir a MSDN). Este objeto proporciona tres formas de configurar los buffers para envíos relacionados de envío y reenvío: SetBuffer(Int32, Int32), SetBuffer(Byte(), Int32, Int32, BufferList; los dos primeros no pueden coexistir con estos últimos ( MSDN explica por qué). Cuando configures un Buffer, ya sea SetBuffer(Byte(), Int32, Int32) o BufferList, intenta configurarlo solo una vez por instancia de SocketAsyncEventArgs durante la vida del programa, ya que esta configuración puede requerir muchos recursos. Se recomienda configurar el búfer de datos a través de SetBuffer(Byte(), Int32, Int32) durante la construcción de SocketAsyncEventArgs, y luego usar SetBuffer(Int32, Int32) para gestionarlo. Cuando quieres establecer una BufferList, es mejor no cambiar <byte>la fuente de byte[] referenciada por <ArraySegment>IList. Si se cambia, hará que SocketAsyncEventArgs vuelva a asignar el buffer y afectará la eficiencia.
Pool SocketAsyncEventArgs
Como se mencionó antes, intenta no cambiar tanto como sea posible el búfer referenciado por SocketAsyncEventArgs para lograr este objetivo. Por lo tanto, es necesario construir un pool de aplicaciones SocketAsyncEventArgs e inicializar el objeto SocketAsyncEventArgs tanto como sea posible al inicio del programa. Además de reducir la creación de SocketAsyncEventArgs, construir pools también puede ahorrar memoria considerablemente. La razón principal es que no puedes saber qué tamaño tiene cada mensaje, por supuesto, puedes darle un límite máximo antes de diseñarlo y luego establecer el búfer correspondiente a SocketAsyncEventArgs. Sin embargo, esto es un gran desperdicio de memoria, porque no todos los mensajes tienen una longitud máxima. Asignar una cantidad adecuada de tamaño de búfer a SocketAsyncEventArgs, proporcionar llamadas a través de pools y escribir mensajes de forma flexible en uno o más SocketAsyncEventArgs, o almacenar múltiples mensajes en un solo SocketAsyncEventArgs para su procesamiento.
Cola
Veo que muchas prácticas consisten en abrir hilos directamente o lanzarlos al pool de hilos tras recibir datos, lo cual es muy malo porque no controla mejor el trabajo de los hilos, incluida la espera de los hilos. Con hilos personalizados + colas, puedes controlar cuántos hilos son responsables de qué trabajo, y el trabajo en cola solo existirá en la cola; No habrá un gran número de hilos ni un gran número de líneas en espera, lo que hará que el sistema operativo pierda recursos debido a la planificación de hilos.
Consolidación tardía de los datos
La transmisión retrasada de datos por fusión es un medio para resolver el problema de las operaciones excesivas de IO de red, que no se utiliza en muchos escenarios, pero es común en servidores de juegos. Alguien me hizo una pregunta antes: si hay 400 usuarios en la escena, el cambio de entorno de cada usuario informará a los demás. Si no se utilizan los datos combinados, se producirá una operación de IO de red muy temible, que es difícil de transportar para el sistema de números de operación de IO. Por lo tanto, es necesario fusionar y enviar datos dentro de un intervalo de retardo adecuado para la aplicación actual. |