如何保留100万个并发TCP连接?
我要devise一个服务器,需要服务数百万的客户端,通过TCP 同时连接到服务器。
服务器和客户端之间的数据stream量很稀疏,所以带宽问题可以忽略不计。
一个重要的要求是,只要服务器需要向任何客户端发送数据,它应该使用现有的TCP连接,而不是打开一个新的连接到客户端(因为客户端可能在防火墙后面)。
有谁知道如何做到这一点,需要什么硬件/软件(以最低的成本)?
你在考虑什么操作系统?
如果使用Windows操作系统并使用比Vista更早的东西,那么在单台机器上连接数千个连接就不会有问题。 我用一个低规格的Windows Server 2003机器运行testing(这里是: http : //www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html ),并且很容易地实现了超过70,000个活动的TCP连接。 一些影响连接数量的资源限制已经在Vista上大大提高了(见这里: http : //www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html )你可以用一小群机器来实现你的目标。 我不知道在路由连接前你需要什么。
Windows提供了一个名为I / O完成端口的工具(请参阅: http : //msdn.microsoft.com/en-us/magazine/cc302334.aspx ),它允许您使用极less的线程服务数千个并发连接(我是通过5000个连接运行testing,通过2个线程来连接服务器来处理I / O …)。 因此基本架构是非常可扩展的。
如果你想运行一些testing,那么我的博客上有一些免费的工具,它们允许你使用成千上万个连接( 1 )和( 2 )以及一些你可以用来让你开始的免费代码( 3 )
您的问题的第二部分,从您的意见,是更棘手的。 如果客户端的IP地址不断变化,而且您和他们之间没有任何东西提供NAT来给您一个一致的IP地址,那么他们的连接无疑将被终止并需要重新build立。 如果客户端检测到这个连接在其IP地址发生变化时就被拆除,那么他们可以重新连接到服务器,如果他们不能,那么我build议客户端需要频繁地轮询服务器,以便他们能够检测到连接丢失,重新连接。 由于无法预测新的IP地址,因此服务器无法在此处执行任何操作,因此发现旧连接在尝试发送数据时失败。
记住,一旦你的系统扩展到这个级别,你的问题才刚刚开始。
这个问题与所谓的C10K问题有关。 C10K页面列出了大量优秀的资源,用于解决您在尝试允许数千个客户端连接到同一服务器时遇到的问题。
我已经遇到了APE项目 。 这似乎是一个梦想成真。 他们可以在单个节点上支持高达10万个并发客户端。 将它们分散在10或20个节点上,并且可以服务数百万个节点。 适用于RESTful应用程序。 可能想更深入地查看任何共享名称空间。 一个缺点是,这是一个独立的服务器,如在networking服务器的补充。 这个服务器当然是开源的,所以任何成本都是硬件/ ISP相关的。
你不能使用UDP。 如果客户端发送了一个请求,并且你没有立即回复,路由器将在30秒或更短的时间内忘记反向路由,所以你的服务器永远无法回复客户端。
TCP是唯一的select,它也会让你头疼。 大多数路由器会在几分钟后忘记路由和/或断开连接,所以你的客户/服务器代码将不得不经常发送“保持活着”。
我build议设置一个“嗅探器”,看看电话公司是如何与您的智能手机保持联系的“推”技术。 复制他们正在做的事情,因为那些东西有用 !
正如Greg所说的,你所描述的问题是C10K(或者说你的情况下是“C1M”),我最近在linux上做了一个简单的TCP回显服务器,它的会话数量可以很好地扩展(只能testing到200.000)使用epoll队列。 在BSD上,你有一些类似的叫做kqueue。 你可以检查出你的代码 。 希望这有助于和祝你好运!
编辑:正如在下面的评论中指出的,我原来断言有一个基于端口数64K的限制是不正确的,但是有一个32K的套接字句柄限制,所以我build议的devise是有效的。
使用典型的TCP / IP服务器devise,您可以拥有的同时打开的连接数量受到限制。 服务器有一个监听端口,当一个客户端连接到服务器时,服务器进行一个接受调用,并在随机端口上为其余的连接创build一个新的套接字。
要处理超过64K的同时连接,我认为你需要使用UDP。 您只需要一个端口供服务器侦听,并且您需要使用数据包数据中的32位客户端ID来pipe理连接,而不是为每个客户端分配一个端口。 32位客户端ID可以是客户端的IP地址,客户端可以在已知的UDP端口上侦听从服务器返回的消息。 该端口将是唯一需要在防火墙上打开的端口。
使用这种方法,唯一的限制就是您可以多快地处理和响应UDP消息。 有了数以百万计的客户端,即使是稀疏的stream量也会给你带来巨大的高峰,如果你没有足够快地读取数据包,你的input队列就会被填满,你将开始丢弃数据包。 格雷格指出,C10K页面将为您提供相应的策略。