Skip to content

Conversation

wlnxing
Copy link

@wlnxing wlnxing commented Sep 2, 2025

Description / 描述

这个 PR 将部分驱动用到的http client 优先使用ipv6,如果ipv6连接超时(1s)或者失败了则回退到ipv4连接

Motivation and Context / 背景

背景

现有的go http client如果连接的地址是ipv6和ipv4解析同时存在时,采取的是谁先解析到地址,就先对谁连接。

目前观察到,所有的双栈地址都是使用的ipv4连接。

好处

  1. 目前大部分ipv6的路由没有ipv4拥挤
  2. 部分地区的ipv6上传没有限制,使用ipv6上传文件会更快。特别是这个PR只更改了各个文件drive部分的http client, 不会影响到其他部分。

How Has This Been Tested? / 测试

以139云盘为例,139云盘在分块上传文件时会调用到NewHttpClient, 然后查看debug级别的日志

本地没有ipv6环境:

image

有ipv6环境优先连接ipv6:

image

Checklist / 检查清单

  • I have read the CONTRIBUTING document.
    我已阅读 CONTRIBUTING 文档。
  • I have formatted my code with go fmt or prettier.
    我已使用 go fmtprettier 格式化提交的代码。
  • I have added appropriate labels to this PR (or mentioned needed labels in the description if lacking permissions).
    我已为此 PR 添加了适当的标签(如无权限或需要的标签不存在,请在描述中说明,管理员将后续处理)。
  • I have requested review from relevant code authors using the "Request review" feature when applicable.
    我已在适当情况下使用"Request review"功能请求相关代码作者进行审查。
  • I have updated the repository accordingly (If it’s needed).
    我已相应更新了相关仓库(若适用)。

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR modifies the HTTP client used by various file drives to prefer IPv6 connections over IPv4, implementing a fallback mechanism that retries with IPv4 if IPv6 connection fails or times out within 1 second.

  • Adds custom DialContext to prioritize IPv6 connections with 1-second timeout
  • Implements IPv4 fallback when IPv6 connection fails
  • Adds debug logging to track connection type selection

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +291 to +310
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
mainDialer := &net.Dialer{}

// 优先尝试IPv6连接
if network == "tcp" {
ipv6Context, cancel := context.WithTimeout(ctx, 1*time.Second) // 缩短IPv6尝试时间
defer cancel()

ipv6Conn, err := mainDialer.DialContext(ipv6Context, "tcp6", addr)
if err == nil {
log.Debugf("Connected via IPv6: %s", ipv6Conn.RemoteAddr().String())
return ipv6Conn, nil
}

// 如果IPv6连接失败,回退到IPv4
log.Debugf("IPv6 connection failed, falling back to IPv4: %v", err)
return mainDialer.DialContext(ctx, network, addr)
}
return mainDialer.DialContext(ctx, network, addr)
},
Copy link
Preview

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded 1-second timeout should be extracted as a named constant to improve maintainability and make it configurable. Consider defining const ipv6ConnectTimeout = 1 * time.Second at the package level.

Copilot uses AI. Check for mistakes.

@@ -287,6 +288,26 @@ func NewHttpClient() *http.Client {
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{InsecureSkipVerify: conf.Conf.TlsInsecureSkipVerify},
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
mainDialer := &net.Dialer{}
Copy link
Preview

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a new net.Dialer instance on every connection is inefficient. Consider creating a shared dialer instance outside the DialContext function or reuse the default dialer configuration.

Copilot uses AI. Check for mistakes.

@ljcbaby
Copy link
Contributor

ljcbaby commented Sep 2, 2025

在 Go 的 net/http 客户端中,默认对双栈(IPv4/IPv6)连接的处理方式就是使用所谓的 RFC 6555 Happy Eyeballs 策略,配合 RFC 6724 的地址选择规则。

@ILoveScratch2
Copy link
Member

不应在 DialContext 函数中硬编码地址族选择逻辑,这不是数据结构问题,而是控制流问题,也不应为network == "tcp"单独处理,不利于结构
并且并不应强制IPv6,且Go标准net已经内置IPv6智能双栈连接,目前没有发现明显问题,如果真有问题,应该配置网络栈,而不是破解应用层

应使用系统级别的网络配置来解决

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants