事后我们得知,在 Router X 上有一条路由聚合配置。但是这条合理的路由聚合,怎么会让整个网段挂掉呢?
BGP 路由聚合
为什么需要路由聚合呢?
Router A 每次宣告一个网段给 Router X,Router X 的 BGP 路由就会多一个。Router B 每次宣告一个网段,X 上也会多一个。可想而知,Router X 上的路由是它的下游的总和。同理,Router X 上游的路由器的路由将会更多。路由的条目越多,对路由器的性能要求就越高。所以,核心路由器要想处理所有的路由条目,就需要性能非常高。性能是有上限的,假设性能再搞也无法处理这么多路由,怎么办呢?我们可以优化另一个变量——路由条目2。
如何减少路由条目呢? 考虑下面 3 个网段:
10.81.2.0/24
10.81.3.0/24
10.83.4.4/26
其实都可以汇聚成一个网段:10.81.0.0/16。把这个网段宣告出去,收到的流量可以在 X 这里根据自己的路由表进行转发。
Whether it’s working on a project, solving a difficult problem, or even refining soft skills like communication, the act of showing up and putting in the hours is essential. Practice makes perfect, but more so it’s all about progress rather than perfection. Each hour you spend iterating, refining, failing and retrying brings you closer to excellence. It doesn’t always feel that way in the moment but when you look back at what you did before, you will see your progress. And that act of looking back, and seeing how you improved, is immensely rewarding and in turn makes you enjoy your work.
这些路径使用 IP 地址的形式表示的。没有人能记住这么多 IP 地址,所以我们需要有意义的名字。我在公司里写了一个平台,集成了其他的二十多个系统,给一个 IP,能查询出来这个 IP 对应的网络设备,容器,物理机,虚拟机等等。
复制 IP 到这个系统中查看结果,还是有些不方便,于是就想能不能让 MTR 直接展示设备的名字。
MTR 支持 DNS PTR 反查,如果查到记录,会优先展示名字。这些名字在公网上通常没有什么意义。我们的内网 DNS 没有支持 PTR,所以这个 PTR 记录在默认的情况下也没有什么用。如果通过 DNS 系统来支持 PTR 记录的话,成本就有些大了,得对 DNS 做一些改造,DNS 又是一个比较重要的系统。那能不能有一个影响比较小的旁路系统来做到这个 feature 呢?
花了一天排查无果,问了朋友,最后发现这个问题:Goroutines cause deadlocks after fork() when run in shared library #155383,而且开发人员的回复是:This is to be expected. It’s almost impossible for multithreaded Go runtime to handle arbitrary forks.
如果一个数据类型需要占用多个 bytes,比如 32 位的 int,占用 4 个 bytes,那我们在编程的时候会用一个内存地址表示这个 int,从这个地址开始,后面一共 4 个 bytes,来表示一个 int。比如一个 16 进制表示的 int 值:0x01020304,其中 01 是 most significant bit,是重要的数字,因为它决定了整个数字的数量级是多大,可以把 01 叫做大头,如果把大头放在前面,即,表示成 0x01020304,这就是 Big Endian. 如果把大头放在这 4 个 bytes 的最后,即,表示成 0x04030201,那就是 Little Endian.
一般来说,这对于程序员是透明的,因为处理 endian 的是 CPU,把数据写入内存的是 CPU,从内存取出来的还是 CPU。所以不管 CPU 是 Little Endian 还是 Big Endian,只要它始终保持一致,就可以了。
但是如果涉及到网络的序列化(其实不仅仅是网络,数据只要离开本机,就涉及 endianness),问题就来了。一个 CPU 序列化成 Little Endian,通过网络传输给另一个机器,另一个机器的 CPU 是 Big Endian,那不就乱套了吗?(现代的大部分 CPU 是 Little Endian, 网络使用 Network Byte order,是 Big Endian。)
所以这里就需要一个转换,libc 提供了两个转换函数:
htons: Host byte order 转换成 Network byte order
ntohs: Network byte order 转换成 Host byte order
两个误解:
「Endian 是 bit 级别的。」这是错误的,Endian 是 byte 级别的。假如一个数据格式只有 8 个 bit,那么无论是 Little Endian 还是 Big Endian,这 8 个 bit 的表示方法都不会变。也没有 Endian 转换的必要。(有些情况下,同一个 byte 内,编译器也会考虑 endianness,见评论2)