acquireConn

文章插图
6
流程比较简单,如果当前 client.conns 数组 > 0,说明有空闲连接,直接取最后一个元素就好,这个元素一般是最近放进去的连接 。
releaseConn
func (c *HostClient) releaseConn(cc *clientConn) { cc.lastUseTime = time.Now() if c.MaxConnWaitTimeout <= 0 { c.connsLock.Lock() c.conns = append(c.conns, cc) c.connsLock.Unlock() return } // try to deliver an idle connection to a *wantConn c.connsLock.Lock() defer c.connsLock.Unlock() delivered := false if q := c.connsWait; q != nil && q.len() > 0 { for q.len() > 0 { w := q.popFront() if w.waiting() { delivered = w.tryDeliver(cc, nil) break } } } if !delivered { c.conns = append(c.conns, cc) }releaseConn 会先尽量尝试把当前的连接给正在等待连接的请求(wantConn),弹出等待队列(connsWait)的第一个元素 。并把连接转交给该请求 。如果该请求的状态已经不是 waiting 了,则继续弹出,直到找到了合适的来接盘,或者等待队列弹空 。如果没有顺利地把连接交出去,把当前连接入空闲连接数组(c.conns) 。
需要注意 fasthttp 里的 conns 是连接池,clientConnPool 是 clientConn 对象的对象池 。
与标准库中的 client 不同的是,fasthttp 中没有 read write loop,所以每个请求是在当前协程中完成的:
- 把 request 的 header 和 body 写入到 conn
- 从 conn 中读取 response
- 释放连接、缓存各种过程中生成的 struct 对象
客户端在 gRPC 中,客户端没有使用连接池,直接使用了 http2 连接:
Invoke-> invoke -> newClientStream -> newAttemptLocked -> getTransport -> blockingpiker.pick -> getReadyTransport -> addrConn.connect -> go ac.resetTransport()然后一路走到创建 http2Client 。(dlv) bt0 0x00000000013e2539 in google.golang.org/grpc/internal/transport.newHTTP2Client at /Users/xargin/go/src/google.golang.org/grpc/internal/transport/http2_client.go:1671 0x000000000145a5ca in google.golang.org/grpc/internal/transport.NewClientTransport at /Users/xargin/go/src/google.golang.org/grpc/internal/transport/transport.go:5752 0x000000000145a5ca in google.golang.org/grpc.(*addrConn).createTransport at /Users/xargin/go/src/google.golang.org/grpc/clientconn.go:12753 0x0000000001459e25 in google.golang.org/grpc.(*addrConn).tryAllAddrs at /Users/xargin/go/src/google.golang.org/grpc/clientconn.go:12054 0x00000000014593b7 in google.golang.org/grpc.(*addrConn).resetTransport at /Users/xargin/go/src/google.golang.org/grpc/clientconn.go:11205 0x000000000105b811 in runtime.goexit at /usr/local/go/src/runtime/asm_amd64.s:1357thriftthrift 官方没有连接池,client 中生成的 seqid 只是用来和服务端返回的 rseqid 进行匹配 。func (p *TStandardClient) Recv(iprot TProtocol, seqId int32, method string, result TStruct) error { rMethod, rTypeId, rSeqId, err := iprot.ReadMessageBegin() if err != nil { return err } if method != rMethod { return NewTApplicationException(WRONG_METHOD_NAME, fmt.Sprintf("%s: wrong method name", method)) } else if seqId != rSeqId { return NewTApplicationException(BAD_SEQUENCE_ID, fmt.Sprintf("%s: out of order sequence response", method)) } else if rTypeId == EXCEPTION { var exception tApplicationException if err := exception.Read(iprot); err != nil { return err } if err := iprot.ReadMessageEnd(); err != nil { return err } return &exception } else if rTypeId != REPLY { return NewTApplicationException(INVALID_MESSAGE_TYPE_EXCEPTION, fmt.Sprintf("%s: invalid message type", method)) } if err := result.Read(iprot); err != nil { return err } return iprot.ReadMessageEnd()}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 快充|等不及发布会!realme Q5i抢先开售:天玑810+5000mAh电池
- C语言的main函数的三个要点
- C语言的编译机制:分制原则与三种文件
- 微软承认Windows 10新BUG:错误显示没有网络连接
- MySQL 5.6--------SSL连接最佳实战
- GO 切片实力踩坑
- 无线投屏器怎么连接电视和手机?用手机怎么无线投屏到投影仪上?
- 我用 Go语言 生成的随机数为什么不随机?随机数是怎样产生的
- 什么是RPC?RPC有什么用?与语言有关吗?
- 华为b2手环与华为手机的连接方法
