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 }