高性能C#服务器套接字的提示/技巧

McK*_*eG1 32 .net c# sockets performance

我有一个.NET 2.0服务器似乎遇到了扩展问题,可能是由于套接字处理代码设计不佳,我正在寻找有关如何重新设计它以提高性能的指导.

使用场景: 50到150个客户端,每个客户端的高速率(高达100秒/秒)的小消息(每个10字节).客户端连接是长期的 - 通常是几个小时.(服务器是交易系统的一部分.客户端消息被聚合成组以通过较少数量的"出站"套接字连接发送到交换机,并且当交换机处理每个组时,确认消息被发送回客户端. .)OS是Windows Server 2003,硬件是2 x 4核X5355.

目前的客户端套接字设计:一个TcpListener产生一个线程作为客户端连接到读取每个客户端套接字.线程阻塞Socket.Receive,解析传入的消息并将它们插入到一组队列中以供核心服务器逻辑处理.使用Socket.BeginSend来自与交换机侧通信的线程的异步调用,通过客户端套接字发回确认消息.

观察到的问题:随着客户端数量的增加(现在为60-70),我们开始在向客户端发送数据和从客户端接收数据时看到间歇性延迟高达100毫秒.(我们记录每条确认消息的时间戳,我们可以看到时间戳序列中偶尔会出现长时间间隔,这些间隙来自同一组中通常在几毫秒内完成的一串ack.)

整体系统CPU使用率很低(<10%),有足够的空闲RAM,核心逻辑和出站(面向交换)端表现良好,因此问题似乎与面向客户端的套接字代码隔离开来.服务器和客户端(千兆局域网)之间有足够的网络带宽,我们排除了网络或硬件层问题.

任何有用资源的建议或指示都将不胜感激.如果有人有任何诊断或调试技巧可以确定出错的地方,那么这些技巧也会很棒.

注意:我有MSDN杂志的文章Winsock:使用.NET中的高性能套接字更接近线路,我已经浏览了Kodart"XF.Server"组件 - 它看起来很粗略.

小智 22

.NET 3.5环境中的套接字I/O性能得到了改进.您可以使用ReceiveAsync/SendAsync而不是BeginReceive/BeginSend来获得更好的性能.把它拿出来:

http://msdn.microsoft.com/en-us/library/bb968780.aspx


gre*_*awk 18

其中很多都与系统上运行的许多线程有关,内核为每个线程提供了时间片.设计简单,但不能很好地扩展.

你可能应该看一下使用Socket.BeginReceive,它将在.net线程池上执行(你可以用某种方式指定它使用的线程数),然后从异步回调中推送到一个队列(可以在任何一个中运行) .NET线程).这应该会给你更高的性能.


Mar*_*ell 8

每个客户端的一个线程看起来非常过分,特别是考虑到这里的总体CPU使用率较低.通常,您需要一个小的线程池来为所有客户端提供服务,使用BeginReceive等待工作异步 - 然后简单地将处理发送给其中一个工作者(可能只需将工作添加到同步队列中,所有工作人员都在等待).


Joh*_*ing 6

我不是一个C#家伙,但对于高性能套接字服务器,最具可扩展性的解决方案是使用I/O完成端口,其中有许多活动线程适合于进程运行的CPU,而不是使用每个连接一个线程的模型.

在您的情况下,使用8核机器,您将需要16个总线程,其中8个并发运行.(其他8个基本保留.)

  • CLR已经将I/O完成端口用于套接字.因此,默认情况下,您可以在.NET上获得该优势. (6认同)