mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-14 18:30:02 +08:00
chore: refactor shutdown config, to prevent setting zero values (#4533)
Signed-off-by: kevin <wanjunfeng@gmail.com>
This commit is contained in:
@@ -13,19 +13,26 @@ import (
|
|||||||
"github.com/zeromicro/go-zero/core/threading"
|
"github.com/zeromicro/go-zero/core/threading"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProcConf struct {
|
const (
|
||||||
WrapUpTime time.Duration `json:",default=1s"`
|
defaultWrapUpTime = time.Second
|
||||||
WaitTime time.Duration `json:",default=5.5s"`
|
// why we use 5500 milliseconds is because most of our queue are blocking mode with 5 seconds
|
||||||
}
|
defaultWaitTime = 5500 * time.Millisecond
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
wrapUpListeners = new(listenerManager)
|
wrapUpListeners = new(listenerManager)
|
||||||
shutdownListeners = new(listenerManager)
|
shutdownListeners = new(listenerManager)
|
||||||
wrapUpTime = time.Second
|
wrapUpTime = defaultWrapUpTime
|
||||||
// why we use 5500 milliseconds is because most of our queue are blocking mode with 5 seconds
|
waitTime = defaultWaitTime
|
||||||
delayTimeBeforeForceQuit = 5500 * time.Millisecond
|
shutdownLock sync.Mutex
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ShutdownConf defines the shutdown configuration for the process.
|
||||||
|
type ShutdownConf struct {
|
||||||
|
WrapUpTime time.Duration `json:",default=1s"`
|
||||||
|
WaitTime time.Duration `json:",default=5.5s"`
|
||||||
|
}
|
||||||
|
|
||||||
// AddShutdownListener adds fn as a shutdown listener.
|
// AddShutdownListener adds fn as a shutdown listener.
|
||||||
// The returned func can be used to wait for fn getting called.
|
// The returned func can be used to wait for fn getting called.
|
||||||
func AddShutdownListener(fn func()) (waitForCalled func()) {
|
func AddShutdownListener(fn func()) (waitForCalled func()) {
|
||||||
@@ -40,12 +47,21 @@ func AddWrapUpListener(fn func()) (waitForCalled func()) {
|
|||||||
|
|
||||||
// SetTimeToForceQuit sets the waiting time before force quitting.
|
// SetTimeToForceQuit sets the waiting time before force quitting.
|
||||||
func SetTimeToForceQuit(duration time.Duration) {
|
func SetTimeToForceQuit(duration time.Duration) {
|
||||||
delayTimeBeforeForceQuit = duration
|
shutdownLock.Lock()
|
||||||
|
defer shutdownLock.Unlock()
|
||||||
|
waitTime = duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setup(conf ProcConf) {
|
func Setup(conf ShutdownConf) {
|
||||||
wrapUpTime = conf.WrapUpTime
|
shutdownLock.Lock()
|
||||||
delayTimeBeforeForceQuit = conf.WaitTime
|
defer shutdownLock.Unlock()
|
||||||
|
|
||||||
|
if conf.WrapUpTime > 0 {
|
||||||
|
wrapUpTime = conf.WrapUpTime
|
||||||
|
}
|
||||||
|
if conf.WaitTime > 0 {
|
||||||
|
waitTime = conf.WaitTime
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown calls the registered shutdown listeners, only for test purpose.
|
// Shutdown calls the registered shutdown listeners, only for test purpose.
|
||||||
@@ -67,8 +83,12 @@ func gracefulStop(signals chan os.Signal, sig syscall.Signal) {
|
|||||||
time.Sleep(wrapUpTime)
|
time.Sleep(wrapUpTime)
|
||||||
go shutdownListeners.notifyListeners()
|
go shutdownListeners.notifyListeners()
|
||||||
|
|
||||||
time.Sleep(delayTimeBeforeForceQuit - wrapUpTime)
|
shutdownLock.Lock()
|
||||||
logx.Infof("Still alive after %v, going to force kill the process...", delayTimeBeforeForceQuit)
|
remainingTime := waitTime - wrapUpTime
|
||||||
|
shutdownLock.Unlock()
|
||||||
|
|
||||||
|
time.Sleep(remainingTime)
|
||||||
|
logx.Infof("Still alive after %v, going to force kill the process...", waitTime)
|
||||||
_ = syscall.Kill(syscall.Getpid(), sig)
|
_ = syscall.Kill(syscall.Getpid(), sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestShutdown(t *testing.T) {
|
func TestShutdown(t *testing.T) {
|
||||||
|
t.Cleanup(restoreSettings)
|
||||||
|
|
||||||
SetTimeToForceQuit(time.Hour)
|
SetTimeToForceQuit(time.Hour)
|
||||||
assert.Equal(t, time.Hour, delayTimeBeforeForceQuit)
|
shutdownLock.Lock()
|
||||||
|
assert.Equal(t, time.Hour, waitTime)
|
||||||
|
shutdownLock.Unlock()
|
||||||
|
|
||||||
var val int
|
var val int
|
||||||
called := AddWrapUpListener(func() {
|
called := AddWrapUpListener(func() {
|
||||||
@@ -31,8 +35,12 @@ func TestShutdown(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestShutdownWithMultipleServices(t *testing.T) {
|
func TestShutdownWithMultipleServices(t *testing.T) {
|
||||||
|
t.Cleanup(restoreSettings)
|
||||||
|
|
||||||
SetTimeToForceQuit(time.Hour)
|
SetTimeToForceQuit(time.Hour)
|
||||||
assert.Equal(t, time.Hour, delayTimeBeforeForceQuit)
|
shutdownLock.Lock()
|
||||||
|
assert.Equal(t, time.Hour, waitTime)
|
||||||
|
shutdownLock.Unlock()
|
||||||
|
|
||||||
var val int32
|
var val int32
|
||||||
called1 := AddShutdownListener(func() {
|
called1 := AddShutdownListener(func() {
|
||||||
@@ -49,8 +57,12 @@ func TestShutdownWithMultipleServices(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWrapUpWithMultipleServices(t *testing.T) {
|
func TestWrapUpWithMultipleServices(t *testing.T) {
|
||||||
|
t.Cleanup(restoreSettings)
|
||||||
|
|
||||||
SetTimeToForceQuit(time.Hour)
|
SetTimeToForceQuit(time.Hour)
|
||||||
assert.Equal(t, time.Hour, delayTimeBeforeForceQuit)
|
shutdownLock.Lock()
|
||||||
|
assert.Equal(t, time.Hour, waitTime)
|
||||||
|
shutdownLock.Unlock()
|
||||||
|
|
||||||
var val int32
|
var val int32
|
||||||
called1 := AddWrapUpListener(func() {
|
called1 := AddWrapUpListener(func() {
|
||||||
@@ -67,6 +79,8 @@ func TestWrapUpWithMultipleServices(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNotifyMoreThanOnce(t *testing.T) {
|
func TestNotifyMoreThanOnce(t *testing.T) {
|
||||||
|
t.Cleanup(restoreSettings)
|
||||||
|
|
||||||
ch := make(chan struct{}, 1)
|
ch := make(chan struct{}, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@@ -97,10 +111,36 @@ func TestNotifyMoreThanOnce(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSetup(t *testing.T) {
|
func TestSetup(t *testing.T) {
|
||||||
Setup(ProcConf{
|
t.Run("valid time", func(t *testing.T) {
|
||||||
WrapUpTime: time.Second * 2,
|
defer restoreSettings()
|
||||||
WaitTime: time.Second * 30,
|
|
||||||
|
Setup(ShutdownConf{
|
||||||
|
WrapUpTime: time.Second * 2,
|
||||||
|
WaitTime: time.Second * 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
shutdownLock.Lock()
|
||||||
|
assert.Equal(t, time.Second*2, wrapUpTime)
|
||||||
|
assert.Equal(t, time.Second*30, waitTime)
|
||||||
|
shutdownLock.Unlock()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("valid time", func(t *testing.T) {
|
||||||
|
defer restoreSettings()
|
||||||
|
|
||||||
|
Setup(ShutdownConf{})
|
||||||
|
|
||||||
|
shutdownLock.Lock()
|
||||||
|
assert.Equal(t, defaultWrapUpTime, wrapUpTime)
|
||||||
|
assert.Equal(t, defaultWaitTime, waitTime)
|
||||||
|
shutdownLock.Unlock()
|
||||||
})
|
})
|
||||||
assert.Equal(t, time.Second*2, wrapUpTime)
|
}
|
||||||
assert.Equal(t, time.Second*30, delayTimeBeforeForceQuit)
|
|
||||||
|
func restoreSettings() {
|
||||||
|
shutdownLock.Lock()
|
||||||
|
defer shutdownLock.Unlock()
|
||||||
|
|
||||||
|
wrapUpTime = defaultWrapUpTime
|
||||||
|
waitTime = defaultWaitTime
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ type (
|
|||||||
Prometheus prometheus.Config `json:",optional"`
|
Prometheus prometheus.Config `json:",optional"`
|
||||||
Telemetry trace.Config `json:",optional"`
|
Telemetry trace.Config `json:",optional"`
|
||||||
DevServer DevServerConfig `json:",optional"`
|
DevServer DevServerConfig `json:",optional"`
|
||||||
Proc proc.ProcConf `json:",optional"`
|
Shutdown proc.ShutdownConf `json:",optional"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ func (sc ServiceConf) SetUp() error {
|
|||||||
sc.Telemetry.Name = sc.Name
|
sc.Telemetry.Name = sc.Name
|
||||||
}
|
}
|
||||||
trace.StartAgent(sc.Telemetry)
|
trace.StartAgent(sc.Telemetry)
|
||||||
proc.Setup(sc.Proc)
|
proc.Setup(sc.Shutdown)
|
||||||
proc.AddShutdownListener(func() {
|
proc.AddShutdownListener(func() {
|
||||||
trace.StopAgent()
|
trace.StopAgent()
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user