通过 tcpcopy(pf_ring) 对 BCM 5719 小包做的多组 benchmark

tcpcopy 在文档化、用户参与方式方面有很大的提升空间这个问题在之前已经专门说过。最终,在我们自己阅读代码的情况下,结合 pf_ring,坚持跑通了整个流程,用其对目前 BCM 5719 型号的网卡做了多组对比,结论见结尾。
使用 tcpcopy 做 benchmark,务必确定 tcpcopy 语法使用的正确性, 尽管互联网上绝大多数的文档以及官方文档都写的含糊不清。
比如,我们之前把过滤条件 -F "tcp and dst port 80" 写成了 -F "tcp and src port 80",造成的结果是在错误的基础上得出了一些奇葩的数据以及无法解释的现象,比如到 target server 的流量特别小,并且及其的不稳定,得到的 pps 也是非常的不稳定大到 400kpps/s,小到 20k  甚至 0。

这里列举我们测试环境使用的一组配置。
所有机器都是 RedHat 6.2 2.6.32-279.el6.x86_64,Tcpcopy 1.0 版本,PF_RING 6.0.1,BCM 5719,双网卡 bonding。另外,我们单台生产机器的流量都比较大,并且绝大多数都是 100B 以下的小包,所以对系统的要求还是比较高的。
为了避免后续的误解,先确定几个用语:
1. online server(OS): 即我们线上生产环境的机器
2. target server(TS): 是我们想做 benchmark 的那台机器,以测试其究竟能支撑多大的量
3. assistant server(AS): 是安装了 intercept 的机器
4. mirror server(MS): 通过 tcpcopy 的 mirror 工具把 OS 的流量复制到该台机器上

我们一共做了三大组 benchmark,每组下面包含若干小的 benchmark,包括:
1. tcpcopy + intercept
2. tcpcopy + intercept + tcpcopy mirror,加一个 mirror 是为了减少对 OS 的负载,这样 tcpcopy 在 MS 上运行
3. tcpcopy + intercept + 交换机 mirror,更直接的方式复制线上流量,保证对 OS 没有干扰,并且能保证 100% 全量复制 OS 的流量

下面是测试机器的信息:

在整个过程中,我们主要关注的是网卡的带宽(sar -n DEV),网卡接受包的数量(sar -n DEV),当前的连接数(ss -s)以及 access log(grep) 的数量。不管是上面哪种类型的测试,基本的招式都是如下的方式:
OS(online server)
$ sudo ./tcpcopy -x [email protected]:BB:CC:DD:EE:22-192.168.50.52:[email protected]:BB:CC:DD:EE:33 -l tcpcopy.log -s 192.168.50.51  -C 16 -F  'tcp and  dst  port 80' -o bond0 -i bond1 -c 192.168.1.x
AS(assistant server)
$ sudo ./intercept -i bond0 -F 'tcp and port 80'   -l intercept.log

TS(target server)上唯一要做的就是设置好路由,简单起见可以把所有的路由都指向 AS,或者通过 -c 参数改变源 IP,这样可以单独增加路由:
$ sudo route add -net YOUR_SRC_IP netmask xxxx gw YOUR_AS_IP
MS(mirror server) 只有在使用 mirror 模式的时候才需要,这个用到的时候再解释。

1. pf_ring mode 测试(0:11 – 0:24)
OS: mode 1
AS: mode 0
320k estab, 120kpps, 120Mbps, 8.5k log/s

2. pf_ring AS mode 测试(0:25 – 0:28)
OS: mode 1
AS: mode 1
没有任何的 estab,但是有 pps

3. pf_ring AS mode 测试(0:28 – 0:29)
OS: mode 1
AS: mode 2
同上,没有任何的 estab,但是有 pps

4. AS 过滤条件的选择对最终 TS 的影响(0:30 – 0:33)
OS: /
AS: -F 'tcp'
跟 1. 一样,没有大波动

5. pf_ring OS mode 测试(0:33 – 0:37)
OS: mode 2
AS: mode 0
跟 1. 一样,没有大波动

6. OS 过滤条件的选择对最终 TS 的影响(0:38 – 0:42)
OS: -F 'tcp'
AS: /
跟 1. 类似,一样的 pps,但是 estab 相对减少,变至 260k,log 也相应变少,至 6.7k log/s

7. OS 跟 AS 之间的并发测试(00:45 – 0:53)
OS: -C 8
AS: /
同样的 pps,但是更多的 estab,350k,log 数量跟 1. 大致类似 8.7k log/s

8. OS 跟 AS 之间的并发测试(0:53 – 01:01)
OS: -C 2
AS: /
同 7.

9. OS 跟 AS 之间的并发测试(01:01 – 01:07)
OS: -C 1
AS: /
基本同 7.,但是 estab 跟 log 稍多,9k log/s

10. 流量放大测试(01:08 – 01:15)
OS: -n 2
AS: /
同样的 estab,320k,但是更多的 pps,180kpps/s,150Mbps/s,与此同时,TS 的 nic 开始 drop 了

11. 源 IP  缩小(01:15 – 01:21)
OS: -c 192.168.1.1
AS: /
只剩 20k estab, 15kpps, 10Mbps, 300 log/s,这个变化很明显,socket 数量明显不够了

12. 完全使用真实的源 IP(01:21 – 01:28)
OS: 去掉 -c 参数
AS: /
跟 1. 类似,但是 nic 有明显的 drop

13. OS 通过原生的 pcap 抓包,不经过 pf_ring(01:28 – 01:34)
OS: 编译的时候不要使用 –with-pfring
AS: 依然是 pf_ring
10kpps/s, 25kestab, 400log/s,情况一下子变糟糕了

14. OS 通过原生的 pcap 抓包,不经过 pf_ring(01:34 – 01:38)
OS: no pf_ring, pcap -C 2
AS: pf_ring
结果同 13.

15. OS/AS 通过原生的 pcap 抓包,不经过 pf_ring(01:38 – 01:41)
OS: no pf_ring, pcap, -C 2
AS: no pf_ring, pcap
同 13、14

16. OS/AS 通过原生的 pcap 抓包,不经过 pf_ring(01:41 – 01:46)
OS: no pf_ring, pcap, -C 16
AS: no pf_ring, pcap
同 13、14、15

17. raw socket 抓包(01:46 – 01:50)
OS: sudo ./tcpcopy -x  80-192.168.50.52:80 -l tcpcopy.log -s 192.168.50.51 -c 192.168.1.x -C 16
AS: sudo ./intercept -i bond0 -F 'tcp'   -l intercept.log
结果跟单纯的 pcap 比一样不理想,100kpps, 3k estab, 20log/s

第一种单机模式测试到此结束,可以得出的结论是:
1. 要让 TS 复制到流量,尤其是比较苛刻的环境,PF_RING 是必须的,raw socket 以及 pcap 是无法满足要求的
2. 源地址要充分的广,可以直接使用真实的客户端发过来的,这个需要将 TS 的默认 GW 指向 AS,这样也最真实,-c 的手法是一个折衷的方式
3. PF_RING 的几种模式对实际影响不大,虽说是 mode 2 大于 mode 1 大于 mode 0 的,但是实际测下来,区别不大

下图是整个测试过程的秒级监控,可以对比上面的时间戳看。

第二种是 mirror 模式,这个的好处是能减少对 OS 的负载,OS 本身就要对外提供服务,再加上个抓包,理论上应该负载会更重,通过把 OS 的流量 mirror 到一台空闲机器上,会减轻 OS 的负载。
在 OS 上起 mirror,把流量打到 MS 上:
sudo  ./mirror -s AA:BB:CC:DD:EE:22 -t AA:BB:CC:DD:EE:55 -F 'tcp and  port 80' -o bond0 -i bond1 -x 192.168.50.50  -l mirror.log

在 MS 上起 tcpcopy:
$ sudo ./tcpcopy -x [email protected]:BB:CC:DD:EE:55-192.168.50.52:[email protected]:BB:CC:DD:EE:33 -l tcpcopy.log -s 192.168.50.51   -F  'tcp'  -o bond0 -c 192.168.1.x  -C 16

在 AS 上起 intercept:
$ sudo ./intercept -i bond0 -F 'tcp'   -l intercept.log

上面的测试结果不是很理想,4k log/s,100kpps/s,75Mbps,220kestab。

最后又玩了下交换机 mirror,通过交换机的 mirror 能够全量的复制 OS 的流量到一台单独的机器上,而不会像 tcpcopy mirror 那样存在瓶颈。然后在被复制的流量的机器上起 tcpcopy,结果跟 tcpcopy mirror 的类似,不如单机, 6k log/s,270k,70kpps estab,70Mbps。

除了上面的方式,作者还提供了一个思路解决运行 tcpcopy 机器的瓶颈问题,就是把 mirror 到的流量先通过一个 LB 分布的几台单独的机器,然后在这些单独的机器分别跑 tcpcopy,这个思路肯定是可行的,不过操作的繁杂程度已经超过我本身做这次 benchmark 的成本了,有条件有时间的可以去试试。

把上面几种模式都玩了一遍,结果已经不是很重要了,或者说结果是显而易见的。毕竟,Broadcom 的卡也仅仅是相同配置 Intel 的 1/3 – 1/4  的价格。关键是要享受这个过程,为了解决一个问题而不断尝试新思路新方式的过程,Enjoy hacking。