目录
-
-
- 1. **本地端口耗尽(最常见原因)**
- 2. **网络配置问题**
- 3. **DNS或IP解析问题**
- 4. **系统资源限制**
- 排查步骤总结:
-
在Go语言中遇到 dial tcp 10.1.68.88:3306: connect: cannot assign requested address
错误,通常是由以下原因导致的:
1. 本地端口耗尽(最常见原因)
- 问题本质:当客户端频繁创建TCP连接时,操作系统会为每个连接分配一个临时端口(Ephemeral Port)。如果短时间内创建大量连接,端口资源会被耗尽。
- 触发场景:
- 高并发请求数据库且未复用连接(如未使用连接池)。
- 代码中频繁创建/关闭数据库连接(如每次查询都开新连接)。
- 验证方法:
# Linux/Mac: 查看TIME_WAIT状态的连接数 netstat -an | grep :3306 | grep TIME_WAIT | wc -l # 查看系统可用端口范围 sysctl net.ipv4.ip_local_port_range # 典型值:32768-60999(约2.8万个端口)
- 解决方案:
- 使用连接池:确保复用数据库连接(推荐
sql.DB
自带连接池):db, _ := sql.Open("mysql", "user:pass@tcp(10.1.68.88:3306)/db") db.SetMaxOpenConns(100) // 限制最大连接数 db.SetMaxIdleConns(20) // 保留空闲连接 defer db.Close()
- 扩大端口范围(临时缓解):
sudo sysctl -w net.ipv4.ip_local_port_range="1024 65000"
- 启用端口复用(Linux):
sudo sysctl -w net.ipv4.tcp_tw_reuse=1
- 使用连接池:确保复用数据库连接(推荐
2. 网络配置问题
- 路由/防火墙限制:本地网络策略阻止访问目标IP。
- 检查防火墙规则:
iptables -L -n # Linux
- 检查防火墙规则:
- 目标服务器限制:
- MySQL服务未运行:确认
10.1.68.88:3306
的MySQL服务已启动。 - 服务器防火墙:确保目标服务器开放3306端口。
- MySQL绑定地址:检查MySQL的
bind-address
配置(非127.0.0.1
)。
- MySQL服务未运行:确认
3. DNS或IP解析问题
- 临时性DNS故障导致IP不可达。
- 尝试直接使用IP连接(如代码中已是IP,跳过此步)。
- 检查本地DNS配置:
cat /etc/resolv.conf
。
4. 系统资源限制
- 文件描述符不足:操作系统限制单个进程的TCP连接数。
- 检查限制:
ulimit -n
- 临时提升:
ulimit -n 65535
- 检查限制:
排查步骤总结:
- 优先检查连接池:确保代码中复用数据库连接(80%问题根源)。
- 验证网络连通性:
telnet 10.1.68.88 3306 # 测试端口 ping 10.1.68.88 # 测试基础连通性
- 监控端口使用:
ss -s | grep "TCP:" # 查看总TCP连接数 netstat -ant | grep :3306 # 查看目标连接状态
- 检查系统日志:
dmesg | grep "TCP" # 查看内核级网络错误
关键建议:
在Go中务必使用database/sql
的连接池(通过sql.Open()
+ 配置参数),避免在循环/高频请求中重复Open/Close
连接。连接池会自动管理连接的复用和生命周期,从根本上解决端口耗尽问题。