翻译:飞哥 (http://hi.baidu.com/imlidapeng)
版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明。
原文名称:《Linux Performance and Tuning Guidelines》
1.5.1 网络实现 1.5.2 TCP/IP 1.5.3 减负 1.5.4 绑定
网络子系统是性能方面另一个重要的子系统。网络除了Linux以外还会与其它很多设备交互,如交换机、路由器、网关、PC客户端等等。尽管这些设备已超出Linux的控制范围,但它们仍会对系统整体性能产生影响。不要忘记我们现在工作生活在一个网络时代。
在此我们将主要关注Linux是怎样处理网络操作的。
TCP/IP协议有着与OSI模型相似的层次结构。Linux网络实现使用了类似的方法。图1-23展示了Linux TCP/IP堆栈的层次结构和TCP/IP通讯的概览。
图1-23 网络层次结构和网络运行概览
像许多UNIX系统一样Linux的TCP/IP网络使用套接字接口。套接字为用户应用程序提供使用接口。让我们将一起来了解一下网络传输时必要的操作步骤。
-
当要传送数据到对方主机时,应用程序创建所要传送的数据。
-
应用程序打开套接字并向套接字写入数据。
-
使用套接字缓冲(socket buffer)接口来处理需要传输的数据。套接字缓冲拥有数据的引用并通过所有层将其向下传递。
-
在每一层里,都会执行相应的操作如解析数据包头、添加修改数据包头、检查大小、路由操作、分片等。当套接字缓冲通过这些层向下传递时,其数据本身不会被复制到每个层,因为将实际的数据复制到每个层是很没有效率的,内核通过及时更改套接字缓冲的引用并传递到下一层来节省没有必要的开销。
-
最后数据通过网卡传输到线路中。
-
以太网帧到达对方主机的网络接口。
-
如果与网卡的MAC吻合,帧会被转到网卡的缓冲。
-
网卡最后会将数据包移到套接字缓冲并向CPU发出一个硬终端。
-
然后CPU处理数据包并通过所有层向上传递直到其到达应用程序(如Apache)的端口。
套接字缓冲
正如前面所述,内核使用缓冲来发送和接受数据。图1-24展示了网络中所用的缓冲。它们可以通过/proc/sys/net下的文件来调整。
/proc/sys/net/core/rmem_max /proc/sys/net/core/rmem_default /proc/sys/net/core/wmem_max /proc/sys/net/core/wmem_default /proc/sys/net/ipv4/tcp_mem /proc/sys/net/ipv4/tcp_rmem /proc/sys/net/ipv4/tcp_wmem
有时它可以影响网络性能。我们将在4.7.4“增加网络缓冲”中详细介绍。
图1-24 套接字缓冲的内存分配
网络API(NAPI)
在新的网络API中网络子系统发生了一些变化。Linux中网络堆栈的标准实现更加关注可靠性和低延时而不是低开销和高吞吐量。当创建防火墙时这些特点适合的,但大多数企业应用如文件打印或数据库的运行速度要比相似情况下windows要慢。
如图1-25中蓝色箭头所描述的,在传统处理网络数据包的方法中,网卡最后将数据包转移至操作系统内核的网络缓冲中并向CPU发出一个硬中断。
虽然这只是简单描述了处理网络数据包的过程,但其反应了这种方法的弊病。每次匹配MAC地址的以太网帧到网络接口时,都会产生一个硬中断。无论何时也不管CPU在做什么都不得不要停止下来处理这个硬中断,这会导致一个上下文交换并要清空相应的处理器缓存。如果只有很少的数据包到达接口,你可能认为这并不是问题,但在千兆网和现代的应用程序每秒钟可以创建数千个数据包的情况下,这会导致大量中断和上下文交换的发生。
图1-25 Linux网路堆栈
因此为减少处理网络通讯的开销,NAPI被采用。当第一个数据包到来时,NAPI像传统方式一样发出一个中断。但此后,网路接口进入轮询模式(Polling Mode)。即使在网络接口的DMA环缓冲中有数据包,也不会产生新的中断,这可以有效减少上下文交换和相应的开销。直到最后一个数据包被处理完并且环缓冲为空时,网卡重新恢复到中断模式【Interrupt Mode】。NAPI另外的好处就是其创建的软中断可以由多个处理器处理从而提升多处理器的扩展性。NAPI为大多数企业级多处理器系统带来明显改善,但它需要支援NAPI的驱动。正如我们在本文调优章节中所阐明的,这里有着很大的调优空间。
Netfilter
作为内核的一部分Linux有着先进的防火墙功能。这个功能由Netfilter模组实现。你可以使用iptables工具来调整和配置Netfilter。
一般而言,Netfilter提供以下功能。
-
包过滤:当数据包符合某个规则时,Netfilter接受或拒绝此数据包,或者根据拒绝规则执行一个特定动作。
-
地址转换:当数据包符合某个规则时,Netfilter将变更此数据包来符合地址转换的要求。
匹配过滤可以定义以下属性。
-
网路接口
-
IP地址、IP地址范围、子网
-
协议
-
ICMP类型
-
端口
-
TCP标志
-
状态(参见“连接追踪”)
图1-26显示数据包是怎样通过Netfilter链的,Nefilter链是指依次应用在每个节点上的一组已定义规则。
图1-26 Netfilter中数据包的流向
如果数据包与规则匹配Netfilter会执行相应的动作,这个动作被叫做target,可能的target有:
ACCEPT:接受数据包并让其通过
DROP:默默地将数据包丢弃
REJECT:丢弃数据包,向发送端回传数据包如ICMP端口不能到达。重置源主机TCP。
LOG:记录匹配的数据包。
MASQUERADE,SNAT,DNAT,REDIRECT:地址转换。
连接追踪
为获得更精致的防火墙功能,Netfilter使用连接追踪机制记录所有网络通讯的状态。使用TCP连接状态(参考“建立连接”)和其他网络属性(如IP地址、端口、协议、序列号、ack number、ICMP类型等),Netfilter将包分为下面四种状态。
NEW:试图建立新连接的包
ESTABLISHED:通过连接的包
RELATED:与前面的包相关的包
INVALID:由于损坏或无效而未知状态的包
另外,Netfilter能使用单独的模组分析协议的特定属性和操作来获得更为详细的连接追踪。例如用于FTP、NetBIOS、TFTP、IRC等的连接追踪模组。
TCP/IP作为默认的网络协议已经有很多年了。Linux的TCP/IP实现与标准完全兼容。为了更好的性能调优,你应该熟悉基本的TCP/IP网络。
要了解详细内容,参见《TCP/IP Tutorial and Technical Overview》,GG24-3376
连接的建立
在应用数据传输前,需要在客户端和服务器端建立连接。连接建立的过程叫做TCP/IP三次握手。图1-27展示了连接建立到结束的过程。
-
客户端发送一个SYN包(设置SYN标志的包)给对方主机请求连接。
-
服务器端接收到包并发送一个SYN+ACK包。
-
然后客户端发送一个ACK包到对方完成连接的建立。
一旦连接建立,应用程序的数据就可以通过连接传输。当所有的数据传输完成,连接结束流程开始。
-
客户端发送一个FIN包给服务器段,开始连接结束流程。
-
服务器端发送FIN的确认,如果没有数据需要传给客户端,发送FIN包到客户端。
-
客户端发送ACK包到服务器端结束连接。
图1-27 TCP三次握手
在此会话过程中,连接状态会发生改变。图1-28展示了TCP/IP连接的状态图。
图1-28 TCP连接的状态图
你可以使用netstat命令了解每个TCP/IP会话的连接状态。更多内容请看2.3.11“netstat”。
流量控制(Traffic control)
TCP/IP实现中有一种机制来保证数据的有效传输和确保即使在网路传输质量很差又拥堵时包也可以顺利传递。
TCP/IP传输窗口
在Linux操作系统效能中传输窗口策略是TCP/IP实现的重要方面。基本上,TCP传输窗口就是在对方请求确认前指定主机能发送和接收数据的最大数量。窗口大小由接收主机通过TCP数据包头中窗口大小栏位提供给发送主机。使用传输窗口,主机可以更有效地发送包,因为发送主机没有必要等待每个发送包的确认。它提高网络利用率。也会提升延迟确认效率。TCP窗口开始时很小,随着来自对方的每此成功确认慢慢增长。想要优化窗口大小,见4.7.4“增加网络缓冲”。
图1-29滑动窗口和延迟确认
作为一个选项,高速网络使用一个名叫窗口缩放(Windows Scaling)的技术来增加最大传输窗口大小。我们将在“TCP选项调优”分析这些实现的影响。
重传(Retransmission)
在连接建立、结束和数据传输过程中,由于一些原因(网卡故障、路由缓慢、网路堵塞、buggy network implementation等)会发生多次超时和数据重传。为解决这种状况TCP/IP将包放入队列并尝试多次发送包。
你可以通过配置参数来改变某些内核行为。你可能想当网络丢包率高时增加尝试TCP SYN连接建立包的数量。你也可以通过/proc/sys/net下的文件改变某些超时临界值。更多信息,请看“调优TCP行为”。
如果你系统中的网络适配器支持硬件减负功能,内核可以将其部分任务转移到适配器上执行,这样可以减少CPU的使用。
- 校验和减负
执行IP/TCP/UDP校验和,通过比较协议头中校验和字段的值和计算包数据的值来为确保包被正确的传输。
- TCP分段减负(TSO)
当数据大小超过目标网络适配器的最大传输单元(MTU)时,数据被分割成MTU大小的包,这个动作由适配器代表内核来完成。
关于更多的网络进阶特性,参见“Tuning IBM System x Servers for Performance”和10.3 网路进阶特性。
Linux内核通过使用绑定(bonding)驱动程序提供将网络接口集成在一起的功能。这是设备独立的绑定驱动。(也有设备特定的驱动)绑定驱动支援802.3连接的集成规范和一些原始的负载平衡和容错实现。它可以获得更高等级的可用性和效能的提升。请参见内核相关文档Documention/networking/bonding.txt