github.com/matrixorigin/matrixone@v0.7.0/cmd/mo-service/launch.go (about) 1 // Copyright 2022 Matrix Origin 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "context" 19 "fmt" 20 "time" 21 22 "github.com/fagongzi/goetty/v2" 23 "github.com/matrixorigin/matrixone/pkg/common/moerr" 24 "github.com/matrixorigin/matrixone/pkg/common/stopper" 25 "github.com/matrixorigin/matrixone/pkg/logservice" 26 "github.com/matrixorigin/matrixone/pkg/logutil" 27 logpb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 28 "go.uber.org/zap" 29 ) 30 31 var ( 32 cnProxy goetty.Proxy 33 ) 34 35 func startCluster(stopper *stopper.Stopper) error { 36 if *launchFile == "" { 37 panic("launch file not set") 38 } 39 40 cfg := &LaunchConfig{} 41 if err := parseConfigFromFile(*launchFile, cfg); err != nil { 42 return err 43 } 44 45 if err := startLogServiceCluster(cfg.LogServiceConfigFiles, stopper); err != nil { 46 return err 47 } 48 if err := startDNServiceCluster(cfg.DNServiceConfigsFiles, stopper); err != nil { 49 return err 50 } 51 if err := startCNServiceCluster(cfg.CNServiceConfigsFiles, stopper); err != nil { 52 return err 53 } 54 return nil 55 } 56 57 func startLogServiceCluster( 58 files []string, 59 stopper *stopper.Stopper) error { 60 if len(files) == 0 { 61 return moerr.NewBadConfig(context.Background(), "Log service config not set") 62 } 63 64 var cfg *Config 65 for _, file := range files { 66 cfg = &Config{} 67 if err := parseConfigFromFile(file, cfg); err != nil { 68 return err 69 } 70 if err := startService(cfg, stopper); err != nil { 71 return err 72 } 73 } 74 return nil 75 } 76 77 func startDNServiceCluster( 78 files []string, 79 stopper *stopper.Stopper) error { 80 if len(files) == 0 { 81 return moerr.NewBadConfig(context.Background(), "DN service config not set") 82 } 83 84 for _, file := range files { 85 cfg := &Config{} 86 if err := parseConfigFromFile(file, cfg); err != nil { 87 return err 88 } 89 if err := startService(cfg, stopper); err != nil { 90 return nil 91 } 92 } 93 return nil 94 } 95 96 func startCNServiceCluster( 97 files []string, 98 stopper *stopper.Stopper) error { 99 if len(files) == 0 { 100 return moerr.NewBadConfig(context.Background(), "CN service config not set") 101 } 102 103 upstreams := []string{} 104 105 var cfg *Config 106 for _, file := range files { 107 cfg = &Config{} 108 if err := parseConfigFromFile(file, cfg); err != nil { 109 return err 110 } 111 upstreams = append(upstreams, fmt.Sprintf("127.0.0.1:%d", cfg.getCNServiceConfig().Frontend.Port)) 112 if err := startService(cfg, stopper); err != nil { 113 return err 114 } 115 } 116 117 if len(upstreams) > 1 { 118 // TODO: make configurable for 6001 119 cnProxy = goetty.NewProxy("0.0.0.0:6001", logutil.GetGlobalLogger().Named("mysql-proxy")) 120 for _, address := range upstreams { 121 cnProxy.AddUpStream(address, time.Second*10) 122 } 123 if err := cnProxy.Start(); err != nil { 124 return err 125 } 126 } 127 return nil 128 } 129 130 func waitHAKeeperReady(cfg logservice.HAKeeperClientConfig) (logservice.CNHAKeeperClient, error) { 131 // wait hakeeper ready 132 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*30) 133 defer cancel() 134 for { 135 var err error 136 client, err := logservice.NewCNHAKeeperClient(ctx, cfg) 137 if moerr.IsMoErrCode(err, moerr.ErrNoHAKeeper) { 138 // not ready 139 logutil.Info("hakeeper not ready, retry") 140 time.Sleep(time.Second) 141 continue 142 } 143 return client, err 144 } 145 } 146 147 func waitHAKeeperRunning(client logservice.CNHAKeeperClient) error { 148 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*30) 149 defer cancel() 150 151 // wait HAKeeper running 152 for { 153 state, err := client.GetClusterState(ctx) 154 if moerr.IsMoErrCode(err, moerr.ErrNoHAKeeper) || 155 state.State != logpb.HAKeeperRunning { 156 // not ready 157 logutil.Info("hakeeper not ready, retry") 158 time.Sleep(time.Second) 159 continue 160 } 161 return err 162 } 163 } 164 165 func waitAnyShardReady(client logservice.CNHAKeeperClient) error { 166 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*30) 167 defer cancel() 168 169 // wait shard ready 170 for { 171 if ok, err := func() (bool, error) { 172 details, err := client.GetClusterDetails(ctx) 173 if err != nil { 174 return false, err 175 } 176 for _, store := range details.DNStores { 177 if len(store.Shards) > 0 { 178 return true, nil 179 } 180 } 181 logutil.Info("shard not ready") 182 return false, nil 183 }(); err != nil { 184 return err 185 } else if ok { 186 logutil.Info("shard ready") 187 return nil 188 } 189 time.Sleep(time.Second) 190 } 191 } 192 193 func waitClusterCondition( 194 cfg logservice.HAKeeperClientConfig, 195 waitFunc func(logservice.CNHAKeeperClient) error, 196 ) error { 197 client, err := waitHAKeeperReady(cfg) 198 if err != nil { 199 return err 200 } 201 if err := waitFunc(client); err != nil { 202 return err 203 } 204 if err := client.Close(); err != nil { 205 logutil.Error("close hakeeper client failed", zap.Error(err)) 206 } 207 return nil 208 }