是否有正当理由不使用TcpListener
用于实现高性能/高吞吐量TCP
服务器而不是SocketAsyncEventArgs
?
我已经使用以下方法实现了这个高性能/高吞吐量 TCP 服务器SocketAsyncEventArgs
使用大的预分配的处理这些固定缓冲区经历了各种令人头痛的事情byte
数组和池SocketAsyncEventArgs
对于接受和接收,使用一些低级的东西和闪亮的智能代码与一些 TPL 数据流和一些 Rx 组合在一起,它工作得很好;这方面的工作几乎是教科书——实际上,我从其他人的代码中学到了 80% 以上的内容。
但也存在一些问题和担忧:
-
复杂:我无法将对这台服务器的任何修改委托给另一台服务器
团队成员。这将我限制在此类任务上,我可以
对其他项目的其他部分没有给予足够的重视。
-
内存使用情况(固定的
byte
数组):使用SocketAsyncEventArgs
需要池
被预先分配。所以对于处理100000个并发连接
(更糟糕的情况,即使在不同的端口上)一大堆 RAM 毫无用处地悬停在那里;
预先分配(即使这些条件只是在某些时候满足,
服务器每天应该能够处理 1 或 2 个这样的峰值)。
-
TcpListener
实际上效果很好: 其实我已经放了TcpListener
进入测试(使用一些技巧,例如
使用AcceptTcpClient
在专用线程上,以及not the async
版本,然后将接受的连接发送到ConcurrentQueue
并且不创造Task
就位等)
使用最新版本的.NET,它运行得很好,几乎一样好
作为SocketAsyncEventArgs
,无数据丢失且内存占用少
这有助于避免在服务器上浪费太多 RAM,并且不需要预先分配。
那么为什么我没有看到TcpListener
在任何地方使用,每个人(包括我自己)都在使用SocketAsyncEventArgs
?我错过了什么吗?
我没有看到任何证据表明这个问题是关于TcpListener
根本不。看来您只关心处理已被接受的连接的代码。这种连接独立于侦听器。
SocketAsyncEventArgs
是CPU负载优化。我相信您可以使用它实现更高的每秒操作率。与普通 APM/TAP 异步 IO 的差异有多大?当然小于一个数量级。大概在 1.2 倍到 3 倍之间。上次我对环回 TCP 事务速率进行基准测试时,我发现内核占用了大约一半的 CPU 使用率。这意味着通过无限优化,您的应用最多可以提高 2 倍的速度。
请记住SocketAsyncEventArgs
大约在 2000 年左右被添加到 BCL,当时 CPU 的能力还远远不够。
Use SocketAsyncEventArgs
仅当您有证据表明您需要它时。它会导致你的工作效率大大降低。更容易出现错误。
这是您的套接字处理循环应如下所示的模板:
while (ConnectionEstablished()) {
var someData = await ReadFromSocketAsync(socket);
await ProcessDataAsync(someData);
}
非常简单的代码。没有回调,感谢await
.
如果您担心托管堆碎片:分配一个new byte[1024 * 1024]
启动时。当您想从套接字读取数据时,将单个字节读入该缓冲区的某个空闲部分。当单字节读取完成时,您会询问实际有多少字节(Socket.Available
)并同步拉动其余部分。这样,您只需固定一个相当小的缓冲区,并且仍然可以使用异步 IO 来等待数据到达。
该技术不需要轮询。自从Socket.Available
只可以increase如果不从套接字读取,我们就不会冒意外执行太小的读取的风险。
或者,您可以通过分配几个非常大的缓冲区并分发块来对抗托管堆碎片。
或者,如果您不认为这是一个问题,则无需执行任何操作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)