多线程TCP网络的性能表现

3

我正在处理一个使用TCP协议的项目,可能需要同时处理数百个或更多连接。

因此,我不确定应该使用什么方法来收集和发送这些数据。

我想知道是否在这里适用于“更多线程=更高性能”的原则。

我怀疑的原因是因为所有数据仍然必须通过网络连接传输,而大多数设备一次只有1个活动连接。另外,我知道重复的上下文切换也会降低性能。

但是,我从其他来源看到了建议使用多线程确实可以将网络性能扩展到一定程度,如果是这样,为什么呢?

目前,我正在使用非Boost版本的ASIO来处理网络。

感谢您提供的任何帮助。


1
使用多个线程(或进程)是否能加快速度完全取决于创建线程的开销是否小于线程需要完成的工作量,以及该线程是否需要定期与其他线程同步。线程有时候可以令人惊叹,但它们并不是万能解决方案,在某些情况下会减慢速度。 - undefined
如果你的程序受限于CPU性能,你需要使用线程,但是如果不是这种情况,你可以通过使用非阻塞库来获得出色的性能。 - undefined
这篇文章有点过时,但在这个主题上仍然值得一读:http://www.kegel.com/c10k.html - undefined
3个回答

2
ASIO是对epoll/IOCP的封装,因此针对高性能的非阻塞I/O进行了优化。在单个线程上,可以实现数十万个同时连接。事实上,旧式的“每个客户端一个线程”的设置由于上下文切换开销,永远无法达到这个水平的性能。
话虽如此,根据所使用的协议,处理网络请求和响应需要一些CPU时间,在高速率的网络中,可能会饱和运行io_service的单个CPU核心。在这种情况下,可以将io_service并行化,以便完成例程可以在多个核心上运行。如果线程数不超过可用的CPU核心/硬件线程数,则不会发生上下文切换。当同一核心需要处理多个线程时以及在用户模式和内核模式之间切换时(即每个系统调用两次)也会发生上下文切换。
基准测试您的服务器,以查看它可以在单个线程上处理多少个客户端。很有可能已足够。将io_service并行化的代价是必须处理并行运行的完成例程,这几乎总是需要额外的同步,这意味着额外的开销。

即使单个核心饱和了,使用多核心会有任何不同吗?毕竟,操作系统仍然只能使用一个线程将数据传输到网络卡上。 - undefined
是的,如果一个核心被饱和了,那么使用多核心会有帮助。当CPU无法及时处理传入的数据包时,初始时数据包会被缓冲,但一旦缓冲区满了,新的数据包将会被丢弃。对于客户端来说,这将表现为“连接重置”和“连接超时”对于新连接和重传以及现有连接的普遍缓慢。但是再次强调,在大多数情况下,单个核心已经足够。计算密集型任务应该委托给辅助线程池,以便完成处理程序快速轻量级,并且io_service线程保持响应性。 - undefined

0

你希望拥有与CPU核心数量相当的线程,包括超线程。不要多于这个数量。

每个线程处理一组套接字。这样,你可以最大限度地提高CPU并行性,但减少开销。

如果你真的需要处理上百个连接且需要低延迟,你应该考虑使用UDP,其中一个单独的套接字可以从许多远程地址接收。但是你必须自己实现可靠性。尽管如此,这是多人游戏服务器通常运行的方式,而且有很好的原因。


2
我认为UDP与TCP的选择不应该基于你将要处理的连接数量,而是取决于你是否可以接受非可靠传输。Web服务器可以轻松处理数千个TCP连接而没有任何问题。 - undefined
我从来没有在Web服务器上工作过,所以我不清楚。但是我曾经在数十个AAA游戏服务器上工作过,而且我绝对不会在低延迟高连接数的服务器上使用TCP。当然,你的情况可能会有所不同。 - undefined
2
主要考虑TCP与UDP决策的因素是“我希望系统如何处理丢失的数据包?” 如果您希望系统自动重传丢失的数据包,以便有效负载字节仍按发送顺序提交给接收应用程序,则应使用TCP。 另一方面,如果您不想等待数据包重传,并且更愿意直接接收通过的任何数据(包括可能缺失/乱序/重复的数据包作为获取更低延迟的代价),那么UDP是一个不错的选择。 - undefined

-2
多线程与单线程是一个难题,我认为这完全取决于你的实现观点。
如果你在一个线程上有一个良好的事件驱动系统,可能使用单线程进行低级网络IO会更好。创建线程本身就会有性能损失,因为系统需要处理它们,当然使用额外的处理器会有帮助,但正如你所说,当最终进入低级别时,所有线程都需要某种形式的同步,再次产生性能损失,除非你使用每个线程一个套接字。
多线程(每个线程一个套接字)在网络上的一个主要缺点是,大部分时间你的系统将容易受到“慢速洛里斯”攻击的影响。 慢速洛里斯的维基百科 关于慢速洛里斯的Computerphile视频 所以,我认为你最好将多线程用于其他长时间等待或耗时的任务。当然,你应该使用非阻塞IO。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接