Di seguito è riportato un riassunto dei problemi nell'implementare un componente socket ad alte prestazioni: se devi gestire solo migliaia di applicazioni concorrenti, puoi concentrarti sulla scrittura del codice, ma devi affrontare decine di migliaia o decine di migliaia di applicazioni concorrenti. Il riassunto delle seguenti domande è ritenuto di grande aiuto per la stesura di questa domanda.
SocketAsyncEventArgs
Questo oggetto è fornito dopo .NET 2.0 sp1 ed è principalmente utilizzato per implementare l'elaborazione ad alta performance di invio e ricezione dati su socket (per un'introduzione più dettagliata, puoi andare su MSDN). Questo oggetto fornisce tre modi per impostare i buffer per inviare e ricevere invi correlati: SetBuffer(Int32, Int32), SetBuffer(Byte(), Int32, Int32, BufferList; i primi due non possono coesistere con questi ultimi ( MSDN spiega il perché). Quando imposti un Buffer, che sia SetBuffer(Byte(), Int32, Int32) o BufferList, cerca di impostarlo solo una volta per ogni istanza di SocketAsyncEventArgs durante la vita del programma, poiché questa impostazione può richiedere molte risorse. Si consiglia di impostare il data buffer tramite SetBuffer(Byte(), Int32, Int32) durante la costruzione di SocketAsyncEventArgs, e poi utilizzare SetBuffer(Int32, Int32) per gestirlo. Quando si vuole impostare una BufferList, è meglio non modificare <byte>la sorgente del byte[] a cui IList <ArraySegment>fa referenza. Se viene modificata, SocketAsyncEventArgs riassegnerà il buffer e ne influirà sull'efficienza.
Pool SocketAsyncEventArgs
Come detto sopra, cerca di non modificare il buffer a cui si fa riferimento SocketAsyncEventArgs il più possibile, per raggiungere questo obiettivo. Pertanto, è necessario costruire un pool di applicazioni SocketAsyncEventArgs e inizializzare l'oggetto SocketAsyncEventArgs il più possibile all'inizio del programma. Oltre a ridurre la creazione di SocketAsyncEventArgs, costruire pool può anche risparmiare notevolmente memoria. La ragione principale è che non puoi sapere quanto è grande ogni messaggio, ovviamente puoi dare al messaggio un limite massimo prima di progettarlo, e poi impostare il buffer corrispondente a SocketAsyncEventArgs. Tuttavia, questo è uno spreco di memoria, perché non tutti i messaggi hanno una lunghezza massima. Assegna una dimensione appropriata del buffer ai SocketAsyncEventArgs, fornisci chiamate tramite pool e scrivi messaggi in modo flessibile su uno o più SocketAsyncEventArgs, oppure memorizza più messaggi in un unico SocketAsyncEventArgs per l'elaborazione.
Coda
Vedo che molte pratiche prevedono di aprire i thread direttamente o di inviarli al pool di thread dopo aver ricevuto dati, il che è molto negativo perché non controlla meglio il lavoro dei thread, inclusa l'attesa dei thread. Con thread personalizzati + code, puoi controllare quanti thread sono responsabili di quale lavoro, e il lavoro in coda esisterà solo nella coda; Non ci sarà un gran numero di thread o un gran numero di linee in attesa, il che farà perdere risorse al sistema operativo a causa della pianificazione dei thread.
Ritardo consolidamento dei dati
La trasmissione ritardata dei dati tramite fusione è un metodo per risolvere il problema delle operazioni eccessive di IO di rete, che non è usato in molti scenari, ma è comune nei server di gioco. Qualcuno mi ha già fatto una domanda: se ci sono 400 utenti nella scena, il cambiamento di ambiente di ogni utente lo dirà agli altri. Se i dati combinati non vengono utilizzati, si produrrà un'operazione IO di rete molto temibile, difficile da trasportare per il sistema di numerazione operativa. Pertanto, è necessario unire e inviare i dati entro un intervallo di ritardo appropriato per l'applicazione corrente. |