PS: Life and code are similar. Without reflection and iteration, growth cannot be achieved.
Recently, I came across the dual-stack problem. Let's briefly summarize the dual-stack and single-stack issues. Compared to IPv4, dual-stack client applications experience noticeable connection delays, which negatively impact the user experience. Let's learn about the dual-stack problem and its solutions. The main contents are as follows:
- Dual-stack selection problem
- Delay when IPv6 is inaccessible
- Happy Eyeballs
- Practical application
Dual-stack selection problem#
The dual-stack selection problem and the IPv6/IPv4 selection problem were first mentioned in the RFC1671 document. IPv6 (Internet Protocol version 6) is the sixth version of the Internet Protocol, while IPv4 (Internet Protocol version 4) is the fourth version. IPv6 primarily addresses the issue of IPv4 address exhaustion. The key enhancement of IPv6 is the expansion of the IP address space from 32 bits to 128 bits, fundamentally achieving unrestricted unique IP addresses. The dual-stack selection problem arises in the context of the rapid development of the Internet. In a dual-stack state, DNS resolution results in two types of addresses. In a single-stack state, DNS resolution results in either an IPv4 or IPv6 address, with IPv4 being the default in most cases.
Delay when IPv6 is inaccessible#
When IPv6 is inaccessible, programs that support IPv6 need to delay for a few seconds before switching to IPv4. This delay affects the user experience, and some systems choose to disable IPv6 to avoid impacting the user experience.
Reasons for IPv6 inaccessibility include no connection to the IPv6 Internet, broken 6to4 or Teredo tunnels, and broken IPv6 peering.
Let's take a look at the flowchart for IPv6 connection failure:
As shown in the above diagram, the client performs domain name resolution and obtains both IPv6 and IPv4 addresses. It first attempts to connect via IPv6, which fails, and then switches to IPv4 after a few seconds, resulting in the delay when IPv6 is inaccessible.
Happy Eyeballs#
RFC6555 defines an algorithm called Happy Eyeballs, which aims to reduce visible delays. The two main goals of Happy Eyeballs are as follows:
- Provide users with the ability to quickly connect via both IPv6 and IPv4, attempting to connect via IPv6 first and switching to IPv4 if the initial IPv6 connection fails.
- Avoid simultaneous connections to both IPv6 and IPv4, which could impact the network.
The following diagram illustrates the above concept:
As shown in the diagram, the client simultaneously sends two TCP SYN packets via both IPv6 and IPv4. If the IPv6 connection fails, the IPv4 connection succeeds, and the client retries the IPv6 connection until the user gives up and directly switches to IPv4.
After completing the above process, the client knows whether the IPv6 and IPv4 addresses have successfully connected. The client can cache the results to avoid impacting the network during subsequent connection attempts. In the example above, if the IPv6 connection fails, the client can directly switch to IPv4 for subsequent connections. The connection result cache can be set with a validity period, such as 10 minutes, and the connection status can be refreshed afterwards. This reduces the delay when IPv6 connections encounter exceptions and helps improve the user experience.
The following diagram illustrates a scenario where IPv6 is functioning properly:
As shown in the diagram, the client simultaneously sends two TCP SYN packets via both IPv6 and IPv4. Both IPv6 and IPv4 connections succeed, and the client directly uses IPv6 since it successfully connects, ignoring IPv4. The IPv6 connection status is also recorded, allowing direct IPv6 connections within the set validity period.
As long as the client host supports dual-stack, the Happy Eyeballs mechanism will always be present. As long as servers that only support IPv4 exist, Happy Eyeballs will continue to exist. Over time, IPv4 will gradually fade into history, and the implementation scenarios of Happy Eyeballs may vary, but they generally follow the requirements mentioned above.
Practical application#
The commonly used domain name resolution API in the application layer is as follows:
public static InetAddress[] getAllByName(String host)
The above method returns the IP addresses corresponding to the domain name "host". Based on whether the IP address is an IPv6 or IPv4 address, adaptation for the dual-stack problem can be implemented. The specific implementation can be adjusted and improved according to requirements. The Happy Eyeballs mechanism mentioned above mainly addresses the delay issue caused by dual-stack, and large-scale apps usually have their own corresponding algorithm implementations. Some even implement their own DNS. This provides a basic understanding in this regard.