通常我们想知道自己的机器和目的机器之间的网络被阻塞了,我们通常会执行Ping命令。
一般来说,对于一个状况良好的网络,你可以看到它对应的丢失丢包率是0%,也就是说可以Ping通。如果看到丢包率是100%,说明Ping失败。
Ping正常。
Ping不通
所以问题来了。假设我可以Ping一台机器,那么如果我切换到TCP来发送数据到目的机器,它会工作吗?
或者换个说法,Ping和tcp走的网络路径是一样的吗?
这时候第一反应就不一定了,因为Ping后中间链路的一个路由器可能会挂掉,然后用TCP连接会走另一条路。
也没错。但是假设中间环节没有变化呢?
我就说答案吧。
不一定,有可能是走的网络路径不一样。
今天就来说说为什么。
Ping和TCP消息传递的区别
我们知道网络是分层的,每一层都有相应的协议。
五层网络协议对应的消息体变化分析
这个网络层就像积木一样,上层协议基于下层协议。
Ping和tcp本质上都是基于网络层IP协议的包,但是到了物理层都是二进制01串,通过网卡发出去。
如果网络环境没变,目的地也一样,按理说他们走的网络路径应该是一样的。什么情况下会不一样?
先说路由的话题。
网络路径
在我们的想象中,当我们想要在两台机器之间传输数据时。将在本地机器和目的机器之间建立连接,就像管道一样,数据从一端流向另一端。这个管道实际上是一个抽象的概念,方便我们理解。
事实上,我们从本地网卡发送数据包后,它会经过各种路由器,然后到达目的机器。
这些路由器数量众多,可以互相连接。连接起来之后,它们就像一张大网,所以可以说“网”是一个非常生动的形象。
路由器网络
考虑到交换机的所有功能,路由器基本都支持,这里只讨论路由器。
那么现在问题来了。路由器收到数据后,怎么知道应该走哪条路径,发送给哪台路由器?
是什么决定了路径?
在这样一个大型网络中,任何路由器都可以采用任何路径向另一台路由器发送数据。
但是路由之间的距离,带宽等等可能是不一样的。
所以非常有必要知道两点之间哪条路是最佳路径。
于是问题就变成了这样一个图形结构。每条边都有一个成本或权重,计算它上面任意两点之间的最短距离。
和Dijkstra路由器
这个时候,我想每个人的回忆都会涌上来。
这个问题我比较熟悉。这是我大学时候刷的Dijkstra算法。菊花的OJ笔测书也频频出现。我现在终于明白,为什么他们的笔测书上的图片题好像比其他大厂多,因为菊花厂是搞通信的,是个老路由器玩家。
路由表的生成
基于Dijkstra算法,封装了一种新的协议OSPF。
通过OSPF,路由器可以获得自己与网络图中其它点之间的最短距离,因此它知道数据包到达某一点时应采用哪条最佳路径。
将这些信息组合成一张表,也就是我们常说的路由表。
在路由表中,它记录了到达哪个IP需要哪个端口,以及采用此路径的成本。
您可以通过route命令查看它。
表格路线
路由表决定数据包路径。
在发送数据包的过程中,目的IP会被添加到网络层。
路由器会将此IP与路由表匹配。
然后,路由表会告诉路由器什么样的消息应该被转发到哪个端口。
比如说。
通过路由表转发数据
假设A要给d发消息,也就是在192.168.0.105/24,会给192.168.1.11/24发一条消息。
然后a会将消息发送到路由器。
路由器知道目的IP192.168.1.11/24,将其与路由表进行匹配,发现192.168.1.0/24在e2端口,于是会从e2端口发送报文,最终将报文发送到目的机器。
当然,如果在路由表中找不到,就调用默认网关,也就是从端口e1发送到IP192.0.2.1,这个路由器的路由表不知道去哪了。也许其他路由器有。
路由表匹配规则
在上面的例子中,路由表中只有一项匹配,所以必须是它。
但是条条大路通罗马。实际上,到达目的地肯定有很多路径。
如果路由表中有很多条目匹配,你会怎么做?
如果多个路由项可以到达目的地,则优先选择匹配长度较长的路由项。比如目的地是192.168.1.11,发现路由表中192.168.1.0/24和192.168.0.0/16都可以匹配,但显然前者的匹配长度更长,所以最后会取192.168.1.0/24对应的转发端口。
但是如果两个条目的匹配长度相同呢?
这取决于生成该路由表条目的协议。选择优先级高的那个。优先级越高,所谓的管理距离就越小。例如,由玩家动态匹配的静态路由是首选,由OSPF动态学习的条目是第二首选。
如果还是一样,看度量,其实就是路径成本费用。成本越小,越容易被选中。
路由器可以选择多条路由,但原则上,只有“一条”是最好的。到目前为止,我们都可以认为Ping和TCP采用相同的路径到达相同的目的地。
但是...
如果连路径成本都一样呢?也就是说,存在多条最优路径。
那就全部用上。
这就是所谓的等效多径,ECMP。
我们可以使用traceroute来查看链路中是否存在等效的多路径。
大家可以看到,中间几行有几个IP,这意味着在这一跳可以同时选择几个目的机器,说明这条路径支持ECMP。
ECMP有什么用?
使用等效多路径,我们可以增加链路带宽。
比如说。
没有ECMP时,只能选择一条路径。
从A点到B点,如果两条路径开销不同,带宽是1千兆。那么这个包必须选择成本低的那条路。如果这条路走不通,就走下面这条路。但无论如何,在同一时间,只有一个路径被使用。另一个闲置的时候就浪费了。有什么办法可以利用吗?
是的,如果它们两条路径的开销设置相同,它们将成为等价路由,然后中间的路由器将打开ECMP功能,以同时使用两条链路。带宽从1千兆变成了2千兆。可以在两条路径中随机选择数据。
使用ECMP,可以同时使用两个链接。
但这也带来了另一个问题。加剧了数据包无序。
本来我只用一条网络路径,数据是依次发出去的,不出意外的话也是依次到达。
现在两个包走两条路径,第一个包可能会晚一点到达。这是不正常的。
那么问题又来了。
无序有什么问题?
对于我们最常用的TCP协议,它是一个可靠的网络协议。这里所说的可靠性,不仅仅是保证数据能够发送到目的地,还要保证数据序列与原发送方相同。
实现也很简单。TCP对每个数据包进行编号。当数据到达接收端时,根据包号发现是乱序包,会将其丢入乱序队列对包进行排序。如果前一个数据包还没有到达,即使后一个数据包先到达,也要在乱序队列中等待,直到到达,然后才能被上层拾取。
例如,发送方发出三个数据包,编号为1、2和3。假设传输层2和3先到达,但1还没有到达。这时候应用层就拿不到2和3的数据包了。它必须等待1的到来,然后应用层才能同时获得这三个数据包。因为这三个包本来可能代表一个完整的消息,如果少了一个,那么这个消息就是不完整的,应用层得到它是没有意义的。
像这样,由于前面的数据丢失,后面的数据无法及时发送到应用层的现象,就是我们常说的TCP队列头阻塞。
等待数据包到达的无序队列。
当出现乱序时,2和3需要留在乱序队列中,而乱序队列实际上使用的是接收缓冲区的内存,大小有限。您可以通过以下命令查看接收缓冲区的大小。
#检查接收缓冲区$ sysctlnet . IP v4 . TCP _ rmemnet . IP v4 . TCP _ rmem = 409687380(默认值)6291456(最大值)#缓冲区将在最小值和最大值之间动态调整。
乱序情况越多,接收缓冲区占用的内存就越多,对应的接收窗口就越小,这样正常可接收的数据就越少,网络吞吐量就越差,也就是性能越差。
所以我们需要尽量保证同一TCP连接下的所有TCP包都走同一条路径,最大程度的避免丢包。
ECMP的路径选择策略
当初启动ECMP是为了提高性能,现在却加重了无序,降低了TCP传输性能。
这怎么能容忍。
要解决这个问题,我们需要一个合理的路径选择策略。为了避免同一连接中数据包的无序,我们需要确保同一连接中的所有数据包都采用相同的路径。
这很好办。我们可以通过连接的五元组信息来定位唯一连接。
五倍的
然后为五元组信息生成一个哈希键,让哈希键相同的数据走同一条路,问题就完美解决了。
五个元组被映射成散列键。
根据五元组选择ECMP路径
TCP和Ping的网络路径一样吗?
现在我们回到文章开头的问题。
对于同一个发送方和接收方,TCP和Ping是否采用相同的网络路径?
肯定是不一样的,因为五元组中有一条信息是通信协议。Ping使用ICMP协议,与TCP协议不同,Ping不需要端口,所以不同的五元组,不同的生成哈希键,通过ECMP选择不同的路径。
TCP和Ping之间的五元组差异
使用相同的TCP协议。数据包是否采用相同的网络路径?
还是一样的发送方和接收方,一样的TCP协议。不同TCP连接采用的网络路径是否相同?
和上面的问题一样,其实是一个五重问题。它也是一种TCP协议。对于同一个发送方和接收方,它们的IP和接收方端口必须相同,但是发送方的端口可以随时改变,因此通过ECMP的路径也可能不同。
不同TCP连接的五元组差异
但是问题又来了。
知道这个有什么用?我是搞业务拓展的,但是没有权限设置网络路由。
使用该知识点解决问题。
对于业务拓展来说,这绝对不是一个没用的知识点。
如果有一天,你发现可以Ping通目的机器,但是用TCP连接,却偶尔连不上目的机器。而且两端的机器都挺闲的,不存在性能瓶颈。没有出路了。
你可以考虑一下。会不会是网络中使用了ECMP,某个环节出现了问题?
Ping成功,但某些TCP连接失败。
筛选方法也很简单。
您知道这台机器的IP和目的机器的IP和端口号,并且您知道您正在使用TCP连接。
只要在报错的时候打印错误信息,就知道发件人的端口号了。
那你就知道什么是五倍子了。
下一步是指定发送方的端口号重新发起TCP请求,同样的五元组,走同样的路径。按理说,如果链接有问题,肯定会重现。
如果不想修改自己的代码,可以用nc命令指定客户端端口,看看TCP连接能否正常建立。
-p 6666是指定请求客户端的端口是6666,后面是连接的域名和端口80。
通过nc成功建立了Tcp连接
假设你用端口6666的五元组总是连接失败,但是用端口6667或者其他端口都可以成功。你可以带着这些信息去找你负责网络的同事。
摘要
路由器可以通过OSPF协议生成路由表,使用数据包中的IP地址来匹配路由表,然后选择最佳路径进行转发。
当没有匹配的路由表时,将使用默认网关。匹配多个时,我们会先看匹配长度,如果相同,我们会看管理距离,如果相同,我们会看路径开销。如果连路径开销都相同,那么等价路径。如果打开ECMP进行路由,这些路径可以同时用于传输。
ECMP可以提高链路带宽,同时使用五元组作为哈希键进行路径选择,保证了相同连接的数据包走相同的路径,减少了乱序。
您可以通过traceroute命令检查链路上是否使用了ECMP。
在ECMP开启的网络链路中,TCP和Ping命令可能会走不同的路径,甚至是同一个TCP,不同连接走的路径也不一样,所以存在连接时好时坏的问题。这是真的绝望,所以考虑它是否与ECMP有关。
当然,遇到问题的时候要怀疑自己,要相信大多数时候真的与ECMP无关。
参考数据
网络故障排除案例课程-极客时间
郑重声明:此文内容为本网站转载企业宣传资讯,目的在于传播更多信息,与本站立场无关。仅供读者参考,并请自行核实相关内容。