Go创建Grpc链接池
转载请注明来源:https://janrs.com/2023/03/%e5%88%9b%e5%bb%bagrpc%e9%93%be%e6%8e%a5%e6%b1%a0/
常规用法
gRPC
四种基本使用
- 请求响应模式
- 客户端数据流模式
- 服务端数据流模式
- 双向流模式
常见的gRPC
调用写法
func main(){
//... some code
// 链接grpc服务
conn , err := grpc.Dial(":8000",grpc.WithInsecure)
if err != nil {
//...log
}
defer conn.Close()
//...some code
存在的问题:面临高并发的情况,性能问题很容易就会出现,例如我们在做性能测试的时候,就会发现,打一会性能测试,客户端请求服务端的时候就会报错:
rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial tcp xxx:xxx: connect: connection refused
实际去查看问题的时候,很明显,这是 gRPC 的连接数被打满了,很多连接都还未完全释放。[#本文来源:janrs.com#]
gRPC
的通信本质上也是 TCP
的连接,那么一次连接就需要三次握手,和四次挥手,每一次建立连接和释放连接的时候,都需要走这么一个过程,如果我们频繁的建立和释放连接,这对于资源和性能其实都是一个大大的浪费。
在服务端,gRPC
服务端的链接管理不用我们操心,但是 gRPC
客户端的链接管理非常有必要关心,要实现复用客户端的连接。
创建链接池
创建链接池需要考虑的问题:
- 连接池是否支持扩缩容
- 空闲的连接是否支持超时自行关闭,是否支持保活
- 池子满的时候,处理的策略是什么样的
创建链接池接口
type Pool interface {
// 获取一个新的连接 , 当关闭连接的时候,会将该连接放入到池子中
Get() (Conn, error)
// 关闭连接池,自然连接池子中的连接也不再可用
Close() error
//[#本文来源:janrs.com#]
Status() string
}
实现链接池接口
创建链接池代码
func New(address string, option Options) (Pool, error) {
if address == "" {
return nil, errors.New("invalid address settings")
}
if option.Dial == nil {
return nil, errors.New("invalid dial settings")
}
if option.MaxIdle <= 0 || option.MaxActive <= 0 || option.MaxIdle > option.MaxActive {
return nil, errors.New("invalid maximum settings")
}
if option.MaxConcurrentStreams