-
Notifications
You must be signed in to change notification settings - Fork 1
/
app.go
119 lines (113 loc) · 3.1 KB
/
app.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package app
import (
"context"
"fmt"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/pflag"
ah "github.com/zhifeifu/fwds/internal/api/http"
"github.com/zhifeifu/fwds/internal/job"
"github.com/zhifeifu/fwds/internal/router"
"github.com/zhifeifu/fwds/pkg/config"
"github.com/zhifeifu/fwds/pkg/db"
"github.com/zhifeifu/fwds/pkg/email"
"github.com/zhifeifu/fwds/pkg/log"
"github.com/zhifeifu/fwds/pkg/redis"
"github.com/zhifeifu/fwds/pkg/trace"
"github.com/zhifeifu/fwds/pkg/valid"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func Flag() string {
var cfgFile = pflag.StringP("config", "c", "", "fwds config file path")
pflag.Parse()
return *cfgFile
}
func Run() {
//获取启动时带的参数
cfgFile := Flag()
//初始化配置
cfg, err := config.Init(cfgFile)
if err != nil {
panic(cfg)
}
//日志初始化
log.Init(&cfg.Log)
//数据库初始化
db.Init(cfg.Mysql)
//redis初始化
redis.Init(&cfg.Redis)
//链路跟踪初始化
trace.Init(cfg)
// Set gin mode.
gin.SetMode(cfg.App.Mode)
// 邮箱客户端 初始化
email.Init(&cfg.Email)
// 定时任务初始化
job.Init()
// http 服务
HttpService(cfg)
}
func pprof(cfg *config.AppConfig) {
go func() {
fmt.Printf("Listening and serving PProf HTTP on %s\n", cfg.PprofPort)
if err := http.ListenAndServe(cfg.PprofPort, http.DefaultServeMux); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen ListenAndServe for PProf, err: %s", err.Error())
}
}()
}
func HttpService(cfg *config.Config) {
// Create the Gin engine.
ge := gin.Default()
//custom validator
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
_ = v.RegisterValidation("phone", valid.Phone)
}
// HealthCheck 健康检查路由
ge.GET("/health", ah.HealthCheck)
// metrics router 可以在 prometheus 中进行监控
ge.GET("/metrics", gin.WrapH(promhttp.Handler()))
// API Routes.
router.Load(ge)
log.Infof("Start to listening the incoming requests on http address: %s", cfg.Http.Addr)
srv := &http.Server{
Addr: cfg.Http.Addr,
Handler: ge,
}
go func() {
// service connections
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s", err.Error())
}
}()
gracefulStop(srv)
}
// gracefulStop 优雅退出
// 等待中断信号以超时 5 秒正常关闭服务器
// 官方说明:https://github.com/gin-gonic/gin#graceful-restart-or-stop
func gracefulStop(srv *http.Server) {
quit := make(chan os.Signal)
// kill 命令发送信号 syscall.SIGTERM
// kill -2 命令发送信号 syscall.SIGINT
// kill -9 命令发送信号 syscall.SIGKILL
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Info("Shutdown Server ...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server Shutdown:", err)
}
// 5 秒后捕获 ctx.Done() 信号
select {
case <-ctx.Done():
log.Info("timeout of 5 seconds.")
default:
}
log.Info("Server exiting")
}