kratos grpc开发必须从.proto定义出发自动生成骨架,proto文件须置于api/目录下且package名与路径一致,否则代码生成失败或运行异常。

Kratos 的 gRPC 开发不是“先写代码再配协议”,而是“从 .proto 定义出发,自动生成骨架,再填业务逻辑”——跳过这一步,后续所有客户端调用、服务注册、HTTP 网关都会出问题。
proto 文件必须放在 api/xxx/xxx.proto 路径下
Kratos 的代码生成工具(kratos proto client / kratos proto server)默认只扫描 api/ 子目录下的 .proto 文件。如果把文件放到 proto/ 或 internal/api/ 下,命令会静默失败,不报错也不生成代码。
- 正确路径示例:
api/metadata/metadata.proto、api/greeter/greeter.proto - package 名必须与目录结构一致,比如
api/greeter/greeter.proto应设为package kratos.api.greeter;,否则生成的 Go 包路径会错乱 - 必须 import
"google/api/annotations.proto"才能启用 HTTP 映射;该文件需通过protoc-gen-go-http插件支持,缺了它option (google.api.http) = { get: "/hello" };就无效
kratos proto server 生成的服务模板不直接可运行
执行 kratos proto server api/greeter/greeter.proto -t internal/service 后,生成的 greeter_service.go 只是空壳:接口方法体全是 return nil, errors.New("unimplemented"),且没注册到 gRPC Server 实例上。
- 你得手动在
internal/server/grpc.go中调用pb.RegisterGreeterServer,传入自己实现的 service 结构体 - 生成的 service 结构体默认嵌入了
UnimplementedGreeterServer,这是为了向前兼容;但如果你删掉它,又没实现全部方法,gRPC Server 启动时会 panic:“missing implementation for …” - 别忽略
internal/service/greeter_service.go里自动生成的var _ pb.GreeterServer = (*GreeterService)(nil)这行断言——它确保类型实现完整,删了可能编译通过但运行时报错
gRPC 客户端初始化必须显式配置 grpc.WithTransportCredentials
本地开发时若用明文连接(即不走 TLS),容易漏掉 grpc.WithTransportCredentials(insecure.NewCredentials()),导致 context deadline exceeded 或直接 panic:“credentials: no credentials specified”。
- 使用 Kratos 的
grpc.Dial工厂时,必须传入grpc.ClientOption列表,其中至少包含传输凭据配置 - 生产环境应换为
credentials.NewTLS(tlsConfig),且服务端ServerOption中的TLSConfig必须与之匹配,否则握手失败 - 如果启用了服务发现(如 etcd),
grpc.WithResolvers和grpc.WithAuthority也得一并配好,否则解析不到实例地址
中间件链顺序反向执行,Chain 函数参数越靠后越先执行
Kratos 的 middleware.Chain 把中间件列表倒序拼接,意味着你在 NewServer 里写的 middleware.Chain(m1, m2, m3),实际执行顺序是 m3 → m2 → m1 → handler。
- 日志中间件通常要放在最外层(即参数列表最后),才能包住耗时统计、panic 捕获等所有环节
- 认证中间件如果依赖上下文里的 token 解析结果,就不能放在日志之后但又在鉴权之前——位置错一位,
ctx.Value就取不到 - 自定义中间件返回
Handler时,务必调用next(ctx, req),漏掉这句会导致请求静默丢失,无错误、无响应
真正卡住人的地方往往不是语法,而是 protoc 插件版本和 Kratos CLI 版本不匹配导致生成代码字段缺失,或者 go.mod 里 google.golang.org/grpc 版本与 Kratos v2.11+ 内置的拦截器签名不兼容——这些不会在 go build 阶段报错,而是在运行时 dial 失败或 panic。











