Följande är en sammanfattning av problemen med att implementera en högpresterande socketkomponent; om du bara behöver hantera tusentals samtidiga applikationer kan du fokusera på kodskrivningen, men du måste hantera tiotusentals eller tiotusentals samtidiga applikationer. Sammanfattningen av följande frågor anses vara till stor hjälp för skrivandet av denna ansökan.
SocketAsyncEventArgs
Detta objekt tillhandahålls efter .NET 2.0 sp1 och används främst för att implementera högpresterande socket-datasändning och mottagningsbehandling (för en mer detaljerad introduktion kan du gå till MSDN). Detta objekt erbjuder tre sätt att ställa in buffertar för sändning och mottagande av relaterade sändningar: SetBuffer(Int32, Int32), SetBuffer(Byte(), Int32, Int32, BufferList, de två första kan inte samexistera med den senare ( MSDN förklarar varför). När du sätter en buffert, oavsett om det är SetBuffer(Byte(), Int32, Int32) eller BufferList, försök att bara ställa in den en gång per SocketAsyncEventArgs-instans under programmets livstid, eftersom denna inställning kan vara mycket resurskrävande. Det rekommenderas att sätta databufferten via SetBuffer(Byte(), Int32, Int32) under konstruktionen av SocketAsyncEventArgs, och sedan använda SetBuffer(Int32, Int32) för att hantera det. När du vill sätta en BufferList är det bäst att inte ändra <byte>byte[]-källan som IList refererar till<ArraySegment>. Om den ändras kommer det att göra att SocketAsyncEventArgs binder om bufferten och påverkar effektiviteten.
SocketAsyncEventArgs-pool
Som nämnts ovan, försök att inte ändra bufferten som refereras av SocketAsyncEventArgs så mycket som möjligt för att uppnå detta mål. Därför är det nödvändigt att bygga en SocketAsyncEventArgs-applikationspool och initiera SocketAsyncEventArgs-objektet så mycket som möjligt i början av programmet. Förutom att minska skapandet av SocketAsyncEventArgs kan konstruktion av pooler också spara minne avsevärt. Huvudorsaken är att du inte kan veta hur stort varje meddelande är, du kan förstås ge meddelandet en maxgräns innan designen och sedan ställa in bufferten motsvarande SocketAsyncEventArgs. Detta är dock ett stort minnesslöseri, eftersom inte alla meddelanden har en maximal längd. Allokera en lämplig buffertstorlek till SocketAsyncEventArgs, tillhandahålla anrop genom pooler och flexibelt skriva meddelanden till en eller flera SocketAsyncEventArgs, eller lagra flera meddelanden i en SocketAsyncEventArgs för bearbetning.
kö
Jag ser att många metoder är att öppna trådar direkt eller kasta dem i trådpoolen efter att ha mottagit data, vilket är väldigt dåligt eftersom det inte bättre kontrollerar trådarnas arbete, inklusive väntan på trådar. Med anpassade trådar + köer kan du styra hur många trådar som ansvarar för vilket arbete, och det köade arbetet kommer bara att finnas i kön; Det kommer inte att finnas ett stort antal trådar eller många rader som väntar, vilket gör att operativsystemet förlorar resurser på grund av trådschemaläggning.
Fördröjd konsolidering av data
Fördröjd överföring av sammanslagna data är ett sätt att lösa problemet med överdrivna nätverks-IO-operationer, vilket inte används i många scenarier, men är vanligt i spelservrar. Någon ställde mig en fråga tidigare, om det är 400 användare i scenen, kommer varje användares miljöförändring att berätta för de andra. Om den kombinerade datan inte används kommer det att skapa en mycket skrämmande nätverks-IO-operation, vilket är svårt för IO-operationsnummersystemet att hantera. Därför är det nödvändigt att slå ihop och skicka data inom ett lämpligt fördröjningsintervall för den aktuella applikationen. |