DANTE

链路聚合折腾记

哪些因素会影响一个服务器上运行着的Web Application的性能?前端程序员,后端程序员,服务器运维人员可能会给出不同的答案。

我最近就遇到了与局域网带宽有关的性能问题。一个Web App,在经过代码层面的性能优化后,在一台配置较老的服务器上观察到了每秒处理请求数的显著提升,而在配置高得多的服务器上,却没有观察到变化。由于高配置服务器的每秒请求处理数量本身就远高于低配置的服务器,我下意识地运行了一下ifstat。果然!在高配置的服务器上,网络端口em1的出站数据高达120000KB/s,看上去已经跑到了千兆以太网的极限。

由于没有万兆设备,一根GbE网线解决不了的事情,就只能靠多根来解决了。幸好服务器上的千兆网卡有4个端口,去掉一个另有他用的端口,仍有三个可以用来做链路聚合。于是我开始搜索资料和教程,尝试配置链路聚合,没想到这一下子就折腾了两三天。

我首先搜索的,就是如何在服务器用的CentOS上配置链路聚合。kernel.org的文档说,Linux提供这样几种链路聚合模式:

  • balance-rr or 0
  • active-backup or 1
  • balance-xor or 2
  • broadcast or 3
  • 802.3ad or 4
  • balance-tlb or 5
  • balance-alb or 6

根据文档和网络资料,5和6不需要任何交换机方面的支持;1最为简单粗暴,轮流用聚合中的物理链路发送packet;4看上去则是最多人用的(尤其是玩NAS的人),不过需要在交换机上额外设置。

我决定从802.3ad开始。

等等,为什么不先试试balance-rr?这可是唯一一个能够让单个TCP连接突破物理链路带宽上限,达到比如说3Gbps的模式!

但是我并不需要。我这里的场景是,多台机器,数量众多的TCP连接,别的模式是能够满足的;而balance-rr会带来packet乱序的问题,引入额外的负担。

回到802.3ad。

在CentOS 7上设置链路聚合非常简单,只需要在/etc/sysconfig/network-scripts/里面创建聚合端口的ifcfg-*文件,并修改其他端口的相应文件使其成为聚合端口的slave,相关教程一抓一大把。

在交换机上设置802.3ad动态链路聚合也并不算复杂,尤其是在有网页版图形界面的时候——真的么?并不是!我所使用的那台交换机就挖了一个大坑。这台交换机大约长这个样子,有48个以太网端口,分为两排,每排24个。端口序号是纵向排布的,也就是说,左上角的端口是1,而它下方的是2,它右侧的是3,如下所示:

| 1 | 3 | 5 | 7 |....
| 2 | 4 | 6 | 8 |....

服务器的三条网线,连接在端口246上。

而在链路聚合的配置页面,端口是这样排列的:

| 1  | 2  | 3  | 4  |....
| 25 | 26 | 27 | 28 |....

刚刚插完网线跑回来配置的我,毫无悬念地在这个页面上为252627配置了链路聚合,并在很长一段时间内搞不明白为何这个链路聚合组是down的状态!!!!!!!!!

所以Dell做这个界面的人脑子进水了么!!!

终于恍然大悟,解决了这个问题之后,我在服务器上启动了三个iperf3的server,然后同时用三台机器运行iperf3的client模式去测速。第一个客户端启动,112MB/s,很正常。第二个启动了,56MB/s。嗯?为什么会这样?

这里就是第二个坑。802.3ad使用Hash算法来选择用聚合中的某条物理链路来传输数据,而Hash的结果是有可能重复的。Dell的交换机提供了6种Hash依据,从MAC到IP,从Source到Dest,一应俱全。但是经过我的尝试,最好的结果似乎就是,三台客户端中的两台挤在同一个物理链路上,而第三台走另一个。

所以,最后,我选择了balance-alb。这个模式不需要交换机的支持,却能让上行/下行的数据量大体平均分配在三个链路上。

评论