标签:des style class blog http tar
如今的server支撑上百万个并发 TCP 连接已经不是新闻(余锋2010年的演讲,ideawu 的 iComet 开源项目,WhatsApp 做到了 2.5M)。实现 C1000k 的常规做法是调整内核參数,提高文件数,降低每一个连接的内存消耗(參考 ideawu 的博客)。
在今年的 BSDCan2014 会议上, Patrick Kelsey 介绍了把 FreeBSD 9.x 的 TCP/IP 协议栈移植到了用户态(slides, github.com/pkelsey/libuinet),并用于 WANProxy 项目。在用户态执行 TCP/IP 协议栈意味着并发 TCP 连接不再占用系统文件数,仅仅占内存,攻克了 C1000k 的一大瓶颈,内核仅仅要提供一个收发网络 packet 的接口即可(比如netmap)。
内核的网络协议栈强调通用性,主要是为吞吐量优化(性能指标一般是 MB/s 或 packets per second),顺带兼顾大量并发连接。为了支持 C1000k,要调整内核參数让每一个连接少占资源,这与内核代码的设计初衷是违背的。
用户态协议栈捅破了这层窗户纸,能够依据应用的特点来剪裁协议栈功能。优化也更直接,不再是调黑盒參数组合,而是直接上 profiling,依据结果修改应用程序和协议栈的代码。
用户态协议栈的吞吐量比不上内核,只是对 C1000k 的应用场合(比如 comet)应该不成问题。
我用 muduo 做了一次 C1000k 的实验,用的是传统方案,没实用 libuinet。在一台 16GB 内存的 Dell WS490 旧工作站上创建了 50万个 TCP 连接,提供 echo 服务。系统可用内存降低了 5286MiB,即每一个连接 10.8KiB(当中服务进程占用了 1421MiB 内存,即每一个连接 2.9KiB,其余 8KiB 左右是内核协议栈的开销)。client是一台 8GB 内存的 i5-2500,内存消耗也是 5GB 多,因此这次实验仅仅试到了 C500k。客户机绑定了 10 个 IP,每一个 IP 上发出 5 万 TCP 连接,执行 pingpong 协议,每一个连接轮流收发 64 字节的消息。測得 QPS 大约是 11k,server的 CPU 占用率约为 60%(单线程)。profile 显示 CPU 的主要开销在内核中,我对这个结果基本惬意。
受 libuinet 启示,我把 4.4BSD-Lite2 的网络协议栈也移植到了 Linux 用户态(github.com/chenshuo/4.4BSD-Lite2),方便《TCP/IP 具体解释 第2卷》的读者跟踪调试其代码。下面是 Eclipse CDT 单步跟踪的截图。
也能够用各种现成的工具来分析函数的调用关系:
我在《谈一谈网络编程学习经验》中说这本书的“代码仅仅能看,不能上机执行,也不能修改试验”如今不再成立了。
我在《关于 TCP 并发连接的几个思考题与试验》中用 TAP/TUN 作为自己写的协议栈的对外接口,对 4.4BSD-Lite2 也可如法炮制,让 20 年前的 TCP/IP 协议栈与如今的机器通信。除了与本机通信,还能够通过 NAT 转发,让 4.4BSD-Lite2 连上如今的 Internet。(sudo iptables -t nat -A PREROUTING -p tcp --dport 2009 -i eth0 -j DNAT --to192.168.0.2:2009)
C1000k 新思路:用户态 TCP/IP 协议栈,布布扣,bubuko.com
标签:des style class blog http tar
原文地址:http://www.cnblogs.com/zfyouxi/p/3789519.html