req + req_id -> http-server -> grpc-client -> grpc-server
客户端/web生成req_id, 在通参中传递到http-server, 加入到request.context上.
return func(w http.ResponseWriter, r *http.Request) {
reqID := r.URL.Query().Get("request_id")
if reqID == "" {
reqID = UUID()
}
r = r.WithContext(context.WithValue(r.Context(), "req_id", reqID))
...
}
grpc-client调用时, 通过metadata将req_id传递到grpc-server上.
func WithOutgoingReqID(ctx context.Context) context.Context {
rawid := ctx.Value(constant.ReqIDKey)
if rawid != nil {
if reqid, ok := rawid.(string); ok {
return metadata.AppendToOutgoingContext(ctx, constant.ReqIDKey, reqid)
}
}
reqid := program.StrUUID()
return metadata.AppendToOutgoingContext(ctx, constant.ReqIDKey, reqid)
}
call(ctx context.Context) {
ctx = WithOutgoingReqID(ctx)
}
grpc-server是handle函数的ctx参数中,提取req-id,以及客户端地址.
func GetReqInfo(ctx context.Context) (reqid string, ip string) {
rreqid := ctx.Value(constant.ReqIDKey)
if s, ok := rreqid.(string); ok {
reqid = s
}
p, ok := peer.FromContext(ctx)
if ok {
ip = p.Addr.String()
}
return
}