go源码阅读:net/http的Transport
Transport是RoundTripper接口的实现: func RoundTrip(req *Request) (*Response, error)
Transport对外只提供方法: func RoundTrip(req *Request) (*Response, error)
Transport的内部对象idleLRU connLRU写得不错, 简单实现了LRU
http.Client就是在Tranport上简单封装一层
Transport就是一个连接池, 池子里面放着persistConn连接对象(idleConn map[connectMethodKey][]*persistConn)
queueForIdleConn: 根据请求的connectMethodKey从t.idleConn获取一个[]*persistConn切片, 并从切片中,根据算法获取一个有效的空闲连接。如果未获取到空闲连接,则将wantConn结构体放入t.idleConnWait[w.key]等待队列
连接释放逻辑在 (t *Transport) tryPutIdleConn(pconn *persistConn)
- 哪些情况才回去调 tryPutIdleConn:
- 大部分的异常情况
- responseBody read完: 代码详细见 case bodyEOF := <-waitForBodyRead
dialConnFor: 会调用t.dialConn获取一个真正的*persistConn。并将这个连接传递给w, 如果w已经获取到了连接,则会传递失败,此时调用t.putOrCloseIdleConn将连接放回空闲连接池。
dialConn:
- 调用t.dial(ctx, “tcp”, cm.addr())创建TCP连接并将其赋予刚new的persistConn
- 如果是https的请求,则对请求建立安全的tls传输通道
- 为persistConn创建读写buffer,如果用户没有自定义读写buffer的大小,读写bufffer的大小默认为4096
- 执行go pconn.readLoop()和go pconn.writeLoop()开启读写循环然后返回连接
dialConn里面这段代码是开启http2的核心
阅读更多