IPV6 && Happy Eyeballs
- 2019 年 12 月 27 日
- 笔记
什么是IPV6
网际协议第6版(英语:Internet Protocol version 6,缩写:IPv6)是网际协议的最新版本,用作互联网的网络层协议。用它来取代IPv4主要是为了解决IPv4地址枯竭问题,同时它也在其他方面对于IPv4有许多改进。IPv6的设计目的是取代IPv4,然而长期以来IPv4在互联网流量中仍占据主要地位,IPv6的使用增长缓慢。在2017年7月,通过IPv6使用Google服务的用户百分率首次超过20%。参考维基百科
option |
ipv4 |
ipv6 |
---|---|---|
地址长度 |
32bit |
128bit |
地址空间 |
2^32 |
2^128(约3.4×1038) |
表达形式 |
4个8进制表示 |
分为8组,每组以4位十六进制 |
简单来说,IPV6是IPV4的下一代ip协议标准,地址更长,地址空间更大,大部分设备都可以分配一个ipv6地址。
Happy Eyeballs跟IPV6有什么关系
ipv4 如何平滑地切换到 ipv6 呢?
如果以彻底推翻 ipv4 的方式进行推广 ipv6 ,那这个推进是无法落地,因为 ipv6 并不能带来实质性的优势,反而增加了成本。
在双栈的网络环境中,一次DNS请求可能获取到2个地址( ipv4 和 ipv6 ),而应该选用哪个?优先使用 ipv6 ,有可能降低服务质量,因为大部分服务还没完全支持 ipv6 ,优先选用 ipv4 ,那无法达到推广 ipv6 的效果。
The dual-stack code may get two addresses back from DNS; which
does it use? During the many years of transition the Internet
will contain black holes. For example, somewhere on the way from
IPng host A to IPng host B there will sometimes (unpredictably) be
IPv4-only routers which discard IPng packets. Also, the state of
the DNS does not necessarily correspond to reality. A host for
which DNS claims to know an IPng address may in fact not be
running IPng at a particular moment; thus an IPng packet to that
host will be discarded on delivery. Knowing that a host has both
IPv4 and IPng addresses gives no information about black holes. A
solution to this must be proposed and it must not depend on
manually maintained information. (If this is not solved, the
dual-stack approach is no better than the packet translation
approach.)
为此,有人提出了一个折衷的办法,Happy Eyeballs算法。
Happy Eyeballs算法
Happy Eyeballs是一个应用于网络双栈环境的算法,于2011年被提出。
Happy Eyeballs有两个主要目标:
- 赛马机制,从 ipv4 和 ipv6 中为用户选择一个最快的链接;
- 避免同时对两地址发起请求,造成网络破坏。
访问一个 Ipv6 的网站的过程是这样的:
通过 DNS 的 AAAA 解析获取到了域名对应的 Ipv6 的地址,然后就会通过 Ipv6 的地址访问网站,如果访问不通,业务就会挂掉,导致用户访问失败。
如果这个网址只支持 Ipv6 ,那就是这种现象。如果网址本身支持双栈,即同时支持 Ipv4 和 Ipv6 ,那么在某些环境下,会启用 Happy Eyeballs 算法,进行快速回退,使用 Ipv4 进行访问。
这样避免让大家担心使用 Ipv6 后如果网络不通,用户流失。
Happy Eyeballs 可以理解为对 ipv6 请求失败时的降级方案。
Happy Eyeballs具体原理
对于支持双栈的网络环境下,当访问一个网站时,会同时发起 AAAA 和 A 的 DNS 查询请求,并对获取的结果进行排列,优先 Ipv6 ,然后进行 Ipv6 的链接尝试,在大概 200ms 后如果链接不通,立即启用下一个 ip 的链接请求,一般就是 Ipv4 了。
在这种场景下,就不要担心由于 Ipv6 的网络连通性比较差而导致站点无法访问了,即使在当前国内各运营商 Ipv6 连通性比较差的情况下,多的就是一个大概 200ms 的延迟,跟拒绝服务比起来,还算能接受。
两种访问场景如下,参考RFC 6555:


What's more
happy eyeballs 的思路可以应用于我们开发的应用中。
一般情况下,一个域名解析会有多个A记录,DNS 使用 round-robin 返回ip地址集合;当启用 ipv6 以后,DNS 则返回一个特定顺序的地址集合(参考这里);开发人员可能会采用 getaddrinfo() + looping over addresses and try connect() 的方法,轮询找到合适的连接地址。
轮询有个缺点,当地址集合第一个 ip 挂掉后,需要拥塞一段时间才会尝试连接第二个 ip,用户体验下降。
在这种情况,一个更优的做法是,启动两个线程分别访问 ipv4 和 ipv6,或者使用非拥塞的单进程(协程)同时发起connect,当获取到最快的一个响应后,拥塞其他响应。
这样就是使用赛马的方法获取最优连接。