参考链接
IPV6 && Happy Eyeballs - 腾讯云开发者社区-腾讯云 (tencent.com)https://cloud.tencent.com/developer/article/1561091
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:
curl支持配置--happy-eyeballs-timeout-ms
--happy-eyeballs-timeout-ms
: 当一个域名有 ipv4 和 ipv6 双栈地址当时候,curl 或者浏览器是怎么访问的?happy-eyeballs 算法是一个解决这个问题的简单方法:即优先用 ipv6,等几百 ms 后发现不行,再试 ipv4 地址,这个参数就是用来控制等待时间的
curl代码实现happy-eyeballs
Name
CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS - head start for IPv6 for happy eyeballs
Synopsis
#include <curl/curl.h> CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, long timeout);
Description
Happy eyeballs is an algorithm that attempts to connect to both IPv4 and IPv6 addresses for dual-stack hosts, preferring IPv6 first for timeout milliseconds. If the IPv6 address cannot be connected to within that time then a connection attempt is made to the IPv4 address in parallel. The first connection to be established is the one that is used.
The range of suggested useful values for timeout is limited. Happy Eyeballs RFC 6555 says "It is RECOMMENDED that connection attempts be paced 150-250 ms apart to balance human factors against network load." libcurl currently defaults to 200 ms. Firefox and Chrome currently default to 300 ms.
Default
CURL_HET_DEFAULT (currently defined as 200L)
Protocols
Example
CURL *curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); curl_easy_setopt(curl, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, 300L); curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); }