除此之外,h2 的 connpool 和 h1 的没什么区别 。
从 idleConn 数组中获取 idle 连接时:
func (t *Transport) queueForIdleConn(w *wantConn) (delivered bool) { if delivered { if pconn.alt != nil { // HTTP/2: multiple clients can share pconn. // Leave it in the list. } else { // HTTP/1: only one client can use pconn. // Remove it from the list. t.idleLRU.remove(pconn) list = list[:len(list)-1] } }
把使用完的连接放回连接池时:
// HTTP/2 (pconn.alt != nil) connections do not come out of the idle list, // because multiple goroutines can use them simultaneously. // If this is an HTTP/2 connection being “returned,” we're done. if pconn.alt != nil && t.idleLRU.m[pconn] != nil { return nil } if pconn.alt == nil { // HTTP/1. // Loop over the waiting list until we find a w that isn't done already, and hand it pconn. for q.len() > 0 { w := q.popFront() if w.tryDeliver(pconn, nil) { done = true break } } } else { // HTTP/2. // Can hand the same pconn to everyone in the waiting list, // and we still won't be done: we want to put it in the idle // list unconditionally, for any future clients too. for q.len() > 0 { w := q.popFront() w.tryDeliver(pconn, nil) } }
- 如果 LRU 列表非空,说明当前没有等待的 goroutine,而在获取 http2 连接时,并没有把连接从连接池中真地拿走,所以直接返回就行了 。
- 如果 LRU 列表为空,这条可能是新建的连接,需要把 waitqueue 弹到空,并把当前这条连接放进连接池 。
fasthttp 的 server 端使用 worker pool 来进行 goroutine 复用,不会频繁创建新的 g 。
workerPool.workerFunc 就是每个 worker 的主循环:
func (wp *workerPool) workerFunc(ch *workerChan) { var c net.Conn for c = range ch.ch { if c == nil { break } wp.WorkerFunc(c) } wp.lock.Lock() wp.workersCount-- wp.lock.Unlock()}
每次 serve 新的 conn 时:- 从 workerpool 中获取一个 worker,没有就新建,启动 workerFunc 主循环,监听 worker channel 。
- 把当前 serve 的新连接发送到 worker channel
- workerFunc 获取到新 conn,即开始请求处理流程 。执行 fasthttp.Server.serveConn
type HostClient struct { // Maximum number of connections which may be established to all hosts // listed in Addr. // // You can change this value while the HostClient is being used // using HostClient.SetMaxConns(value) // // DefaultMaxConnsPerHost is used if not set. MaxConns int // Keep-alive connections are closed after this duration. // // By default connection duration is unlimited. MaxConnDuration time.Duration // Idle keep-alive connections are closed after this duration. // // By default idle connections are closed // after DefaultMaxIdleConnDuration. MaxIdleConnDuration time.Duration // Maximum number of attempts for idempotent calls // // DefaultMaxIdemponentCallAttempts is used if not set. MaxIdemponentCallAttempts int // Maximum duration for waiting for a free connection. // // By default will not waiting, return ErrNoFreeConns immediately MaxConnWaitTimeout time.Duration clientName atomic.Value lastUseTime uint32 connsLock sync.Mutex connsCount int conns []*clientConn connsWait *wantConnQueue}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 快充|等不及发布会!realme Q5i抢先开售:天玑810+5000mAh电池
- C语言的main函数的三个要点
- C语言的编译机制:分制原则与三种文件
- 微软承认Windows 10新BUG:错误显示没有网络连接
- MySQL 5.6--------SSL连接最佳实战
- GO 切片实力踩坑
- 无线投屏器怎么连接电视和手机?用手机怎么无线投屏到投影仪上?
- 我用 Go语言 生成的随机数为什么不随机?随机数是怎样产生的
- 什么是RPC?RPC有什么用?与语言有关吗?
- 华为b2手环与华为手机的连接方法