Hieronder volgt een samenvatting van de problemen bij het implementeren van een high-performance socketcomponent: als je alleen met duizenden gelijktijdige applicaties hoeft te werken, kun je op het schrijven van de code letten, maar je moet wel tienduizenden of tienduizenden gelijktijdige applicaties aanpakken. De samenvatting van de volgende vragen wordt gezien als van grote hulp bij het schrijven van deze aanvraag.
SocketAsyncEventArgs
Dit object wordt geleverd na .NET 2.0 sp1 en wordt voornamelijk gebruikt voor het implementeren van high-performance socket data verzend- en ontvangsverwerking (voor een meer gedetailleerde introductie kun je naar MSDN gaan). Dit object biedt drie manieren om de buffers in te stellen voor het verzenden en ontvangen van gerelateerde zenden: SetBuffer(Int32, Int32), SetBuffer(Byte(), Int32, Int32, BufferList, waarbij de eerste twee niet naast de laatste kunnen bestaan ( MSDN legt uit waarom). Wanneer je een Buffer instelt, of het nu SetBuffer(Byte(), Int32, Int32) of BufferList is, probeer deze dan slechts één keer per SocketAsyncEventArgs-instantie in te stellen gedurende de looptijd van het programma, omdat deze instelling erg resource-intensief kan zijn. Het wordt aanbevolen om de databuffer tijdens de constructie van SocketAsyncEventArgs in te stellen via SetBuffer(Byte(), Int32, en vervolgens SetBuffer(Int32, Int32) te gebruiken om dit te verwerken. Wanneer je een BufferList wilt instellen, is het het beste om <byte>de byte[]-bron waarnaar IList verwijst niet te veranderen<ArraySegment>. Als deze wordt veranderd, zal SocketAsyncEventArgs de buffer opnieuw binden en de efficiëntie beïnvloeden.
SocketAsyncEventArgs pool
Zoals hierboven vermeld, probeer de buffer waarnaar SocketAsyncEventArgs verwijst zoveel mogelijk te veranderen om dit doel te bereiken. Daarom is het noodzakelijk om een SocketAsyncEventArgs-applicatiepool op te bouwen en het SocketAsyncEventArgs-object zo veel mogelijk aan het begin van het programma te initialiseren. Naast het verminderen van de aanmaak van SocketAsyncEventArgs, kan het bouwen van pools ook aanzienlijk geheugen besparen. De belangrijkste reden is dat je niet kunt weten hoe groot elk bericht is, natuurlijk kun je het bericht een maximale limiet geven voordat je het ontwerpt, en dan de buffer instellen die overeenkomt met SocketAsyncEventArgs. Dit is echter een grote geheugenverspilling, omdat niet alle berichten een maximale lengte hebben. Wees een passende buffergrootte toe aan SocketAsyncEventArgs, bied aanroepen via pools en schrijf flexibel berichten naar één of meer SocketAsyncEventArgs, of sla meerdere berichten op in één SocketAsyncEventArgs voor verwerking.
wachtrij
Ik zie dat veel praktijken zijn om threads direct te openen of naar de threadpool te gooien nadat ze data hebben ontvangen, wat erg slecht is omdat het het werk van threads, inclusief het wachten van threads, niet beter controleert. Met aangepaste threads + wachtrijen kun je bepalen hoeveel threads verantwoordelijk zijn voor welk werk, en het in de wachtrij geplaatste werk bestaat alleen in de wachtrij; Er zal geen groot aantal threads of veel wachtregels zijn, wat ertoe leidt dat het besturingssysteem middelen verliest door threadplanning.
Vertraagde consolidatie van gegevens
Vertraagde gegevensoverdracht bij samenvoeging is een manier om het probleem van overmatige netwerk-IO-operaties op te lossen, wat in veel scenario's niet wordt gebruikt, maar gebruikelijk is op gameservers. Iemand stelde me eerder een vraag: als er 400 gebruikers in de scène zijn, zal elke verandering in de omgeving het aan de andere gebruikers vertellen. Als de gecombineerde data niet wordt gebruikt, veroorzaakt dit een zeer angstige netwerk-IO-operatie, wat moeilijk is voor het IO-operatienummersysteem om te dragen. Daarom is het noodzakelijk om gegevens te mergen en binnen een passend vertragingsinterval voor de huidige applicatie te verzenden. |