github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/p2p/client_connector.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 p2p
    15  
    16  import (
    17  	"context"
    18  	"net"
    19  	"time"
    20  
    21  	"github.com/pingcap/errors"
    22  	"github.com/pingcap/log"
    23  	"github.com/pingcap/tiflow/pkg/security"
    24  	proto "github.com/pingcap/tiflow/proto/p2p"
    25  	"go.uber.org/zap"
    26  	"google.golang.org/grpc"
    27  )
    28  
    29  type clientConnectOptions struct {
    30  	// network and addr are similar to the parameters
    31  	// to net.Dial.
    32  	network string
    33  	addr    string
    34  
    35  	// credential is used to setup the connection to the gRPC server.
    36  	credential *security.Credential
    37  	// timeout specifies the DialTimeout of the connection.
    38  	timeout        time.Duration
    39  	maxRecvMsgSize int
    40  }
    41  
    42  type cancelFn = func()
    43  
    44  // clientConnector abstracts away the underlying gRPC operation of dialing and
    45  // the creation of a gRPC client.
    46  type clientConnector interface {
    47  	Connect(opts clientConnectOptions) (proto.CDCPeerToPeerClient, cancelFn, error)
    48  }
    49  
    50  type clientConnectorImpl struct{}
    51  
    52  func newClientConnector() clientConnector {
    53  	return &clientConnectorImpl{}
    54  }
    55  
    56  // Connect creates a gRPC client connection to the server.
    57  // the returned cancelFn must be called to close the connection.
    58  func (c *clientConnectorImpl) Connect(opts clientConnectOptions) (proto.CDCPeerToPeerClient, cancelFn, error) {
    59  	securityOption, err := opts.credential.ToGRPCDialOption()
    60  	if err != nil {
    61  		return nil, nil, errors.Trace(err)
    62  	}
    63  
    64  	conn, err := grpc.Dial(
    65  		opts.addr,
    66  		securityOption,
    67  		grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(opts.maxRecvMsgSize)),
    68  		grpc.WithContextDialer(func(ctx context.Context, s string) (net.Conn, error) {
    69  			return net.DialTimeout(opts.network, s, opts.timeout)
    70  		}),
    71  		// We do not need a unary interceptor since we are not making any unary calls.
    72  		grpc.WithStreamInterceptor(grpcClientMetrics.StreamClientInterceptor()))
    73  	if err != nil {
    74  		log.Warn("gRPC dial error", zap.Error(err))
    75  		return nil, nil, errors.Trace(err)
    76  	}
    77  
    78  	cancel := func() {
    79  		if err := conn.Close(); err != nil {
    80  			log.Warn("gRPC connection close error", zap.Error(err))
    81  		}
    82  	}
    83  
    84  	return proto.NewCDCPeerToPeerClient(conn), cancel, nil
    85  }