感谢各位热情读者朋友的大力支持这篇文章,交流群的一位读者这么说的:“一台电脑有一块无线网卡、一个有线网卡,连在同一个网络里,一点事没有,上网正常”。
他是对的,电脑允许两块网卡配置同一个网段地址,比如192.168.1.x/24。这两块网卡其实没有任何关联性。如果你把电脑看成一个流量的蓄水池,这两块网卡就是两个出口(outgoing traffic),或者两个进口(incoming traffic)。称它们为A口(wired)、B口(wireless)。
蓄水池是如何负载均衡的?
-
流量全部从A口流出
-
流量全部从B口流出
-
流量一半从A口流出,剩下一半从B口流出
计算机操作系统,对于不同类型的接口,有自己的喜好。认为可靠性高的物理接口,有更高的优先级,在路由选路算法中占据优势。那么这种优先级用什么来衡量呢?
用Metric,Metric越小,说明优先级越高,路由算法里优先选择。大家来看一张路由表:
路由表的最后一栏,就是metric,最小的metric =35,最大的metric = 331。但是在这张路由表里metric没有多大意义。因为任何一个路由条目只有一个表项,比如:0.0.0.0/0,这是一条指向Internet的路由,就这一条路由,无论metric多少,只有这一种选择。
回到主题上来,A口与B口谁的优先级高呢?
A口的优先级高,通常有线口的丢包率、延迟性能都优于无线口,所以metric会更小,那么路由算法就会优选A口。流量会全部从A口进出。
可以手动将B口metric值修改得比A口小,让流量优先从B口进出?
当然是可以的。
可以将A、B口的metric 修改成一样的,让流量一半从A口出,一半从B口出?
当然也是可以的。这里要敲黑板了,这就是上篇文章里提到的ECMP(Equal Cost Multiple Path),这是一种统计学意义上的负载均衡。
什么是统计学意义上的负载均衡?
当有多条ECMP等价路由(Metric相等)时,是将流量平均分配到每一条链路(出口)上去吗?
并不是!为什么不这么做呢?
这样就把同一个session的流量平均分摊到多条链路,造成的潜在后果是,后发的报文先到,造成乱序。而乱序的后果挺严重,在报文的接收方眼里,乱序和丢包几乎没有差别。会触发发送方重传乱序的报文,一旦发送方开始重传,伴随的是流量降速,从而影响session的整体性能。
那么,如何保证同一个session的流量走同一条链路?
你在浏览器打开一个网站,浏览一副图片,这就是一个session。
一个session的四元组通常是一样的,这四元组分别是:
-
源IP
-
目的IP
-
源端口
-
目的端口
将一个session的四元组做为输入参数,运行一个Hash函数,得出的值是不是都是一样的?
Hash函数,和高中一年级学习到的函数并没有本质的差别。输入值相同,得出的输出值也会相同,这就是函数。
digest = hash(source ip, source port, destination ip,destination port)
假设现在有2条ECMP链路,用digest (digest为正整数)除以2,得到的余数只有两种可能:
-
0
-
1
将余数为0对应的digest所代表的session,流量分摊到A接口。
将余数为1对应的digest所代表的session,流量分摊到B接口。
假设现在有3条ECMP链路,用digest 除以3,得到的余数只有三种可能:
-
0
-
1
-
2
将余数为0对应的digest所代表的session,流量分摊到A接口。
将余数为1对应的digest所代表的session,流量分摊到B接口。
将余数为2对应的digest所代表的session,流量分摊到C接口。
无论有多少条链路,采用以上算法依此类推,即可算出分摊到的物理链路。
如果朋友们觉得这篇文章有点帮助,可以转发给您的朋友一起看。如果文章统计意义上的数据达到心里的预期,会在下一篇文章里写“会员专享”内容,这些内容和ECMP高度相关,里面包含有多年排错的积累,这些内容只会在Kirin博客和交流群里分享,感谢各位朋友的阅读!