linux – 高性能文件服务的设计选择
我正在开发一个
linux下的应用程序,需要支持大约250个连接,并通过100MB大小范围内的TCP套接字传输大文件.目的是调整吞吐量而不是延迟.我希望始终保持饱和的2x1Gbit以太网连接.这些将是渠道保税.
预计应用程序将持续繁忙,并且将尽快丢弃数据.连接将在大多数时间保持不变,因此与HTTP不同,它们不会经常被拆除. 我一直在寻找各种选项,如epoll,sendfile api等高性能和aio(看起来太不成熟和风险恕我直言). 我也一直在寻找使用下面的epoll的提升asio api.我之前使用过它,但不是像这样的高性能应用程序. 我有超过4个处理器核心可用,所以我可以利用它. 但是,我读到由于反应器设计中的一些锁定,使用多线程的boost asio不是很好.这对我来说可能是一个问题吗? 如果我有很多可用的CPU核心,我应该创建尽可能多的线程或分叉进程并将它们设置为在每个处理器核心上运行吗? 怎么样锁定等我想要一些设计建议.我怀疑我的主要瓶颈是磁盘I / O但是仍然……我想要一个好的设计,以后再进行大量的返工. 有什么建议? 解决方法
磁盘IO通常比网络慢. 250个客户端对现代CPU来说毫无用处. 大文件的大小并不重要.真正的问题是数据的总量是否适合RAM – 并且可以扩展RAM以使数据适合它.如果数据适合RAM,那么不要过分优化:带有sendfile()的哑单线程服务器就可以了. 应考虑使用SSD进行存储,尤其是在优先读取数据时.
“尽可能快”是一场灾难.我负责至少一个这样的多线程灾难,由于它导致的磁盘数量,它无法扩展. 通常,您可能希望每个存储器具有很少(例如4个)磁盘读取线程,这将为非常大的块调用read()或sendfile(),以便OS有机会优化IO.由于人们希望乐观地认为某些数据可以并行地从OS的IO缓存中提供,因此很少需要线程. 别忘了还设置大套接字发送缓冲区.在您的情况下,轮询插槽的可写性也是有意义的:如果客户端无法以您可以读取/发送的速度接收,则读取没有意义.服务器上的网络通道可能很胖,但客户端NIC /磁盘不是这样.
几乎所有FTP服务器现在都使用sendfile(). Oracle使用AIO和Linux是他们的主要平台.
IIRC仅适用于插座. IMO任何便于处理插座的实用程序都很好.
NIC加速TCP,磁盘IO主要由控制器本身完成.理想情况下,您的应用程序将处于空闲状态,等待磁盘IO.
检查libevent作为替代方案.您可能只需要sendfile()的线程数量有限.并且数量应该是有限的,否则你会用磁盘搜索来消除吞吐量.
不是.磁盘受搜寻影响最大. (我是否重复了足够的时间?)如果您有许多自主读取线程,您将失去控制发送到磁盘的IO的可能性. 考虑最糟糕的情况.所有read()必须转到磁盘==更多线程,更多磁盘搜索. 考虑最好的情况.所有read()都是从cache == no IO提供的.然后你正在以RAM的速度工作,可能根本不需要线程(RAM比网络快).
这是一个非常长的答案的问题,这不适合这里(我也没有时间写).它还主要取决于您要提供的数据量,使用的存储类型以及访问存储的方式. 如果我们将SSD作为存储,那么任何愚蠢的设计(如为每个客户端启动一个线程)都可以正常工作.如果后端有真正的旋转介质,那么您必须对来自客户端的IO请求进行切片和排队,试图避免一侧的客户端和另一端的客户端不能以一定的方式调度IO,从而导致最少量的搜索. 我个人本想开始使用简单的单线程设计,在主循环中使用poll()(或boost.asio或libevent).如果数据被缓存,则无法启动新线程.如果必须从磁盘中提取数据,单线程将确保我避免搜索.使用读取数据填充套接字缓冲区并更改等待POLLOUT模式以了解客户端何时使用了数据并准备好接收下一个块.这意味着我在主循环中至少有三种类型的套接字:监听套接字,客户端套接字我正在等待请求,客户端套接字我正在等待再次变为可写.
啊…甜蜜的梦…… (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |