/
main.go
140 lines (112 loc) · 3.57 KB
/
main.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"context"
"flag"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"
"time"
"github.com/daheige/thinkgo/gpprof"
"github.com/daheige/thinkgo/logger"
"github.com/daheige/thinkgo/monitor"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
_ "go.uber.org/automaxprocs"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"github.com/daheige/go-proj/app/rpc/middleware"
"github.com/daheige/go-proj/app/rpc/service"
config "github.com/daheige/go-proj/conf"
"github.com/daheige/go-proj/pb"
)
var (
port int
logDir string
configDir string
wait time.Duration // 平滑重启的等待时间1s or 1m
)
func init() {
flag.IntVar(&port, "port", 50051, "grpc port")
flag.StringVar(&logDir, "log_dir", "./logs", "log dir")
flag.StringVar(&configDir, "config_dir", "./", "config dir")
flag.DurationVar(&wait, "graceful-timeout", 3*time.Second, "the server gracefully reload. eg: 15s or 1m")
flag.Parse()
// 日志文件设置
logger.SetLogDir(logDir)
logger.SetLogFile("go-grpc.log")
logger.MaxSize(500)
logger.TraceFileLine(true) // 开启文件名和行数追踪
// 由于app/extensions/logger基于thinkgo/logger又包装了一层,所以这里是3
logger.InitLogger(3)
// 初始化配置文件
config.InitConf(configDir)
config.InitRedis()
// 添加prometheus性能监控指标
prometheus.MustRegister(monitor.CpuTemp)
prometheus.MustRegister(monitor.HdFailures)
// 性能监控的端口port+1000,只能在内网访问
httpMux := gpprof.New()
// 添加prometheus metrics处理器
httpMux.Handle("/metrics", promhttp.Handler())
gpprof.Run(httpMux, port+1000)
}
func main() {
lis, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
opts := make([]grpc.ServerOption, 0, 4)
// 设置超时10s
opts = append(opts, grpc.ConnectionTimeout(10*time.Second))
// 注册interceptor和中间件
opts = append(opts, grpc.UnaryInterceptor(
middleware.ChainUnaryServer(
middleware.RequestInterceptor,
middleware.Limit(&middleware.MockPassLimiter{}),
)))
server := grpc.NewServer(opts...)
pb.RegisterGreeterServiceServer(server, &service.GreeterService{})
// register reflection service on gRPC server.
reflection.Register(server)
// 其他grpc拦截器用法,看go grpc源代码,里面都有对应的方法
// Go-gRPC 实践指南 https://www.bookstack.cn/read/go-grpc/chapter2-interceptor.md
log.Println("go-proj grpc run on:", port)
go func() {
defer logger.Recover()
if err = server.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}()
// 平滑重启
ch := make(chan os.Signal, 1)
// We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C)
// recivie signal to exit main goroutine
// window signal
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
// linux signal,please use this in production.
// signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR2, os.Interrupt, syscall.SIGHUP)
// Block until we receive our signal.
sig := <-ch
log.Println("exit signal: ", sig.String())
done := make(chan struct{}, 1)
// Create a deadline to wait for.
ctx, cancel := context.WithTimeout(context.Background(), wait)
defer cancel()
go func() {
defer close(done)
server.GracefulStop()
}()
select {
case <-done:
log.Println("shutdown success")
case <-ctx.Done():
e := ctx.Err()
logger.Error("server shutdown timeout", map[string]interface{}{
"trace_error": e.Error(),
})
log.Println("shutdown timeout,reason: ", e.Error())
}
}