github.com/matrixorigin/matrixone@v1.2.0/pkg/proxy/conn_migration.go (about) 1 // Copyright 2021 - 2024 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 proxy 16 17 import ( 18 "context" 19 "time" 20 21 "github.com/matrixorigin/matrixone/pkg/clusterservice" 22 "github.com/matrixorigin/matrixone/pkg/common/moerr" 23 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 24 "github.com/matrixorigin/matrixone/pkg/pb/query" 25 v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" 26 "go.uber.org/zap" 27 ) 28 29 func (c *clientConn) getQueryAddress(addr string) string { 30 var queryAddr string 31 c.moCluster.GetCNService(clusterservice.NewSelectAll(), func(service metadata.CNService) bool { 32 if service.SQLAddress == addr { 33 queryAddr = service.QueryAddress 34 return false 35 } 36 return true 37 }) 38 return queryAddr 39 } 40 41 func (c *clientConn) migrateConnFrom(sqlAddr string) (*query.MigrateConnFromResponse, error) { 42 req := c.queryClient.NewRequest(query.CmdMethod_MigrateConnFrom) 43 req.MigrateConnFromRequest = &query.MigrateConnFromRequest{ 44 ConnID: c.connID, 45 } 46 ctx, cancel := context.WithTimeout(c.ctx, time.Second*3) 47 defer cancel() 48 addr := c.getQueryAddress(sqlAddr) 49 if addr == "" { 50 return nil, moerr.NewInternalError(c.ctx, "cannot get query service address") 51 } 52 resp, err := c.queryClient.SendMessage(ctx, addr, req) 53 if err != nil { 54 return nil, err 55 } 56 r := resp.MigrateConnFromResponse 57 defer c.queryClient.Release(resp) 58 return r, nil 59 } 60 61 func (c *clientConn) migrateConnTo(sc ServerConn, info *query.MigrateConnFromResponse) error { 62 // Before migrate session info with RPC, we need to execute some 63 // SQLs to initialize the session and account in handler. 64 // Currently, the session variable transferred is not used anywhere else, 65 // and just used here. 66 if _, err := sc.ExecStmt(internalStmt{ 67 cmdType: cmdQuery, 68 s: "/* cloud_nonuser */ set transferred=1;", 69 }, nil); err != nil { 70 return err 71 } 72 73 // First, we re-run the set variables statements. 74 for _, stmt := range c.migration.setVarStmts { 75 if _, err := sc.ExecStmt(internalStmt{ 76 cmdType: cmdQuery, 77 s: stmt, 78 }, nil); err != nil { 79 v2.ProxyConnectCommonFailCounter.Inc() 80 return err 81 } 82 } 83 84 // Then, migrate other info with RPC. 85 addr := c.getQueryAddress(sc.RawConn().RemoteAddr().String()) 86 if addr == "" { 87 return moerr.NewInternalError(c.ctx, "cannot get query service address") 88 } 89 c.log.Info("connection migrate to server", zap.String("server address", addr), 90 zap.String("tenant", string(c.clientInfo.Tenant)), 91 zap.String("username", c.clientInfo.username), 92 zap.Uint32("conn ID", c.connID)) 93 req := c.queryClient.NewRequest(query.CmdMethod_MigrateConnTo) 94 req.MigrateConnToRequest = &query.MigrateConnToRequest{ 95 ConnID: c.connID, 96 DB: info.DB, 97 PrepareStmts: info.PrepareStmts, 98 } 99 ctx, cancel := context.WithTimeout(c.ctx, time.Second*3) 100 defer cancel() 101 resp, err := c.queryClient.SendMessage(ctx, addr, req) 102 if err != nil { 103 return err 104 } 105 c.queryClient.Release(resp) 106 return nil 107 } 108 109 func (c *clientConn) migrateConn(prevAddr string, sc ServerConn) error { 110 resp, err := c.migrateConnFrom(prevAddr) 111 if err != nil { 112 return err 113 } 114 if resp == nil { 115 return moerr.NewInternalError(c.ctx, "bad response") 116 } 117 return c.migrateConnTo(sc, resp) 118 }