From bd48ea556ba378514894b97de1fc262a67cf3f30 Mon Sep 17 00:00:00 2001 From: smallnest Date: Mon, 13 Jul 2020 18:00:08 +0800 Subject: [PATCH] implement graceful restart --- server/gateway.go | 2 +- server/server.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/server/gateway.go b/server/gateway.go index 10266b1..45be3a0 100644 --- a/server/gateway.go +++ b/server/gateway.go @@ -20,7 +20,7 @@ import ( func (s *Server) startGateway(network string, ln net.Listener) net.Listener { if network != "tcp" && network != "tcp4" && network != "tcp6" { - log.Infof("network is not tcp/tcp4/tcp6 so can not start gateway") + // log.Infof("network is not tcp/tcp4/tcp6 so can not start gateway") return ln } diff --git a/server/server.go b/server/server.go index 410005b..570533f 100644 --- a/server/server.go +++ b/server/server.go @@ -18,6 +18,7 @@ import ( "time" "os" + "os/exec" "os/signal" "syscall" @@ -751,6 +752,46 @@ func (s *Server) Shutdown(ctx context.Context) error { return err } +// Restart restarts this server gracefully. +// It starts a new rpcx server with the same port with SO_REUSEPORT socket option, +// and shutdown this rpcx server gracefully. +func (s *Server) Restart(ctx context.Context) error { + pid, err := s.startProcess() + if err != nil { + return err + } + log.Infof("restart a new rpcx server: %d", pid) + + // TODO: is it necessary? + time.Sleep(3 * time.Second) + return s.Shutdown(ctx) +} + +func (s *Server) startProcess() (int, error) { + argv0, err := exec.LookPath(os.Args[0]) + if err != nil { + return 0, err + } + + // Pass on the environment and replace the old count key with the new one. + var env []string + for _, v := range os.Environ() { + env = append(env, v) + } + + var originalWD, _ = os.Getwd() + allFiles := append([]*os.File{os.Stdin, os.Stdout, os.Stderr}) + process, err := os.StartProcess(argv0, os.Args, &os.ProcAttr{ + Dir: originalWD, + Env: env, + Files: allFiles, + }) + if err != nil { + return 0, err + } + return process.Pid, nil +} + func (s *Server) checkProcessMsg() bool { size := atomic.LoadInt32(&s.handlerMsgNum) log.Info("need handle in-processing msg size:", size)