Skip to content

Commit 7360efc

Browse files
committed
Upgrade to go 1.8 version, supports shutdown and reboot gracefully.
1 parent 1db950b commit 7360efc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+687
-2269
lines changed

README.md

+17-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ v1.0
2020

2121
### Requirements
2222

23-
Go Version ≥1.6
23+
Go Version ≥1.8
2424

2525
## Quick Start
2626

@@ -68,6 +68,7 @@ think run [appname]
6868
- Supports XSRF security filtering
6969
- Supports near-LRU memory caching (mainly used for static file cache)
7070
- Nice and easy to use configuration file, automatically write default values
71+
- Supports shutdown and reboot gracefully
7172

7273
- `struct Handler` multi-usage
7374

@@ -112,7 +113,7 @@ func main() {
112113
// )
113114

114115
// Start the service
115-
app.Run()
116+
thinkgo.Run()
116117
}
117118

118119
/*
@@ -256,6 +257,20 @@ app2.Group("home")
256257
app2.Run()
257258
```
258259

260+
## shutdown and reboot
261+
262+
- shutdown gracefully
263+
264+
```sh
265+
kill [pid]
266+
```
267+
268+
- reboot gracefully
269+
270+
```sh
271+
kill -USR2 [pid]
272+
```
273+
259274
## Configuration
260275

261276
- Each instance of the application has a single configuration (file name format `config/{appname}[_{version}].ini`). Refer to the following:

README_ZH.md

+16-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ v1.0
2222

2323
### 安装要求
2424

25-
Go Version ≥1.6
25+
Go Version ≥1.8
2626

2727
## 快速使用
2828

@@ -69,6 +69,7 @@ think run [appname]
6969
- 支持Gzip全局配置
7070
- 提供XSRF跨站请求伪造安全过滤
7171
- 简单整洁的配置文件,且自动补填默认值方便设置
72+
- 支持平滑关闭与重启
7273

7374
- `struct Handler` 的多用途合一
7475

@@ -257,6 +258,20 @@ app2.Group("home")
257258
app2.Run()
258259
```
259260

261+
## 平滑关闭与重启
262+
263+
- 平滑关闭
264+
265+
```sh
266+
kill [pid]
267+
```
268+
269+
- 平滑重启
270+
271+
```sh
272+
kill -USR2 [pid]
273+
```
274+
260275
## 配置文件说明
261276

262277
- 应用的各实例均有单独一份配置,其文件名格式 `config/{appname}[_{version}].ini`,配置详情:

global.go

+42-23
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package thinkgo
1616

1717
import (
18+
"context"
1819
"encoding/json"
1920
"fmt"
2021
"net/http"
@@ -70,6 +71,11 @@ type (
7071

7172
syslog *logging.Logger
7273
bizlog *logging.Logger
74+
75+
// finalizer is called after the services shutdown.
76+
finalizer func(context.Context) error
77+
78+
graceOnce sync.Once
7379
}
7480
// PresetStatic is the system default static file routing information
7581
PresetStatic struct {
@@ -201,31 +207,16 @@ func GetFrame(name string, version ...string) (*Framework, bool) {
201207
// Run starts all web services.
202208
func Run() {
203209
global.framesLock.Lock()
204-
count := len(global.frames)
205-
if count == 0 {
206-
global.framesLock.Unlock()
207-
return
208-
}
209-
var last = -1
210-
for i := count - 1; i >= 0; i-- {
211-
if !global.frames[i].Running() {
212-
last = i
213-
break
214-
}
215-
}
216-
if last == -1 {
217-
global.framesLock.Unlock()
218-
return
219-
}
220-
for _, frame := range global.frames[:last] {
210+
for _, frame := range global.frames {
221211
if !frame.Running() {
222212
go frame.run()
223213
time.Sleep(time.Second)
224214
}
225215
}
226-
frame := global.frames[last]
227216
global.framesLock.Unlock()
228-
frame.run()
217+
global.graceOnce.Do(func() {
218+
graceSignal()
219+
})
229220
}
230221

231222
// Running returns whether the frame service is running.
@@ -237,14 +228,42 @@ func Running(name string, version ...string) bool {
237228
return frame.Running()
238229
}
239230

240-
// Close closes all the frame services.
241-
// TODO: close listeners
242-
func Close() {
231+
// SetFinalizer sets the function which is called after the services shutdown.
232+
func SetFinalizer(finalizer func(context.Context) error) {
233+
global.finalizer = finalizer
234+
}
235+
236+
const (
237+
// SHUTDOWN_TIMEOUT the time-out period for closing the service
238+
SHUTDOWN_TIMEOUT = 1 * time.Minute
239+
)
240+
241+
// Shutdown closes all the frame services gracefully.
242+
func Shutdown(timeout ...time.Duration) {
243+
Print("\x1b[46m[SYS]\x1b[0m shutting down servers...")
243244
global.framesLock.Lock()
244245
defer global.framesLock.Unlock()
246+
var d = SHUTDOWN_TIMEOUT
247+
if len(timeout) > 0 {
248+
d = timeout[0]
249+
}
250+
// shut down gracefully, but wait no longer than d before halting
251+
ctxTimeout, _ := context.WithTimeout(context.Background(), d)
252+
count := new(sync.WaitGroup)
245253
for _, frame := range global.frames {
246-
frame.Close()
254+
count.Add(1)
255+
go func(fm *Framework) {
256+
fm.shutdown(ctxTimeout)
257+
count.Done()
258+
}(frame)
259+
}
260+
count.Wait()
261+
if global.finalizer != nil {
262+
if err := global.finalizer(ctxTimeout); err != nil {
263+
Error(err.Error())
264+
}
247265
}
266+
Print("\x1b[46m[SYS]\x1b[0m servers gracefully stopped.")
248267
CloseLog()
249268
}
250269

0 commit comments

Comments
 (0)