github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/client/server_master_client.go (about)

     1  // Copyright 2022 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 client
    15  
    16  import (
    17  	"github.com/pingcap/log"
    18  	"github.com/pingcap/tiflow/engine/enginepb"
    19  	"github.com/pingcap/tiflow/engine/pkg/client/internal"
    20  	"github.com/pingcap/tiflow/pkg/errors"
    21  	"github.com/pingcap/tiflow/pkg/security"
    22  	"go.uber.org/zap"
    23  	"google.golang.org/grpc"
    24  )
    25  
    26  type (
    27  	// MasterServerList is an alias for map[string]bool.
    28  	// It is a mapping from servers' address to whether they are the leader.
    29  	MasterServerList = internal.MasterServerList
    30  )
    31  
    32  // ServerMasterClient is a client for connecting to the server master.
    33  type ServerMasterClient interface {
    34  	TaskSchedulerClient
    35  	DiscoveryClient
    36  	ResourceManagerClient
    37  
    38  	// Close closes the gRPC connection used to create the client.
    39  	Close()
    40  }
    41  
    42  // ServerMasterClientWithFailOver implements ServerMasterClient.
    43  // It maintains an updatable list of servers and records the leader's address.
    44  type ServerMasterClientWithFailOver struct {
    45  	TaskSchedulerClient
    46  	DiscoveryClient
    47  	ResourceManagerClient
    48  
    49  	conn     *grpc.ClientConn
    50  	resolver *internal.LeaderResolver
    51  }
    52  
    53  // NewServerMasterClientWithEndpointList creates a new ServerMasterClientWithFailOver
    54  // with an endpoint list.
    55  func NewServerMasterClientWithEndpointList(
    56  	endpoints []string,
    57  	credentials *security.Credential,
    58  ) (*ServerMasterClientWithFailOver, error) {
    59  	serverList := make(MasterServerList, len(endpoints))
    60  	for _, addr := range endpoints {
    61  		serverList[addr] = false
    62  	}
    63  	return NewServerMasterClientWithFailOver(serverList, credentials)
    64  }
    65  
    66  // NewServerMasterClientWithFailOver creates a new ServerMasterClientWithFailOver.
    67  // It is recommended that we use a singleton pattern here: Create one ServerMasterClientWithFailOver
    68  // in each executor process.
    69  func NewServerMasterClientWithFailOver(
    70  	serverList MasterServerList,
    71  	credentials *security.Credential,
    72  ) (*ServerMasterClientWithFailOver, error) {
    73  	if credentials == nil {
    74  		credentials = &security.Credential{}
    75  	}
    76  
    77  	dialOpt, err := credentials.ToGRPCDialOption()
    78  	if err != nil {
    79  		return nil, errors.Trace(err)
    80  	}
    81  
    82  	leaderResolver := internal.NewLeaderResolver(serverList)
    83  	conn, err := grpc.Dial(
    84  		"tiflow://dummy", // Dummy
    85  		grpc.WithResolvers(leaderResolver),
    86  		dialOpt)
    87  	if err != nil {
    88  		return nil, errors.Trace(err)
    89  	}
    90  
    91  	return &ServerMasterClientWithFailOver{
    92  		TaskSchedulerClient:   NewTaskSchedulerClient(enginepb.NewTaskSchedulerClient(conn)),
    93  		DiscoveryClient:       NewDiscoveryClient(enginepb.NewDiscoveryClient(conn)),
    94  		ResourceManagerClient: NewResourceManagerClient(enginepb.NewResourceManagerClient(conn)),
    95  		conn:                  conn,
    96  		resolver:              leaderResolver,
    97  	}, nil
    98  }
    99  
   100  // Close closes the NewServerMasterClientWithFailOver.
   101  func (c *ServerMasterClientWithFailOver) Close() {
   102  	if err := c.conn.Close(); err != nil {
   103  		log.L().Warn("failed to close client", zap.Error(err))
   104  	}
   105  }
   106  
   107  // UpdateServerList updates the server list maintained by the client.
   108  // It is thread-safe.
   109  func (c *ServerMasterClientWithFailOver) UpdateServerList(serverList MasterServerList) {
   110  	c.resolver.UpdateServerList(serverList)
   111  }