# go-grpc + context 请求打通 req + req_id -> http-server -> grpc-client -> grpc-server 客户端/web生成req_id, 在通参中传递到http-server, 加入到request.context上. ```go 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上. ```go 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,以及客户端地址. ```go 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 } ```