grpc内置了客户端和服务端的请求追踪,基于golang.org/x/net/trace
包实现,默认是开启状态,可以查看事件和请求日志,对于基本的请求状态查看调试也是很有帮助的。
客户端与服务端基本一致,这里以服务端开启trace server为例,修改hello项目服务端代码:
代码示例
package main
import (
"context"
"fmt"
"go_study/framework/grpc/pb" // 导入proto
"golang.org/x/net/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"net"
"net/http"
)
// 定义 UserInfoService 服务
type UserInfoService struct{
pb.UnimplementedUserInfoServiceServer
}
// GetUserInfo 实现方法
func (s *UserInfoService) GetUserInfo(ctx context.Context, req *pb.UserRequest) (resp *pb.UserResponse, err error) {
//err = tokenAuth(ctx)
//if err != nil {
// return nil, err
//}
// 通过用户名查询用户信息
name := req.Name
// 数据里查用户信息
if name == "zs" {
resp = &pb.UserResponse{
Id: 1,
Name: name,
Age: 22,
Hobby: []string{"Sing", "Run"},
}
}
return
}
type HelloService struct {
pb.UnimplementedHelloServiceServer
}
func (h *HelloService) SayHello(ctx context.Context, in *pb.HelloRequest) (resp *pb.HelloResponse, err error) {
//err = tokenAuth(ctx)
//if err != nil {
// return nil, err
//}
resp = new(pb.HelloResponse)
resp.Result = fmt.Sprintf("hello %s", in.Name)
return resp, nil
}
// 使用这种方式验证token 每个服务端每个服务中都验证一次,比较繁琐
func tokenAuth(ctx context.Context) error {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return status.Errorf(codes.Unauthenticated, "无Token认证信息")
}
var (
appid string
appkey string
)
if val, ok := md["appid"]; ok {
appid = val[0]
}
if val, ok := md["appkey"]; ok {
appkey = val[0]
}
if appid != "101010" || appkey != "i am key" {
return status.Errorf(codes.Unauthenticated, "Token认证信息无效: appid=%s, appkey=%s", appid, appkey)
}
return nil
}
// interceptor 拦截器
// grpc.UnaryServerInfo 包含有关服务器端一元 RPC 的各种信息。所有 per-rpc 信息都可能被拦截器改变
func interceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
err := tokenAuth(ctx)
if err != nil {
return nil, err
}
// 继续处理请求
return handler(ctx, req)
}
func init(){
// 新版 grpc 开启 Trace 需要这个
grpc.EnableTracing = true
}
func main(){
// 地址
addr := "127.0.0.1:8180"
// 1.监听
listener, err := net.Listen("tcp", addr)
if err != nil {
grpclog.Fatalf("Failed to listen: %v", err)
}
fmt.Printf("监听端口:%s\n", addr)
// tls认证
creds,err := credentials.NewServerTLSFromFile("./framework/grpc/keys/server.pem", "./framework/grpc/keys/server.key")
if err != nil {
grpclog.Fatalf("Failed to generate credentials %v", err)
}
var opts []grpc.ServerOption
// 添加 tls 认证
opts = append(opts, grpc.Creds(creds))
// 注册拦截器
opts = append(opts, grpc.UnaryInterceptor(interceptor))
// 2.实例化gRPC
s := grpc.NewServer(opts...)
// 3.在gRPC上注册微服务
var u = UserInfoService{}
pb.RegisterUserInfoServiceServer(s, &u)
var h = HelloService{}
pb.RegisterHelloServiceServer(s, &h)
grpclog.Infoln("Listen on " + addr + " with TLS")
// 开启grpc的trace
go startTrace()
// 4.启动服务端
s.Serve(listener)
}
func startTrace() {
trace.AuthRequest = func(req *http.Request) (any, sensitive bool) {
return true, true
}
go http.ListenAndServe(":50051", nil)
grpclog.Infoln("Trace listen on 50051")
}
注意:新版 grpc 需要开启
grpc.EnableTracing = true
,否则只会看到,显示地址的空白。
服务端事件查看
访问:localhost:50051/debug/events
,结果如图:
可以看到 服务端注册的服务 和 服务正常启动 的 事件信息。
请求日志信息查看
访问:localhost:50051/debug/requests
,结果如图:
作者:joker.liu 创建时间:2023-05-23 15:15
最后编辑:joker.liu 更新时间:2023-05-23 15:45
最后编辑:joker.liu 更新时间:2023-05-23 15:45