如何最小化在TCP服务器应用程序中使用的线程数?

时间:2020-03-05 18:44:21  来源:igfitidea点击:

我正在寻找人们在实现服务于客户端TCP(或者UDP)请求的服务器应用程序时使用的任何策略:设计模式,实现技术,最佳实践等。

出于这个问题的目的,让我们假设请求的寿命相对较长(几分钟),并且流量是时间敏感的,因此响应消息的延迟是不可接受的。另外,我们既要处理来自客户端的请求,又要与其他服务器建立连接。

我的平台是.NET,但是由于基础技术与平台无关,因此我很感兴趣,希望能找到任何语言的答案。

解决方案

回答

现代的方法是利用操作系统为我们多路复用许多网络套接字,从而使应用程序解放出来,使其仅处理具有流量的活动连接。

每当我们打开套接字时,它都会与选择器关联。我们使用单个线程轮询该选择器。每当数据到达时,选择器都会指示套接字处于活动状态,我们将该操作移交给子线程并继续轮询。

这样,每个并发操作只需要一个线程。打开但空闲的套接字不会占用线程。

  • 使用select()和poll()方法
  • 使用Java NIO构建高度可扩展的服务器

回答

G'day,

我将从查看我们要用于线程框架的隐喻开始。

也许是"领导者跟随者",其中一个线程正在侦听传入的请求,并且当一个新请求进入时它起作用,并且池中的下一个线程开始侦听传入的请求。

或者线程池,其中同一线程始终侦听传入的请求,然后将请求传递到线程池中的下一个可用线程。

我们可能想访问Ace Components的Reactor部分以获取一些想法。

HTH。

干杯,

回答

更复杂的方法是使用IO完成端口。 (视窗)
使用IO完成端口,我们可以留给操作系统来管理轮询,这使它有可能在NIC驱动程序支持下使用很高水平的优化。
基本上,我们有一个由OS管理的网络操作队列,并提供一个在操作完成时调用的回调函数。有点像(硬盘驱动器)DMA,但用于网络。

Len Holgate几年前在Codeproject上撰写了有关IO完成端口的精彩系列文章:
http://www.codeproject.com/KB/IP/jbsocketserver2.aspx


我在.net的IO完成端口上找到了一篇文章(虽然还没有读过)
http://www.codeproject.com/KB/cs/managediocp.aspx

我还要说的是,与尝试编写可扩展的替代方案相比,使用完成端口更容易。问题在于它们仅在NT(2000,XP,Vista)上可用

回答

如果直接使用C ++和Win32,则建议我们阅读有关重叠的I / O和I / O完成端口的信息。我有一个免费的C ++,IOCP,客户端/服务器框架以及完整的源代码,有关更多详细信息,请参见此处。

由于我们使用的是.Net,因此应该考虑使用异步套接字方法,这样我们就不必为每个连接都拥有一个线程。我的博客文章中有几个链接可能是有用的起点:http://www.lenholgate.com/blog/2005/07/disappointing-net-sockets-article-in-msdn-magazine-this-month .html(一些最佳链接在原始文章的注释中!)