最近有一个项目在用go语言重构,重构完项目表现很好,好记性不如烂笔头,其中遇到的问题记录下来,用到的组件记录下来
thrift pool 实现const DEFAUL_TTIMEOUT = 300 * time.Millisecond type ThriftPool struct { Timeout time.Duration MaxIdleConns int mutex sync.Mutex freeconn []*Thrift socket Addr string } type ThriftSocket struct { time time.Time tSocket *thrift.TSocket err error } func New(addr string) *ThriftPool { server := ThriftPool{} server.Addr = addr return &server } func (pool *ThriftPool) NetTimeOut() time.Duration { if pool.Timeout != 0 { return pool.Timeout } return DEFAUL_TTIMEOUT } func (socket *ThriftSocket) SetErr(err error) { socket.err = err } func (socket *ThriftSocket) GetSocket()*thrift.TSocket { return socket.tSocket } // release returns this connection back to the client's free pool func (pool *ThriftPool) Release(socket *ThriftSocket) { pool.mutex.Lock() defer pool.mutex.Unlock() //有错直接关闭服务 if socket.err != nil { libs .Logger.Info("thrift_pool", zap.String("release err", socket.err.Error())) socket.tSocket. Close () return } // 超过最大连接池限制直接关闭连接 if len(pool.freeconn) > pool.MaxIdleConns { libs.Logger.Info("thrift_pool", zap.String("release msg", " > pool.MaxIdleConns")) socket.tSocket.Close() return } socket.time = time.Now() socket.err = nil socket.tSocket.Conn().SetDeadline(time.Now().Add(time.Duration(pool.Timeout))) pool.freeconn = append(pool.freeconn, socket) } func (pool *ThriftPool) GetConn() (socket *ThriftSocket, err error) { pool.mutex.Lock() defer pool.mutex.Unlock() if len(pool.freeconn) > 0 { for { if len(pool.freeconn) > 0 { socket = pool.freeconn[len(pool.freeconn)-1] pool.freeconn = pool.freeconn[:len(pool.freeconn)-1] // 检查时间,在thrift socket 会调用 pushDeadline 设置连接的绝对时间 if time.Now().Sub(socket.time) < pool.NetTimeOut() { return socket, nil } socket.tSocket.Close() } // 别忘了退出呀 break } } thriftSocket := ThriftSocket{} if socket,err := thrift.NewTSocketTimeout(pool.Addr, pool.Timeout); err == nil { thriftSocket.tSocket = socket thriftSocket.time = time.Now() } else { libs.Logger.Info("thrift_pool", zap.String("get err", err.Error())) return nil, err } // 直接连接 if err := thriftSocket.tSocket.Open(); err != nil { libs.Logger.Info("thrift_pool", zap.String("get err", err.Error())) return nil, err } return &thriftSocket, nil }
使用方法如下:
tSocket, err := dyanmicPool.GetConn() defer dyanmicPool.Release(tSocket) if err != nil { tSocket.SetErr(err) return err } socket := tSocket.GetSocket() // 创建二进制协议 protocol := thrift.NewTBinaryProtocolTransport(socket) // 接口需要context,以便在长操作时用户可以取消 RPC 调用 ctx := context.Background() // DynamicTService 为thrift 服务 dynamicProtocol := thrift.NewTMultiplexedProtocol(protocol, "DynamicTService") // 创建代理客户端,使用TMultiplexedProtocol访问对应的服务 c := thrift.NewTStandardClient(dynamicProtocol, dynamicProtocol) client :=DynamicTService.NewDynamicTServiceClient(c) // 调用具体的方法 if list, err := client.DynamicExtraInfo(ctx, int64(uid), dynamicIdList); err == nil { dynamicInfoList = list } else { return err }