A seguir está um resumo dos problemas na implementação de um componente socket de alto desempenho: se você só precisa lidar com milhares de aplicações concorrentes, pode prestar atenção à escrita do código, mas precisa enfrentar dezenas de milhares ou dezenas de milhares de aplicações simultâneas. Acredita-se que o resumo das perguntas a seguir seja de grande ajuda na redação desta candidatura.
SocketAsyncEventArgs
Este objeto é fornecido após o .NET 2.0 sp1 e é usado principalmente para implementar processamento de envio e recepção de dados em sockets de alto desempenho (para uma introdução mais detalhada, você pode acessar MSDN). Este objeto fornece três formas de definir os buffers para envios relacionados ao envio e recebimento: SetBuffer(Int32, Int32), SetBuffer(Byte(), Int32, Int32, BufferList, sendo que os dois primeiros não podem coexistir com os últimos ( MSDN explica o porquê). Quando você definir um Buffer, seja SetBuffer(Byte(), Int32, Int32) ou BufferList, tente configurá-lo apenas uma vez por instância do SocketAsyncEventArgs durante a vida útil do programa, pois essa configuração pode ser muito intensiva em recursos. Recomenda-se configurar o data buffer através do SetBuffer(Byte(), Int32, Int32) durante a construção do SocketAsyncEventArgs, e então usar o SetBuffer(Int32, Int32) para lidar com isso. Quando você quer definir um BufferList, é melhor não alterar <byte>a fonte do byte[] referenciada pelo IList<ArraySegment>. Se for alterado, fará com que o SocketAsyncEventArgs reassocie o buffer e afetará a eficiência.
Pool SocketAsyncEventArgs
Como mencionado acima, tente não alterar o buffer referenciado pelo SocketAsyncEventArgs o máximo possível para alcançar esse objetivo. Portanto, é necessário construir um pool de aplicações SocketAsyncEventArgs e inicializar o objeto SocketAsyncEventArgs o máximo possível no início do programa. Além de reduzir a criação de SocketAsyncEventArgs, construir pools também pode economizar muito memória. O principal motivo é que você não pode saber o tamanho de cada mensagem, claro, pode dar um limite máximo para a mensagem antes de projetar e então definir o buffer correspondente ao SocketAsyncEventArgs. No entanto, isso é um grande desperdício de memória, pois nem todas as mensagens têm um comprimento máximo. Aloque uma quantidade apropriada de tamanho de buffer para SocketAsyncEventArgs, forneça chamadas por meio de pools e escreva mensagens de forma flexível para um ou mais SocketAsyncEventArgs, ou armazene múltiplas mensagens em um único SocketAsyncEventArgs para processamento.
Fila
Vejo que muitas práticas são abrir threads diretamente ou jogá-las para o pool de threads após receber dados, o que é muito ruim porque não controla melhor o trabalho das threads, incluindo a espera das threads. Com threads + queues personalizadas, você pode controlar quantas threads são responsáveis por qual trabalho, e o trabalho na fila só existirá na fila; Não haverá um grande número de threads ou muitas linhas esperando, o que fará com que o sistema operacional perca recursos devido ao escalonamento de threads.
Consolidação tardia de dados
A transmissão atrasada de dados por fusão é um meio de resolver o problema das operações excessivas de IO na rede, que não é usado em muitos cenários, mas é comum em servidores de jogos. Alguém me fez uma pergunta antes: se houver 400 usuários na cena, a mudança de ambiente de cada usuário vai avisar os outros usuários. Se os dados combinados não forem usados, isso gerará uma operação de IO de rede muito temida, o que é difícil para o sistema de numeração de operações de IO carregar. Portanto, é necessário mesclar e enviar dados dentro de um intervalo de atraso apropriado para a aplicação atual. |