Skip to content

Commit 1b7e877

Browse files
Merge pull request #79 from github/r15.0/add-shutdown-state-in-vtgate
Gracefully shutdown VTGate instances
2 parents 6e3ab03 + ebd0acf commit 1b7e877

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

go/mysql/conn.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,12 @@ type Conn struct {
199199
// enableQueryInfo controls whether we parse the INFO field in QUERY_OK packets
200200
// See: ConnParams.EnableQueryInfo
201201
enableQueryInfo bool
202+
203+
// mu protects the fields below
204+
mu sync.Mutex
205+
// this is used to mark the connection to be closed so that the command phase for the connection can be stopped and
206+
// the connection gets closed.
207+
closing bool
202208
}
203209

204210
// splitStatementFunciton is the function that is used to split the statement in case of a multi-statement query.
@@ -895,6 +901,11 @@ func (c *Conn) handleNextCommand(handler Handler) bool {
895901
return false
896902
}
897903

904+
// before continue to process the packet, check if the connection should be closed or not.
905+
if c.IsMarkedForClose() {
906+
return false
907+
}
908+
898909
switch data[0] {
899910
case ComQuit:
900911
c.recycleReadPacket()
@@ -1581,3 +1592,21 @@ func (c *Conn) IsUnixSocket() bool {
15811592
func (c *Conn) GetRawConn() net.Conn {
15821593
return c.conn
15831594
}
1595+
1596+
// MarkForClose marks the connection for close.
1597+
func (c *Conn) MarkForClose() {
1598+
c.mu.Lock()
1599+
defer c.mu.Unlock()
1600+
c.closing = true
1601+
}
1602+
1603+
// IsMarkedForClose return true if the connection should be closed.
1604+
func (c *Conn) IsMarkedForClose() bool {
1605+
c.mu.Lock()
1606+
defer c.mu.Unlock()
1607+
return c.closing
1608+
}
1609+
1610+
func (c *Conn) IsShuttingDown() bool {
1611+
return c.listener.isShutdown()
1612+
}

go/mysql/server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,8 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti
520520

521521
for {
522522
kontinue := c.handleNextCommand(l.handler)
523-
if !kontinue {
523+
// before going for next command check if the connection should be closed or not.
524+
if !kontinue || c.IsMarkedForClose() {
524525
return
525526
}
526527
}

go/vt/vtgate/plugin_mysql_server.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ func startSpan(ctx context.Context, query, label string) (trace.Span, context.Co
182182
}
183183

184184
func (vh *vtgateHandler) ComQuery(c *mysql.Conn, query string, callback func(*sqltypes.Result) error) error {
185+
session := vh.session(c)
186+
if c.IsShuttingDown() && !session.InTransaction {
187+
c.MarkForClose()
188+
return mysql.NewSQLError(mysql.ERServerShutdown, mysql.SSNetError, "Server shutdown in progress")
189+
}
190+
185191
ctx := context.Background()
186192
var cancel context.CancelFunc
187193
if *mysqlQueryTimeout != 0 {
@@ -209,7 +215,6 @@ func (vh *vtgateHandler) ComQuery(c *mysql.Conn, query string, callback func(*sq
209215
"VTGate MySQL Connector" /* subcomponent: part of the client */)
210216
ctx = callerid.NewContext(ctx, ef, im)
211217

212-
session := vh.session(c)
213218
if !session.InTransaction {
214219
atomic.AddInt32(&busyConnections, 1)
215220
}
@@ -536,11 +541,11 @@ func newMysqlUnixSocket(address string, authServer mysql.AuthServer, handler mys
536541

537542
func shutdownMysqlProtocolAndDrain() {
538543
if mysqlListener != nil {
539-
mysqlListener.Close()
544+
mysqlListener.Shutdown()
540545
mysqlListener = nil
541546
}
542547
if mysqlUnixListener != nil {
543-
mysqlUnixListener.Close()
548+
mysqlUnixListener.Shutdown()
544549
mysqlUnixListener = nil
545550
}
546551
if sigChan != nil {

0 commit comments

Comments
 (0)