Skip to content

Commit 7bd525d

Browse files
committed
feat: add logic of prometheus to rpc server and client interceptor, and http middleware
1 parent a9e9092 commit 7bd525d

File tree

11 files changed

+191
-25
lines changed

11 files changed

+191
-25
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Microservice framework implemented based on Golang.
6262
│ │ └─app.go 这个 app 是 GRPC,服务名称,注册中心等的集合
6363
│ ├─code 有一些公用的错误码
6464
│ ├─core 底层共通核心的包
65-
│ │ ├─metric
65+
│ │ ├─metric 服务监控相关的逻辑 使用了 prometheus
6666
│ │ └─trace 链路追踪,采用 opentemlemetry
6767
│ ├─registry
6868
│ │ └─consul 服务注册中心相关逻辑,参考 kratos
@@ -76,9 +76,9 @@ Microservice framework implemented based on Golang.
7676
│ └─rpcserver rpc 服务的初始化配置
7777
│ ├─client.go rpc 客户端的初始化配置
7878
│ ├─server.go rpc 服务端的初始化配置
79-
│ ├─clientinterceptors 客户端的拦截器:超时连接器
79+
│ ├─clientinterceptors 客户端的拦截器:超时连接器,监控 prometheus
8080
│ ├─resolver 服务发现相关的逻辑 解析器
81-
│ │ ├─direct 直连
81+
│ │ ├─direct 直连,加权轮询的时候使用
8282
│ │ └─discovery 服务发现,负载均衡
8383
│ │ ├─builder.go 服务发现的构建器
8484
│ │ └─resolver.go 服务发现的解析器,负载均衡的逻辑在这里实现 UpdateState 核心
@@ -89,7 +89,7 @@ Microservice framework implemented based on Golang.
8989
│ │ ├─p2c 负载均衡 [Power of Two Random Choices] 算法
9090
│ │ ├─random 负载均衡随机算法
9191
│ │ └─wrr 负载均衡 加权轮询 [Weighted Round Robin] 算法
92-
│ └─serverinterceptors 服务端的拦截器:超时,crash恢复
92+
│ └─serverinterceptors 服务端的拦截器:超时,crash恢复,监控
9393
├─pkg
9494
│ ├─app 包括的项目的启动服务,配置文件的读取,命令行工具,以及其他选项
9595
│ │ ├─app.go 服务启动:命令行工具,日志,错误包,配置等

app/shop/admin/http.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ func NewUserHTTPServer(conf *config.Config) (*restserver.Server, error) {
1818
restserver.WithPort(conf.Server.HttpPort),
1919
restserver.WithEnableProfiling(true),
2020
restserver.WithMiddlewares(conf.Server.Middlewares),
21+
restserver.WithEnableProfiling(true),
22+
restserver.WithMetrics(true),
2123
)
2224
//_ = tracerProvider()
2325

app/user/srv/rpc.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ func NewUserRPCServer(cfg *config.Config) (*rpcserver.Server, error) {
2929
userver := user.NewUserServer(srv)
3030

3131
rpcAddr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port)
32-
urpcServer := rpcserver.NewServer(rpcserver.WithAddress(rpcAddr))
32+
urpcServer := rpcserver.NewServer(
33+
rpcserver.WithAddress(rpcAddr),
34+
rpcserver.WithEnableMetric(cfg.Server.EnableMetrics),
35+
)
3336

3437
// 注册 user 模块的 rpc 服务
3538
upbv1.RegisterUserServer(urpcServer.Server, userver)

configs/user/srv.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ registry:
1313
address: 127.0.0.1:8500
1414
scheme: http
1515

16+
server:
17+
name: user-srv #服务名,注册到consul使用的名称
18+
limit: true
19+
host: "127.0.0.1" #host, 默认使用 0.0.0.0
20+
port: 8078 # grpc 安全模式的端口号,默认 8081
21+
http-port: 8088
22+
healthz: true # 是否开启健康检查,如果开启会安装 /healthz 路由,默认 true
23+
enable-metrics: true # 开启 metrics, router: /metrics
24+
profiling: true # 开启性能分析, 可以通过 <host>:<port>/debug/pprof/地址查看程序栈、线程等系统信息,默认值为 true
25+
1626
telemetry:
1727
Name: user-srv
1828
Endpoint: http://127.0.0.1:14268/api/traces

gmicro/server/restserver/options.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,9 @@ func WithCustomMiddlewares(middlewares []gin.HandlerFunc) ServerOption {
5555
s.customMiddlewares = middlewares
5656
}
5757
}
58+
59+
func WithMetrics(metrics bool) ServerOption {
60+
return func(s *Server) {
61+
s.enableMetrics = metrics
62+
}
63+
}

gmicro/server/restserver/server.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import (
1111
"github.com/CoderI421/gframework/gmicro/server/restserver/validation"
1212
"github.com/CoderI421/gframework/pkg/errors"
1313
"github.com/CoderI421/gframework/pkg/log"
14-
1514
"github.com/gin-gonic/gin"
1615
ut "github.com/go-playground/universal-translator"
16+
"github.com/penglongli/gin-metrics/ginmetrics"
1717
)
1818

1919
type JwtInfo struct {
@@ -38,6 +38,8 @@ type Server struct {
3838
healthz bool
3939
//是否开启pprof接口,默认开启,如果开启会自动添加/debug/pprof接口
4040
enableProfiling bool
41+
//是否开启metrics接口,默认开启,如果开启会自动添加/metrics接口
42+
enableMetrics bool
4143
//中间件(拦截器)两种用法 1.提前写好,直接配置名称就可以,用起来方便,比rpc自定义的实现弱,2.自定义gin.HandlerFunc
4244
middlewares []string
4345
customMiddlewares []gin.HandlerFunc
@@ -112,6 +114,20 @@ func (s *Server) Start(ctx context.Context) error {
112114
if s.enableProfiling {
113115
pprof.Register(s.Engine)
114116
}
117+
//根据配置初始化metrics路由
118+
if s.enableMetrics {
119+
// get global Monitor object
120+
m := ginmetrics.GetMonitor()
121+
// +optional set metric path, default /debug/metrics
122+
m.SetMetricPath("/metrics")
123+
// +optional set slow time, default 5s
124+
m.SetSlowTime(10)
125+
// +optional set request duration, default {0.1, 0.3, 1.2, 5, 10}
126+
// used to p95, p99
127+
m.SetDuration([]float64{0.1, 0.3, 1.2, 5, 10})
128+
//反向注入
129+
m.Use(s)
130+
}
115131

116132
// 如果开启了健康检查接口,就添加/health接口
117133
if s.healthz {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package clientinterceptors
2+
3+
import (
4+
"context"
5+
"strconv"
6+
"time"
7+
8+
"github.com/CoderI421/gframework/gmicro/core/metric"
9+
"google.golang.org/grpc"
10+
"google.golang.org/grpc/status"
11+
)
12+
13+
const serverNamespace = "rpc-client"
14+
15+
var (
16+
metricServerReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
17+
VectorOpts: metric.VectorOpts{
18+
Namespace: serverNamespace,
19+
Subsystem: "requests",
20+
Name: "your_service_name_duration_microseconds",
21+
Help: "rpc client requests duration in microseconds",
22+
Labels: []string{"method"}},
23+
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000},
24+
})
25+
26+
metricServerReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
27+
Namespace: serverNamespace,
28+
Subsystem: "requests",
29+
Name: "your_service_status_code_total",
30+
Help: "rpc client requests status code count",
31+
Labels: []string{"method", "code"},
32+
})
33+
)
34+
35+
// UnaryClientPrometheusInterceptor prometheus sclient interceptor.
36+
func UnaryClientPrometheusInterceptor() grpc.UnaryClientInterceptor {
37+
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn,
38+
invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
39+
startTime := time.Now()
40+
err := invoker(ctx, method, req, reply, cc, opts...)
41+
//记录了耗时
42+
metricServerReqDur.Observe(int64(time.Since(startTime)/time.Millisecond), method)
43+
44+
//记录了状态码
45+
metricServerReqCodeTotal.Inc(method, strconv.Itoa(int(status.Code(err))))
46+
return err
47+
}
48+
}

gmicro/server/rpcserver/server.go

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ type Server struct {
4444
metadata *apimd.Server
4545
//设置监听的ip port
4646
endpoint *url.URL
47+
48+
//是否开启 metric 监测
49+
enableMetric bool
4750
}
4851

4952
func (s *Server) Address() string {
@@ -64,7 +67,9 @@ func NewServer(opts ...ServerOption) *Server {
6467
unaryInts := []grpc.UnaryServerInterceptor{
6568
srvints.UnaryCrashInterceptor,
6669
otelgrpc.UnaryServerInterceptor(), // 设置链路追踪的拦截器
67-
//srvints.UnaryTimeoutInterceptor(srv.timeout),
70+
}
71+
if srv.enableMetric {
72+
unaryInts = append(unaryInts, srvints.UnaryServerPrometheusInterceptor)
6873
}
6974
//timeout可以交给用户设置,不设置就不用此拦截器
7075
if srv.timeout > 0 {
@@ -99,34 +104,25 @@ func NewServer(opts ...ServerOption) *Server {
99104
}
100105

101106
func WithAddress(address string) ServerOption {
102-
return func(s *Server) {
103-
s.address = address
104-
}
107+
return func(s *Server) { s.address = address }
105108
}
106109
func WithTimeout(timeout time.Duration) ServerOption {
107-
return func(s *Server) {
108-
s.timeout = timeout
109-
}
110+
return func(s *Server) { s.timeout = timeout }
110111
}
111112
func WithLis(lis net.Listener) ServerOption {
112-
return func(s *Server) {
113-
s.lis = lis
114-
}
113+
return func(s *Server) { s.lis = lis }
115114
}
116115
func WithUnaryInterceptor(in ...grpc.UnaryServerInterceptor) ServerOption {
117-
return func(s *Server) {
118-
s.unaryInts = in
119-
}
116+
return func(s *Server) { s.unaryInts = in }
120117
}
121118
func WithStreamInterceptor(in ...grpc.StreamServerInterceptor) ServerOption {
122-
return func(s *Server) {
123-
s.streamInts = in
124-
}
119+
return func(s *Server) { s.streamInts = in }
125120
}
126121
func WithOptions(opts ...grpc.ServerOption) ServerOption {
127-
return func(s *Server) {
128-
s.grpcOpts = opts
129-
}
122+
return func(s *Server) { s.grpcOpts = opts }
123+
}
124+
func WithEnableMetric(enable bool) ServerOption {
125+
return func(s *Server) { s.enableMetric = enable }
130126
}
131127

132128
// 完成ip和端口的提取
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,52 @@
11
package serverinterceptors
2+
3+
import (
4+
"context"
5+
"strconv"
6+
"time"
7+
8+
"github.com/CoderI421/gframework/gmicro/core/metric"
9+
"google.golang.org/grpc"
10+
"google.golang.org/grpc/status"
11+
)
12+
13+
const serverNamespace = "rpc_server"
14+
15+
var (
16+
metricServerReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
17+
VectorOpts: metric.VectorOpts{
18+
// 服务的名称
19+
Namespace: serverNamespace,
20+
Subsystem: "requests",
21+
Name: "your_service_name_duration_microseconds",
22+
Help: "rpc server requests duration in microseconds",
23+
Labels: []string{"method"},
24+
},
25+
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000},
26+
})
27+
28+
metricServerReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
29+
Namespace: serverNamespace,
30+
Subsystem: "requests",
31+
Name: "your_service_status_code_total",
32+
Help: "rpc server requests status code count",
33+
Labels: []string{"method", "code"},
34+
})
35+
)
36+
37+
// UnaryPrometheusInterceptor prometheus server interceptor.
38+
func UnaryServerPrometheusInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
39+
handler grpc.UnaryHandler) (resp interface{}, err error) {
40+
41+
//进入执行逻辑前
42+
startTime := time.Now()
43+
// 执行请求的逻辑
44+
resp, err = handler(ctx, req)
45+
46+
metricServerReqDur.Observe(int64(time.Since(startTime)/time.Millisecond), info.FullMethod)
47+
48+
//记录了状态码记录那个方法,获取了那个状态码
49+
metricServerReqCodeTotal.Inc(info.FullMethod, strconv.Itoa(int(status.Code(err))))
50+
51+
return
52+
}

go.mod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,11 @@ require (
4545
require (
4646
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
4747
github.com/armon/go-metrics v0.4.0 // indirect
48+
github.com/beorn7/perks v1.0.1 // indirect
49+
github.com/bits-and-blooms/bitset v1.2.0 // indirect
4850
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
4951
github.com/bytedance/sonic v1.8.0 // indirect
52+
github.com/cespare/xxhash/v2 v2.2.0 // indirect
5053
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
5154
github.com/davecgh/go-spew v1.1.1 // indirect
5255
github.com/fsnotify/fsnotify v1.6.0 // indirect
@@ -74,13 +77,19 @@ require (
7477
github.com/mattn/go-colorable v0.1.13 // indirect
7578
github.com/mattn/go-isatty v0.0.17 // indirect
7679
github.com/mattn/go-runewidth v0.0.14 // indirect
80+
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
7781
github.com/mitchellh/go-homedir v1.1.0 // indirect
7882
github.com/mitchellh/mapstructure v1.5.0 // indirect
7983
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
8084
github.com/modern-go/reflect2 v1.0.2 // indirect
8185
github.com/openzipkin/zipkin-go v0.4.1 // indirect
8286
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
87+
github.com/penglongli/gin-metrics v0.1.10 // indirect
8388
github.com/pmezard/go-difflib v1.0.0 // indirect
89+
github.com/prometheus/client_golang v1.12.0 // indirect
90+
github.com/prometheus/client_model v0.2.0 // indirect
91+
github.com/prometheus/common v0.32.1 // indirect
92+
github.com/prometheus/procfs v0.7.3 // indirect
8493
github.com/rivo/uniseg v0.2.0 // indirect
8594
github.com/spf13/afero v1.9.3 // indirect
8695
github.com/spf13/cast v1.5.0 // indirect

0 commit comments

Comments
 (0)