1. 目标:
a. 欲自定义一个捕捉grpc-server里面的全局代码500报错(panic报错)的中间件。
b. grpc中间件与http-gin定义中间件不一样,gin可以用use或handlerFunc启用中间件,grpc用不了。这里以go-grpc-middleware插件来演示。
c. gRPC-Client只作为主动调用接口没必要去做中间件。
2. 书写中间件:
安装插件依赖:
go get github.com/grpc-ecosystem/go-grpc-middleware
中间件全部代码,其中返回值类型为固定的形式(为go-grpc-middleware插件返回最值形式):
package middlewares
import (
"context"
"fmt"
"google.golang.org/grpc"
)
// StreamGSError500 捕捉流式代码致命错误
func StreamGSError500(address string) grpc.StreamServerInterceptor {
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) (err error) {
fmt.Println("StreamGSError500 服务已经加入监听===")
defer func() {
if err := recover(); err != nil {
//打印错误堆栈信息
fmt.Println(err)
}
}()
err = handler(srv, stream)
return err
}
}
// UnaryGSError500 捕捉简单代码致命错误
func UnaryGSError500(address string) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (_ interface{}, err error) {
fmt.Println("UnaryGSError500 服务已经加入监听===")
defer func() {
if err := recover(); err != nil {
//打印错误堆栈信息
fmt.Println(err)
}
}()
resp, err := handler(ctx, req)
return resp, err
}
}
3. 启动grpc-server时加入中间件:
引入:
import (
"github.com/grpc-ecosystem/go-grpc-middleware"
grpcRecovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
"google.golang.org/grpc"
)
启动:
var address string = "127.0.0.1:9600"
// 实例化grpc服务端,并插入中间价
grpcServer := grpc.NewServer(
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer( // 流式拦截器
middlewares.StreamGSError500(address),
grpcRecovery.StreamServerInterceptor(),
)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( // 简单拦截器
middlewares.UnaryGSError500(address),
grpcRecovery.StreamServerInterceptor(),
)),
)
-