当服务器的并发TCP连接数以十万计时,我们就会对一个TCP连接在操作系统内核上消耗的内存多少感兴趣。socket编程方法提供了SO_SNDBUF、SO_RCVBUF这样的接口来设置连接的读写缓存,linux上还提供了以下系统级的配置来整体设置服务器上的TCP内存使用,但这些配置看名字却有些互相冲突、概念模糊的感觉,如下(sysctl-a命令可以查看这些配置): [cpp]viewplaincopy net.ipv4.tcp_rmem= net.ipv4.tcp_wmem= net.ipv4.tcp_mem=912167 net.core.rmem_default= net.core.wmem_default= net.core.rmem_max=167 net.core.wmem_max=167 还有一些较少被提及的、也跟TCP内存相关的配置: [cpp]viewplaincopy net.ipv4.tcp_moderate_rcvbuf=1 net.ipv4.tcp_adv_win_scale=2 (注:为方便下文讲述,介绍以上系统配置时前缀省略掉,配置值以空格分隔的多个数字以数组来称呼,例如tcp_rmem[2]表示上面第一行最后一列167。) 网上可以找到很多这些系统配置项的说明,然而往往还是让人费解,例如,tcp_rmem[2]和rmem_max似乎都跟接收缓存最大值有关,但它们却可以不一致,究竟有什么区别?或者tcp_wmem[1]和wmem_default似乎都表示发送缓存的默认值,冲突了怎么办?在用抓包软件抓到的syn握手包里,为什么TCP接收窗口大小似乎与这些配置完全没关系? TCP连接在进程中使用的内存大小千变万化,通常程序较复杂时可能不是直接基于socket编程,这时平台级的组件可能就封装了TCP连接使用到的用户态内存。不同的平台、组件、中间件、网络库都大不相同。而内核态为TCP连接分配内存的算法则是基本不变的,这篇文章将试图说明TCP连接在内核态中会使用多少内存,操作系统使用怎样的策略来平衡宏观的吞吐量与微观的某个连接传输速度。这篇文章也将一如既往的面向应用程序开发者,而不是系统级的内核开发者,所以,不会详细的介绍为了一个TCP连接、一个TCP报文操作系统分配了多少字节的内存,内核级的数据结构也不是本文的国际高尔夫挑战赛正式开始萌宠丨阿布一只平衡宇宙万物的柯基犬
|