first commit
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 全局单例变量
|
||||
var (
|
||||
once sync.Once // 保证初始化只执行一次
|
||||
globalClient *http.Client // 复用的 HTTP Client 实例
|
||||
)
|
||||
|
||||
// InitHttpClient 初始化全局 HTTP Client(手动调用,可选)
|
||||
// 配置连接池参数,优化连接复用
|
||||
func InitHttpClient() {
|
||||
once.Do(func() {
|
||||
// 核心:配置 Transport(连接池核心参数)
|
||||
transport := &http.Transport{
|
||||
// 全局最大空闲连接数(避免连接数过多)
|
||||
MaxIdleConns: 100,
|
||||
// 空闲连接超时时间(超时后关闭,释放资源)
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
// 每个目标主机的最大空闲连接数(避免单主机占用过多连接)
|
||||
MaxIdleConnsPerHost: 10,
|
||||
MaxConnsPerHost: 20, // 新增:每个目标主机的最大并发连接数(防止打满服务器)
|
||||
// 禁用压缩(根据业务需求调整,比如调用微信接口可开启)
|
||||
DisableCompression: false,
|
||||
// TCP 连接建立超时(防止连接挂死)
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 10 * time.Second, // 连接建立超时
|
||||
KeepAlive: 30 * time.Second, // TCP 保活时间(维持长连接)
|
||||
}).DialContext,
|
||||
// TLS 握手超时(HTTPS 场景必配)
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
/// 等待响应头的超时
|
||||
ResponseHeaderTimeout: 15 * time.Second,
|
||||
}
|
||||
|
||||
// 构建 HTTP Client
|
||||
globalClient = &http.Client{
|
||||
Timeout: 20 * time.Second, // 整个请求的超时(连接+读取+写入)
|
||||
Transport: transport,
|
||||
// 可选:禁用自动重定向(根据业务需求,比如微信接口无需重定向)
|
||||
// CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
// return http.ErrUseLastResponse
|
||||
// },
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// GetClient 获取全局 HTTP Client 实例(推荐使用此方法调用)
|
||||
// 懒加载:如果未初始化,自动触发初始化
|
||||
func GetClient() *http.Client {
|
||||
InitHttpClient() // 兜底:确保初始化
|
||||
return globalClient
|
||||
}
|
||||
Reference in New Issue
Block a user