天天看点

grpc复用client连接

以前在调用grpc接口时,总要调用Dial函数来创建一个grpc的ClientConn,如果每次都要创建,那么开销代价是很大的。

grpc的ClientConn对象可以帮我们实现自动重连的机制,并且是并发安全的,因此可以定义一个全局的ClientConn,然后用到的时候就用这个连接。

下面是简易实现:

package delayqueue

import (
	"google.golang.org/grpc"
	"sync"
	"sync/atomic"
	"unsafe"
)

var (
	globalClientConn unsafe.Pointer
	lck              sync.Mutex
)

func GetClient(target string) (DelayQueueClient, error) {  //返回需要的client
	conn, err := GetConn(target)
	if err != nil {
		return (DelayQueueClient)(nil), err
	}
	return NewDelayQueueClient(conn), nil  //此处调用pb.go文件中生成的创建client的方法
}

func GetConn(target string) (*grpc.ClientConn, error) {
	if atomic.LoadPointer(&globalClientConn) != nil {
		return (*grpc.ClientConn)(globalClientConn), nil
	}
	lck.Lock()
	defer lck.Unlock()
	if atomic.LoadPointer(&globalClientConn) != nil { //double check
		return (*grpc.ClientConn)(globalClientConn), nil
	}
	cli, err := newGrpcConn(target)
	if err != nil {
		return nil, err
	}
	atomic.StorePointer(&globalClientConn, unsafe.Pointer(cli))
	return cli, nil
}

func newGrpcConn(target string) (*grpc.ClientConn, error) {
	conn, err := grpc.Dial(
		target,
		grpc.WithInsecure(),
	)
	if err != nil {
		return nil, err
	}
	return conn, nil
}