首页 文章

有关缓冲区使用和自定义TCP服务调整的一些提示?

提问于
浏览
2

我最近一直在研究一些网络库和框架,比如libevent,libev,Facebook Tornado和Concurrence(Python) .

我在实现中注意到的一件事是使用应用程序级的每个客户端读/写缓冲区(例如Tornado中的IOStream) - 甚至HAProxy也有这样的缓冲区 .

除了这些应用程序级缓冲区之外,每个套接字还有OS内核TCP实现的缓冲区 .

我可以理解app / lib对读缓冲区的使用我认为:app / lib从内核缓冲区读取到app缓冲区,应用程序对数据执行某些操作(例如,对其中的消息进行反序列化) .

但是,我对写缓冲区的需要/使用感到困惑 . 为什么不写入内核的发送/写入缓冲区?是为了避免系统调用(写入)的开销吗?我想重点是准备好将更多数据推入内核's write buffer when the kernel notifies the app/lib that the socket is 688583 (e.g. EPOLLOUT). But, why not just do away with the app write buffer and configure the kernel'的TCP写缓冲区同样大?

此外,考虑禁用Nagle算法有意义的服务(例如游戏服务器) . 在这样的配置中,我想我想要相反:没有内核写缓冲区而是应用程序写缓冲区,是吗?当应用程序准备好发送完整的消息时,它会通过send()等写入应用程序缓冲区,内核会通过它 .

如果愿意的话,请帮助我清楚了解这些理解 . 谢谢!

2 回答

  • 1

    好吧,对于haproxy来说,它在读取和写入缓冲区之间没有区别,缓冲区用于两种用途,这样可以节省副本 . 但是,做一些改变真的很痛苦 . 例如,有时你必须重写HTTP标头,你必须设法正确地为你的重写移动数据,并保存一些关于前一个标头值的状态 . 在haproxy中,可以重写连接头,并保存其先前和新状态,因为在重写之后需要它们 . 使用读取和写入缓冲区,您没有这种复杂性,因为如果需要任何原始数据,您可以随时回顾读取缓冲区 .

    Haproxy也能够在Linux上的套接字之间使用拼接 . 这意味着它不会读取或写入数据,它只是告诉内核要在哪里以及在何处移动它 . 然后内核自动移动指针而不复制数据以将TCP段从网卡传输到另一个(如果可能),但是数据然后永远不会传输到用户空间,因此避免了双重复制 .

    你通常不需要在缓冲区之间复制数据,这是完全正确的 . 这是浪费内存带宽 . Haproxy以10Gbps的速度运行,20%的CPU使用拼接,但没有拼接(2个拷贝),接近100% . 但是,然后考虑替代品的复杂性,并做出您的选择 .

    希望这会有所帮助 .

  • 0

    当您使用异步套接字IO操作时,异步读/写操作立即返回,因为异步操作不能保证成功处理所有数据(即将所有必需的数据放入TCP套接字缓冲区或从中获取所有必需的数据)一次调用,部分数据必须比多次操作更长久 . 然后,只要IO操作持续,您就需要一个应用程序缓冲区空间来保留数据 .

相关问题