github.com/matrixorigin/matrixone@v1.2.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 "errors" 20 "fmt" 21 "time" 22 23 "github.com/fagongzi/goetty/v2" 24 "github.com/matrixorigin/matrixone/pkg/backup" 25 "github.com/matrixorigin/matrixone/pkg/common/moerr" 26 "github.com/matrixorigin/matrixone/pkg/common/stopper" 27 "github.com/matrixorigin/matrixone/pkg/logservice" 28 "github.com/matrixorigin/matrixone/pkg/logutil" 29 logpb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 30 "go.uber.org/zap" 31 ) 32 33 var ( 34 cnProxy goetty.Proxy 35 ) 36 37 func startCluster( 38 ctx context.Context, 39 stopper *stopper.Stopper, 40 shutdownC chan struct{}, 41 ) error { 42 if *launchFile == "" { 43 panic("launch file not set") 44 } 45 46 cfg := &LaunchConfig{} 47 if err := parseConfigFromFile(*launchFile, cfg); err != nil { 48 return err 49 } 50 51 if cfg.Dynamic.Enable { 52 return startDynamicCluster(ctx, cfg, stopper, shutdownC) 53 } 54 55 /* 56 When the mo started in local cluster, we save all config files. 57 Because we can get all config files conveniently. 58 */ 59 backup.SaveLaunchConfigPath(backup.LaunchConfig, []string{*launchFile}) 60 backup.SaveLaunchConfigPath(backup.LogConfig, cfg.LogServiceConfigFiles) 61 backup.SaveLaunchConfigPath(backup.DnConfig, cfg.TNServiceConfigsFiles) 62 backup.SaveLaunchConfigPath(backup.CnConfig, cfg.CNServiceConfigsFiles) 63 if err := startLogServiceCluster(ctx, cfg.LogServiceConfigFiles, stopper, shutdownC); err != nil { 64 return err 65 } 66 if err := startTNServiceCluster(ctx, cfg.TNServiceConfigsFiles, stopper, shutdownC); err != nil { 67 return err 68 } 69 if err := startCNServiceCluster(ctx, cfg.CNServiceConfigsFiles, stopper, shutdownC); err != nil { 70 return err 71 } 72 if *withProxy { 73 backup.SaveLaunchConfigPath(backup.ProxyConfig, cfg.ProxyServiceConfigsFiles) 74 if err := startProxyServiceCluster(ctx, cfg.ProxyServiceConfigsFiles, stopper, shutdownC); err != nil { 75 return err 76 } 77 } 78 if err := startPythonUdfServiceCluster(ctx, cfg.PythonUdfServiceConfigsFiles, stopper, shutdownC); err != nil { 79 return err 80 } 81 return nil 82 } 83 84 func startLogServiceCluster( 85 ctx context.Context, 86 files []string, 87 stopper *stopper.Stopper, 88 shutdownC chan struct{}, 89 ) error { 90 if len(files) == 0 { 91 return moerr.NewBadConfig(context.Background(), "Log service config not set") 92 } 93 94 var cfg *Config 95 for _, file := range files { 96 cfg = NewConfig() 97 if err := parseConfigFromFile(file, cfg); err != nil { 98 return err 99 } 100 if err := startService(ctx, cfg, stopper, shutdownC); err != nil { 101 return err 102 } 103 } 104 return nil 105 } 106 107 func startTNServiceCluster( 108 ctx context.Context, 109 files []string, 110 stopper *stopper.Stopper, 111 shutdownC chan struct{}, 112 ) error { 113 if len(files) == 0 { 114 return moerr.NewBadConfig(context.Background(), "DN service config not set") 115 } 116 117 for _, file := range files { 118 cfg := NewConfig() 119 // mo boosting in standalone mode 120 cfg.IsStandalone = true 121 if err := parseConfigFromFile(file, cfg); err != nil { 122 return err 123 } 124 if err := startService(ctx, cfg, stopper, shutdownC); err != nil { 125 return nil 126 } 127 } 128 return nil 129 } 130 131 func startCNServiceCluster( 132 ctx context.Context, 133 files []string, 134 stopper *stopper.Stopper, 135 shutdownC chan struct{}, 136 ) error { 137 if len(files) == 0 { 138 return moerr.NewBadConfig(context.Background(), "CN service config not set") 139 } 140 141 upstreams := []string{} 142 143 var cfg *Config 144 for _, file := range files { 145 cfg = NewConfig() 146 if err := parseConfigFromFile(file, cfg); err != nil { 147 return err 148 } 149 upstreams = append(upstreams, fmt.Sprintf("127.0.0.1:%d", cfg.getCNServiceConfig().Frontend.Port)) 150 if err := startService(ctx, cfg, stopper, shutdownC); err != nil { 151 return err 152 } 153 } 154 155 if len(upstreams) > 1 { 156 // TODO: make configurable for 6001 157 cnProxy = goetty.NewProxy("0.0.0.0:6001", logutil.GetGlobalLogger().Named("mysql-proxy")) 158 for _, address := range upstreams { 159 cnProxy.AddUpStream(address, time.Second*10) 160 } 161 if err := cnProxy.Start(); err != nil { 162 return err 163 } 164 } 165 return nil 166 } 167 168 func startProxyServiceCluster( 169 ctx context.Context, 170 files []string, 171 stopper *stopper.Stopper, 172 shutdownC chan struct{}, 173 ) error { 174 if len(files) == 0 { 175 return moerr.NewBadConfig(context.Background(), "Proxy service config not set") 176 } 177 178 var cfg *Config 179 for _, file := range files { 180 cfg = NewConfig() 181 if err := parseConfigFromFile(file, cfg); err != nil { 182 return err 183 } 184 if err := startService(ctx, cfg, stopper, shutdownC); err != nil { 185 return err 186 } 187 } 188 189 return nil 190 } 191 192 func startPythonUdfServiceCluster( 193 ctx context.Context, 194 files []string, 195 stopper *stopper.Stopper, 196 shutdownC chan struct{}, 197 ) error { 198 if len(files) == 0 { 199 return nil 200 } 201 202 for _, file := range files { 203 cfg := NewConfig() 204 if err := parseConfigFromFile(file, cfg); err != nil { 205 return err 206 } 207 if err := startService(ctx, cfg, stopper, shutdownC); err != nil { 208 return err 209 } 210 } 211 return nil 212 } 213 214 func waitHAKeeperReady(cfg logservice.HAKeeperClientConfig) (logservice.CNHAKeeperClient, error) { 215 // wait hakeeper ready 216 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*30) 217 defer cancel() 218 for { 219 var err error 220 client, err := logservice.NewCNHAKeeperClient(ctx, cfg) 221 if moerr.IsMoErrCode(err, moerr.ErrNoHAKeeper) { 222 // not ready 223 logutil.Info("hakeeper not ready, retry") 224 time.Sleep(time.Second) 225 continue 226 } 227 return client, err 228 } 229 } 230 231 func waitHAKeeperRunning(client logservice.CNHAKeeperClient) error { 232 ctx, cancel := context.WithTimeout(context.TODO(), time.Minute*2) 233 defer cancel() 234 235 // wait HAKeeper running 236 for { 237 state, err := client.GetClusterState(ctx) 238 if errors.Is(err, context.DeadlineExceeded) { 239 return err 240 } 241 if moerr.IsMoErrCode(err, moerr.ErrNoHAKeeper) || 242 state.State != logpb.HAKeeperRunning { 243 // not ready 244 logutil.Info("hakeeper not ready, retry") 245 time.Sleep(time.Second) 246 continue 247 } 248 return err 249 } 250 } 251 252 func waitAnyShardReady(client logservice.CNHAKeeperClient) error { 253 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*30) 254 defer cancel() 255 256 // wait shard ready 257 for { 258 if ok, err := func() (bool, error) { 259 details, err := client.GetClusterDetails(ctx) 260 if err != nil { 261 if errors.Is(err, context.DeadlineExceeded) { 262 logutil.Errorf("wait TN ready timeout: %s", err) 263 return false, err 264 } 265 logutil.Errorf("failed to get cluster details %s", err) 266 return false, nil 267 } 268 for _, store := range details.TNStores { 269 if len(store.Shards) > 0 { 270 return true, nil 271 } 272 } 273 logutil.Info("shard not ready") 274 return false, nil 275 }(); err != nil { 276 return err 277 } else if ok { 278 logutil.Info("shard ready") 279 return nil 280 } 281 time.Sleep(time.Second) 282 } 283 } 284 285 func waitClusterCondition( 286 cfg logservice.HAKeeperClientConfig, 287 waitFunc func(logservice.CNHAKeeperClient) error, 288 ) error { 289 client, err := waitHAKeeperReady(cfg) 290 if err != nil { 291 return err 292 } 293 if err := waitFunc(client); err != nil { 294 return err 295 } 296 if err := client.Close(); err != nil { 297 logutil.Error("close hakeeper client failed", zap.Error(err)) 298 } 299 return nil 300 }