不同的ACK行为(减慢吞吐量?)

我在一台机器(opensolaris)上运行netio( http://freshmeat.net/projects/netio/ )并联系两台不同的Linux机器(2.6.18-128.el5),机器A和机器B.机器A的networking吞吐量为10MB /秒,netio和B机器的每秒100MB /秒。 在公开的solaris上,我跟踪了连接,所有的交互看起来都是一样的 – 在接收和发送相同的窗口大小,相同的窗口大小,相同的拥塞窗口大小,但是慢速的机器每2或3次发送ACK,机器每12个接收一个ACK。 所有三台机器都在同一台交换机上。 这里是Dtrace输出:快速机器:

三angular洲发送recd  
  (us)字节字节swnd snd_ws rwnd rcv_ws cwnd ssthresh 
   122 1448 \ 195200 7 131768 2 128872 1073725440 
    37 1448 \ 195200 7 131768 2 128872 1073725440 
    20 1448 \ 195200 7 131768 2 128872 1073725440 
    18 1448 \ 195200 7 131768 2 128872 1073725440 
    18 1448 \ 195200 7 131768 2 128872 1073725440 
    18 1448 \ 195200 7 131768 2 128872 1073725440 
    18 1448 \ 195200 7 131768 2 128872 1073725440 
    19 1448 \ 195200 7 131768 2 128872 1073725440 
    18 1448 \ 195200 7 131768 2 128872 1073725440 
    18 1448 \ 195200 7 131768 2 128872 1073725440  
    57 1448 \ 195200 7 131768 2 128872 1073725440
   171 1448 \ 195200 7 131768 2 128872 1073725440    
    29 912 \ 195200 7 131768 2 128872 1073725440   
    30/0 195200 7 131768 2 128872 1073725440  

慢机:

三angular洲发送recd  
  (us)字节字节swnd snd_ws rwnd rcv_ws cwnd ssthresh 
   161/0 195200 7 131768 2 127424 1073725440  
    52 1448 \ 195200 7 131768 2 128872 1073725440 
    33 1448 \ 195200 7 131768 2 128872 1073725440   
    11 1448 \ 195200 7 131768 2 128872 1073725440   
   143/0 195200 7 131768 2 128872 1073725440   
    46 1448 \ 195200 7 131768 2 130320 1073725440   
    31 1448 \ 195200 7 131768 2 130320 1073725440   
    11 1448 \ 195200 7 131768 2 130320 1073725440   
   157/0 195200 7 131768 2 130320 1073725440  
    46 1448 \ 195200 7 131768 2 131768 1073725440 
    18 1448 \ 195200 7 131768 2 131768 1073725440

Dtrace代码

 dtrace:130717在CPU 0上丢弃
 #!/ usr / sbin / dtrace -s
 #pragma D选项安静
 #pragma D选项defaultargs
内联int TICKS = $ 1;
内联stringADDR = $$ 2;
的DTrace ::: BEGIN
 {
        TIMER =(TICKS!= NULL)?  TICKS:1;
        ticks = TIMER;
        TITLE = 10;
        title = 0;
        walltime =时间戳;
        printf(“正在启动... \ n”);
 }
 TCP发送:::
 /(args [2]  - > ip_daddr == ADDR || ADDR == NULL)/
 {
     NFS [参数[1]  - > cs_cid] = 1;  / *这是一个NFS线程* /
     delta = timestamp-walltime;
     walltime =时间戳;
     printf(“%6d%8d \%8s%8d%8d%8d%8d%8d%12d%12d%12d%8d%8d%d \ n”,
        增量/ 1000,
         args [2]  - > ip_plength  -  args [4]  - > tcp_offset,
         “”
         ARGS [3]  - > tcps_swnd,
         ARGS [3]  - > tcps_snd_ws,
         ARGS [3]  - > tcps_rwnd,
         ARGS [3]  - > tcps_rcv_ws,
         ARGS [3]  - > tcps_cwnd,
         ARGS [3]  - > tcps_cwnd_ssthresh,
         ARGS [3]  - > tcps_sack_fack,
         ARGS [3]  - > tcps_sack_snxt,
         ARGS [3]  - > tcps_rto,
         ARGS [3]  - > tcps_mss,
         ARGS [3]  - > tcps_retransmit
       );
    标志= 0;
    标题 - ;
 }
 TCP :::接收
 /(args [2]  - > ip_saddr == ADDR || ADDR == NULL)&& nfs [args [1]  - > cs_cid] /
 {
      增量=时间戳的walltime;
       walltime =时间戳;

       printf(“%6d%8s /%8d%8d%8d%8d%8d%8d%12d%12d%12d%8d%8d%d \ n”,
        增量/ 1000,
         “”
         args [2]  - > ip_plength  -  args [4]  - > tcp_offset,
         ARGS [3]  - > tcps_swnd,
         ARGS [3]  - > tcps_snd_ws,
         ARGS [3]  - > tcps_rwnd,
         ARGS [3]  - > tcps_rcv_ws,
         ARGS [3]  - > tcps_cwnd,
         ARGS [3]  - > tcps_cwnd_ssthresh,
         ARGS [3]  - > tcps_sack_fack,
         ARGS [3]  - > tcps_sack_snxt,
         ARGS [3]  - > tcps_rto,
         ARGS [3]  - > tcps_mss,
         ARGS [3]  - > tcps_retransmit
       );
    标志= 0;
    标题 - ;
 }

后续增加了包括未确认字节的数量,结果是慢代码确实运行了它的未确认字节,直到它到达拥塞窗口,在那里快速机器从不碰到它的拥塞窗口。 这是慢速机器的输出,当它的未确认字节到达拥塞窗口时:

取消增量字节字节发送接收信息
字节字节我们发送收到的窗口窗口窗口 
发送收到
 139760 0 31 1448 \ 195200 131768 144800 1073725440
 139760 0 33 1448 \ 195200 131768 144800 1073725440
 144104 0 29 1448 \ 195200 131768 146248 1073725440
 145552 0 31/0 195200 131768 144800 1073725440
 145552 0 41 1448 \ 195200 131768 147696 1073725440
 147000 0 30/0 195200 131768 144800 1073725440
 147000 0 22 1448 \ 195200 131768 76744 72400
 147000 0 28/0 195200 131768 76744 72400
 147000 0 18 1448 \ 195200 131768 76744 72400
 147000 0 26/0 195200 131768 76744 72400
 147000 0 17 1448 \ 195200 131768 76744 72400
 147000 0 27/0 195200 131768 76744 72400
 147000 0 18 1448 \ 195200 131768 76744 72400
 147000 0 56/0 195200 131768 76744 72400
 147000 0 22 1448 \ 195200 131768 76744 72400

dtrace代码:


 #!/ usr / sbin / dtrace -s
 #pragma D选项安静
 #pragma D选项defaultargs
内联int TICKS = $ 1;
内联stringADDR = $$ 2;
 tcp :::发送,tcp :::接收
 /(args [2]  - > ip_daddr == ADDR || ADDR == NULL)/
 {
     NFS [参数[1]  - > cs_cid] = 1;  / *这是一个NFS线程* /
     delta = timestamp-walltime;
     walltime =时间戳;
     printf(“%6d%6d%6d%8d \%8s%8d%8d%8d%8d%8d%12d%12d%12d%8d%8d%d \ n”,
         args [3]  - > tcps_snxt  -  args [3]  - > tcps_suna,
         args [3]  - > tcps_rnxt  -  args [3]  - > tcps_rack,
        增量/ 1000,
         args [2]  - > ip_plength  -  args [4]  - > tcp_offset,
         “”
         ARGS [3]  - > tcps_swnd,
         ARGS [3]  - > tcps_snd_ws,
         ARGS [3]  - > tcps_rwnd,
         ARGS [3]  - > tcps_rcv_ws,
         ARGS [3]  - > tcps_cwnd,
         ARGS [3]  - > tcps_cwnd_ssthresh,
         ARGS [3]  - > tcps_sack_fack,
         ARGS [3]  - > tcps_sack_snxt,
         ARGS [3]  - > tcps_rto,
         ARGS [3]  - > tcps_mss,
         ARGS [3]  - > tcps_retransmit
       );
 }
 TCP :::接收
 /(args [2]  - > ip_saddr == ADDR || ADDR == NULL)&& nfs [args [1]  - > cs_cid] /
 {
      增量=时间戳的walltime;
       walltime =时间戳;
       printf(“%6d%6d%6d%8s /%-8d%8d%8d%8d%8d%8d%12d%12d%12d%8d%8d%d \ n”,
         args [3]  - > tcps_snxt  -  args [3]  - > tcps_suna,
         args [3]  - > tcps_rnxt  -  args [3]  - > tcps_rack,
        增量/ 1000,
         “”
         args [2]  - > ip_plength  -  args [4]  - > tcp_offset,
         ARGS [3]  - > tcps_swnd,
         ARGS [3]  - > tcps_snd_ws,
         ARGS [3]  - > tcps_rwnd,
         ARGS [3]  - > tcps_rcv_ws,
         ARGS [3]  - > tcps_cwnd,
         ARGS [3]  - > tcps_cwnd_ssthresh,
         ARGS [3]  - > tcps_sack_fack,
         ARGS [3]  - > tcps_sack_snxt,
         ARGS [3]  - > tcps_rto,
         ARGS [3]  - > tcps_mss,
         ARGS [3]  - > tcps_retransmit
       );
 }

现在,它仍然是一个机器为什么落后,而另一个没有…

我以前见过这样的行为。 我看到了两个原因:

  • 错误的TCP / IPstream量控制协商
  • 坏司机

由于两台机器都运行相同的内核,因此运行相同的TCP / IP代码(除了设备内核模块,如果不同的话),TCP / IPstream量控制问题不太可能发生。

司机虽然。

我有一台Windows 2003服务器,而这个服务器根本无法传输超过6-10MB / s到某些服务器,因为这是一个备份到磁盘服务器,这是不可接受的。 看了一些包捕获,他们看起来很像你所看到的。 什么修复它是更新接收服务器(Server 2003备份服务器)上的networking驱动程序(如发生的广播)更新。 一旦完成,我就达到了60-80MB / s。

由于这是Linux,您可能会遇到某种大型分段卸载问题。 这在一定程度上依赖于NIC硬件本身来处理大段的分裂。 如果由于某种原因而无法正常工作(固件错误?),可能会导致这种奇怪的延迟。 这是基于每个驱动程序或接口configuration的。 ethtool -K可以通过设备进行configuration。