Kratos的RPC调用本质是gRPC调用,依赖protoc-gen-go-grpc插件生成NewXXXClient等客户端接口,底层走HTTP/2二进制流;需确保插件安装正确、grpc.Server已启动并传入kratos.New,客户端通过NewXXXClient复用连接池发起调用,地址格式须为"127.0.0.1:9000"或"dns:///service-name",禁用http://前缀。

Kratos 的 RPC 调用本质就是 gRPC 调用,不是自研协议,也不走 HTTP 客户端;直接用生成的 XXXClient 接口发请求,底层走的是二进制 gRPC 流。
proto 编译后没有 RegisterXXXServiceServer 和 NewXXXClient?
这是插件没装全或命令没跑对的典型表现。Kratos 的 gRPC 代码生成依赖两个核心插件协同工作:
-
protoc-gen-go-grpc:生成服务注册函数(如RegisterGreeterServiceServer)和客户端 stub(如NewGreeterServiceClient) -
protoc-gen-go-http:生成 HTTP 映射逻辑(如registerGreeterServiceHandlerFromEndpoint),但不影响 RPC 调用本身
只装 protoc-gen-go(老版)或只跑 kratos proto client 不够——必须确保 protoc-gen-go-grpc 已安装且在 PATH 中,并用 kratos proto server 或完整 protoc 命令触发它。检查生成的 *_grpc.pb.go 文件里是否有 NewXXXClient 函数体,没有就重装插件再生成。
service.Register() 报 rpc error: code = Unavailable desc = connection closed
这个错误和网络无关,是本进程内 gRPC Server 根本没起来导致的。因为 service.Register() 是向本地已运行的 grpc.Server 实例注册服务,不是发远程请求。
- 确认
grpc.NewServer()被调用,且返回值非nil(比如 consul 初始化失败时可能静默返回nil) - 确认该
grpc.Server实例被传入kratos.New(kratos.Server(httpSrv, grpcSrv)),漏传等于没启 - 监听地址别写
localhost:9000:某些容器或 CI 环境下localhost解析失败,改用0.0.0.0:9000 - 如果项目纯 HTTP、完全不用 gRPC,就别调
service.Register()—— 它和 REST 接口完全解耦
客户端怎么发起 gRPC 调用?不是用 http.Client,也不是手写 dial
Kratos 生成的 client 代码已经封装好连接池和重试逻辑,直接 new 出来用即可。关键点在于传入的 context.Context 和目标地址。
- 地址格式必须是
"127.0.0.1:9000"或"dns:///service-name"(配合服务发现),不能带http://前缀 - 推荐用
grpc.WithTransportCredentials(insecure.NewCredentials())开发期跳过 TLS,生产环境必须配证书 - 不要自己反复
grpc.Dial:连接应复用,Kratos 的NewXXXClient内部已处理连接池 - 示例片段:
conn, _ := grpc.Dial("127.0.0.1:9000", grpc.WithTransportCredentials(insecure.NewCredentials()))<br>client := v1.NewGreeterServiceClient(conn)<br>resp, _ := client.SayHello(context.Background(), &v1.HelloRequest{Name: "kratos"})
为什么 ctx.Value() 在 gRPC 客户端拿不到 transport 信息?
Kratos 的 transport.Context 是单向注入的:服务端从 gRPC/HTTP 请求中提取 kind、operation、reqid 等并塞进 ctx,但客户端发请求时不会反向把本地 ctx.Value 自动透传过去——那是跨进程边界,需要显式传递 metadata。
- 想让服务端收到自定义字段,得用
metadata.Pairs("x-user-id", "123")构造metadata.MD,再通过grpc.Header(&md)或grpc.Trailer(&md)传 -
transport.Kind这类基础字段由 Kratos 框架在服务端自动注入,客户端无需、也无法设置 - 中间件里取
transport.FromServerContext(ctx)才能拿到服务端解析出的 transport 信息,别直接ctx.Value(transport.KindKey)
真正容易被忽略的是:gRPC 调用的 endpoint 地址、TLS 配置、metadata 透传这三者,必须和服务端监听配置严格对齐,差一个字符(比如多写个 / 或少写端口)都会导致 Unavailable,而不是更具体的错误码。


















