github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/cdc/kv/grpc_pool_impl_test.go (about) 1 // Copyright 2021 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package kv 15 16 import ( 17 "context" 18 "testing" 19 20 "github.com/pingcap/tiflow/pkg/security" 21 "github.com/stretchr/testify/require" 22 ) 23 24 // Use clientSuite for some special reasons, the embed etcd uses zap as the only candidate 25 // logger and in the logger initialization it also initializes the grpclog/loggerv2, which 26 // is not a thread-safe operation and it must be called before any gRPC functions 27 // ref: https://github.com/grpc/grpc-go/blob/master/grpclog/loggerv2.go#L67-L72 28 func TestConnArray(t *testing.T) { 29 t.Parallel() 30 31 ctx, cancel := context.WithCancel(context.Background()) 32 defer cancel() 33 34 pool := NewGrpcPoolImpl(ctx, &security.Credential{}) 35 defer pool.Close() 36 addr := "127.0.0.1:20161" 37 conn, err := pool.GetConn(addr) 38 require.Nil(t, err) 39 require.Equal(t, int64(1), conn.active) 40 pool.ReleaseConn(conn, addr) 41 require.Equal(t, int64(0), conn.active) 42 43 lastConn := conn 44 // First grpcConnCapacity*2 connections will use initial two connections. 45 for i := 0; i < grpcConnCapacity*2; i++ { 46 conn, err := pool.GetConn(addr) 47 require.Nil(t, err) 48 require.NotSame(t, conn.ClientConn, lastConn.ClientConn) 49 require.Equal(t, int64(i)/2+1, conn.active) 50 lastConn = conn 51 } 52 // The following grpcConnCapacity*2 connections will trigger resize of connection array. 53 for i := 0; i < grpcConnCapacity*2; i++ { 54 conn, err := pool.GetConn(addr) 55 require.Nil(t, err) 56 require.NotSame(t, conn.ClientConn, lastConn.ClientConn) 57 require.Equal(t, int64(i)/2+1, conn.active) 58 lastConn = conn 59 } 60 } 61 62 func TestConnArrayRecycle(t *testing.T) { 63 t.Parallel() 64 65 ctx, cancel := context.WithCancel(context.Background()) 66 defer cancel() 67 68 pool := NewGrpcPoolImpl(ctx, &security.Credential{}) 69 defer pool.Close() 70 addr := "127.0.0.1:20161" 71 72 bucket := 6 73 // sharedConns will store SharedConn with the same index according to connArray bucket. 74 sharedConns := make([]*sharedConn, bucket) 75 // get conn for 6000 times, and grpc pool will create 6 buckets 76 for i := 0; i < grpcConnCapacity*bucket; i++ { 77 conn, err := pool.GetConn(addr) 78 require.Nil(t, err) 79 if i%(grpcConnCapacity*resizeBucketStep) == 0 { 80 sharedConns[i/grpcConnCapacity] = conn 81 } 82 if i%(grpcConnCapacity*resizeBucketStep) == 1 { 83 sharedConns[i/grpcConnCapacity+1] = conn 84 } 85 } 86 for i := 2; i < bucket; i++ { 87 require.Equal(t, int64(grpcConnCapacity), sharedConns[i].active) 88 for j := 0; j < grpcConnCapacity; j++ { 89 pool.ReleaseConn(sharedConns[i], addr) 90 } 91 } 92 empty := pool.bucketConns[addr].recycle() 93 require.False(t, empty) 94 require.Len(t, pool.bucketConns[addr].conns, 2) 95 96 for i := 0; i < 2; i++ { 97 require.Equal(t, int64(grpcConnCapacity), sharedConns[i].active) 98 for j := 0; j < grpcConnCapacity; j++ { 99 pool.ReleaseConn(sharedConns[i], addr) 100 } 101 } 102 empty = pool.bucketConns[addr].recycle() 103 require.True(t, empty) 104 require.Len(t, pool.bucketConns[addr].conns, 0) 105 }