Im Folgenden finden Sie eine Zusammenfassung der Probleme bei der Implementierung einer Hochleistungs-Socket-Komponente: Wenn Sie nur mit Tausenden gleichzeitiger Anwendungen arbeiten müssen, können Sie sich auf das Codewriting konzentrieren, aber Sie müssen Zehntausende oder Zehntausende gleichzeitiger Anwendungen bewältigen. Die Zusammenfassung der folgenden Fragen wird als große Hilfe für das Verfassen dieser Bewerbung angesehen.
SocketAsyncEventArgs
Dieses Objekt wird nach .NET 2.0 sp1 bereitgestellt und hauptsächlich zur Implementierung von Hochleistungs-Socket-Daten-Send- und Empfangsverarbeitung verwendet (für eine ausführlichere Einführung finden Sie MSDN). Dieses Objekt bietet drei Möglichkeiten, die Puffer für das Senden und Empfangen verwandter Sends einzustellen: SetBuffer(Int32, Int32), SetBuffer(Byte(), Int32, Int32, BufferList; die ersten beiden können nicht mit letzteren koexistieren ( MSDN erklärt warum). Wenn Sie einen Buffer setzen, sei es SetBuffer(Byte(), Int32, Int32) oder BufferList, versuchen Sie, ihn während der gesamten Programmlaufzeit nur einmal pro SocketAsyncEventArgs-Instanz einzustellen, da diese Einstellung sehr ressourcenintensiv sein kann. Es wird empfohlen, den Datenpuffer während der Erstellung von SocketAsyncEventArgs über SetBuffer(Byte(), Int32, Int32) zu setzen und dann SetBuffer(Int32, Int32) zu verwenden. Wenn Sie eine BufferList festlegen möchten, ist es am besten, <byte>die von IList referenzierte Byte[]-Quelle nicht zu ändern<ArraySegment>. Wenn sie geändert wird, führt dies dazu, dass SocketAsyncEventArgs den Puffer neu binden und die Effizienz beeinträchtigt.
SocketAsyncEventArgs-Pool
Wie oben erwähnt, versuchen Sie, den von SocketAsyncEventArgs referenzierten Puffer so wenig wie möglich zu verändern, um dieses Ziel zu erreichen. Daher ist es notwendig, einen SocketAsyncEventArgs-Anwendungspool zu erstellen und das SocketAsyncEventArgs-Objekt so weit wie möglich zu Beginn des Programms zu initialisieren. Neben der Reduzierung der Erstellung von SocketAsyncEventArgs kann das Erstellen von Pools auch erheblich Speicher sparen. Der Hauptgrund ist, dass man natürlich nicht wissen kann, wie groß jede Nachricht ist; man kann der Nachricht vor dem Design ein Maximum geben und dann den Puffer entsprechend SocketAsyncEventArgs einstellen. Dies ist jedoch eine große Speicherverschwendung, da nicht alle Nachrichten eine maximale Länge haben. Zuweisen Sie SocketAsyncEventArgs eine angemessene Puffergröße, stellen Sie Aufrufe über Pools bereit und schreiben Sie flexibel Nachrichten an einen oder mehrere SocketAsyncEventArgs oder speichern Sie mehrere Nachrichten in einem SocketAsyncEventArgs zur Verarbeitung.
Warteschlange
Ich sehe, dass viele Praktiken darin bestehen, Threads direkt zu öffnen oder nach Erhalt der Daten in den Threadpool zu werfen, was sehr schlecht ist, weil es die Arbeit der Threads, einschließlich des Wartens von Threads, nicht besser kontrolliert. Mit benutzerdefinierten Threads + Warteschlangen kannst du steuern, wie viele Threads für welche Arbeit verantwortlich sind, und die Warteschlange existiert nur in der Warteschlange; Es wird keine große Anzahl von Threads oder eine große Anzahl von Wartezeilen geben, was dazu führen kann, dass das Betriebssystem durch Thread-Planung Ressourcen verliert.
Verzögerte Datenkonsolidierung
Die verzögerte Übertragung von Datenzusammenführungen ist ein Mittel zur Lösung des Problems übermäßiger Netzwerk-IO-Operationen, das in vielen Szenarien nicht verwendet wird, aber auf Spielservern häufig vorkommt. Jemand hat mir vorher eine Frage gestellt: Wenn 400 Nutzer in der Szene sind, wird jede Umgebungsänderung den anderen Nutzern mitteilen. Wenn die kombinierten Daten nicht verwendet werden, führt dies zu einer sehr beängstigenden Netzwerk-IO-Operation, die für das IO-Operationsnummernsystem schwer zu tragen ist. Daher ist es notwendig, die Daten innerhalb eines geeigneten Verzögerungsintervalls für die aktuelle Anwendung zusammenzuführen und zu senden. |