涉及结构体
- Client、Transport、Dailer、Request、Resolver
Request
- ctx context.Context 可以设置超时时间
Client
- Timeout:整体超时设置,与Request的ctx取较小超时时间
Transport
- TLSHandshakeTimeout:tls握手的超时时间,通过AfterFunc实现,超时后,直接返回tlsHandshakeTimeoutError
- DisableKeepAlives:如果为true,不会有conn连接池,每次都是开启新连接,不会进行连接复用,与TCP的keep-alive没有关系
- persistConn的readLoop和writeLoop一个进行读数据,一个写数据
- MaxResponseHeaderBytes:获取返回的Header最大值,默认值为10M,返回的body没有限制,在persistConn里的Read函数实现
- IdleConnTimeout:conn放入Idle池中后,IdleConnTimeout时间仍未使用,直接关闭,通过TimeAfter函数执行关闭函数closeConnIfStillIdle。DefaultTransport里面给的是90s。默认是使用连接池,90s后没有使用就关闭连接
persistConn
-
br和bw对应底层的persistConn和persistConnWriter,一个是reader,一个是writer。
readLoop
-
bodyEOFSignal:封装response,br读取完后,返回EOF的error,然后执行bodyEOFSignal的fn函数,然后通过waitForBodyRead信号量,将isEOF的信号传递给bodyEOF,执行一下代码,tryPutIdleConn确认是否退出for循环DisableKeepAlives为true和MaxIdleConnsPerHost,返回false,退出for循环
select { case bodyEOF := <-waitForBodyRead: replaced := pc.t.replaceReqCanceler(rc.cancelKey, nil) // before pc might return to idle pool alive = alive && bodyEOF && !pc.sawEOF && pc.wroteRequest() && replaced && tryPutIdleConn(trace) if bodyEOF { eofc <- struct{}{} } ... }
-
退出循环,会通过defer close persistConn
-
Dialer
-
Timeout:获取conn的超时时间,与Request的ctx取较小超时时间。一般TCP的超时一般是3分钟
-
DialContext
-
先使用Resolver进行域名解析
-
多个地址,每个连接的超时时间是平分的,通过partialDeadline实现
-
TCP实现dialTCP
-
UDP实现dialUDP
-
IP实现dialIP
-
socket连接超时使用的ctx
-
Keepalive参数:keepalive通过系统调用,将句柄设置keepalive的超时时间。keepalive开启分为
两步
- 通过系统调用将句柄的SO_KEEPALIVE字段设置为true
- 通过系统调用设置超时时间,设置TCP_KEEPINTVl字段和TCP_KEEPIDLE字段,TCP_KEEPINTVl默认为15,linux系统为75,TCP_KEEPIDLE默认为15s
- 涉及字段为KeepAlive、tcp_keepalive_time、tcp_keepalive_intvl、tcp_keepalive_probes
- KeepAlive:是否开启keepalive这一功能选项
- tcp_keepalive_time:tcp可以保持的空闲时间,即发送一次探针成功后,可以保证这个TCP这么长的时间是活的
- tcp_keepalive_intvl:探针发送的周期
- tcp_keepalive_probes:如果tcp_keepalive_time这么久没有收到探针,则再发送tcp_keepalive_time次数探活测试包包,如果都失败,则表明这个TCP连接已经挂了
-
Resolver
- lookupIPAddr:获取IP地址数组
- parseIPZone直接解析ip地址,不走dns
- 实际调用的函数为lookupIP
- PreferGo默认为false,实际最后都是调用goLookupIPCNAMEOrder,两种方式直接获取的order的不太一样
- prefergo
- true:只从systemConf里面获取Oder
- false:先从systemConf里面获取Oder,如果为hostLoopupCgo,则Cgo的方式获取
- 读取/etc/nsswitch.conf、/etc/resolv.conf和/etc/mdns.allow
- order有下面几种类型
- hostLookupCgo
- hostLoopupFilesDNS
- hostLoopupDNSFiles
- hostLoopupFiles
- hostLoopupDNS
- goLoopupIPCNAMEOrder
- 域名最大长度255
- 可以通过配置resolv.conf的useTCP强制使用TCP,否则先通过udp获取,获取不到再使用tcp
- dns的超时时间默认为5s,如果在resolv.conf配置了,使用配置中的
- 调用远端的dailer也是Dialer
- prefergo
TLS
- persistConn.addTLS:添加tls
- 握手
- clientHandshake
- serverHandshake