kratos要求接口版本必须在protobuf中显式声明,package名需与url路径版本段严格一致(如helloworld.v1),并配合google.api.http option才能生成对应http路由;grpc需分版本生成代码、独立server注册;动态开关需手动读取配置控制register调用。

接口版本规划:从Protobuf定义开始
Kratos要求所有HTTP/gRPC接口的版本信息必须在Protobuf IDL中显式声明,不能靠URL路径或Header临时补救。
在api/helloworld/v1/helloworld.proto中,将package名设为helloworld.v1,这是框架识别版本边界的唯一依据;若写成helloworld.v1alpha或helloworld.v1_beta,kratos generate将无法生成对应版本的HTTP路由注册代码。
service Greeter { rpc SayHello(SayHelloRequest) returns (SayHelloReply); } 必须配合option (google.api.http) = { get: "/helloworld/v1/say_hello" }; 才能触发v1路由绑定;缺少该option时,即使package是v1,生成器也不会注册HTTP handler。
【package名必须与URL路径中版本段严格一致】,例如路径用/helloworld/v2/,则package必须为helloworld.v2,否则运行时请求404且无提示。
HTTP路由自动注册机制
Kratos在启动时扫描internal/server/http.go中http.NewServer()传入的所有RegisterXXXHandler函数,这些函数由protoc-gen-go-http插件自动生成。
方法一:使用kratos proto client命令生成完整服务骨架,其中已包含按v1/v2分目录的Register函数调用链;直接运行kratos run即可加载全部路由。
方法二:手动注册——在http.go里显式调用v1.RegisterGreeterHTTPServer(mux, srv),但必须确保srv实现了v1.GreeterServer接口;若srv是v2版实现却注册到v1 handler,运行时报panic: interface conversion错误。
方法三:混合版本共存——在同一个HTTP Server中同时注册v1.RegisterGreeterHTTPServer和v2.RegisterGreeterHTTPServer,前提是两个Register函数操作的是不同path前缀(如/helloworld/v1/与/helloworld/v2/),否则后注册者覆盖前者。
gRPC路由版本隔离配置
第一步:确认proto文件中service定义已添加version选项。在helloworld.proto顶部添加option go_package = "github.com/go-kratos/kratos/examples/helloworld/api/helloworld/v1;v1";
第二步:执行kratos proto client -t api/helloworld/v1/helloworld.proto生成v1版Go代码;重复该命令并修改-t参数为api/helloworld/v2/生成v2版,两套代码会输出到不同目录。
第三步:在internal/service/greeter.go中,分别实现v1.GreeterServer和v2.GreeterServer两个接口;注意两个实现不可共用同一struct指针,否则gRPC Server注册时类型断言失败。
第四步:在main.go中创建两个独立gRPC Server实例,分别绑定不同端口(如:9000和:9001),各自注册对应版本的service;【不可在同一个grpc.Server上调用两次RegisterGreeterServer】,否则第二次调用会panic: grpc: attempting to register duplicate service。
动态路由开关:通过配置控制版本可见性
在configs/config.yaml中添加api_versions字段:
api_versions:
helloworld.v1: true
helloworld.v2: false
然后在http server初始化逻辑中读取该配置,仅对值为true的版本调用其Register函数;未启用的版本不会暴露任何路由,也不会出现在生成的Swagger文档中。
这一步需要手动修改internal/server/http.go,在Register调用前插入config.GetBool("api_versions.helloworld.v2")判断;框架本身不提供自动路由开关能力,必须编码介入。











