kratos 是一套轻量级的 Go 微服务框架,包含大量微服务相关框架及工具。Kratos 定位为 Go 微服务基础设施层框架 ,类似于 Java 生态中的 Spring Cloud 或 Dubbo。Kratos 致力于提供一套简洁、通用、高效、稳定 的微服务开发框架,帮助开发者快速构建微服务,让开发者更加聚焦于业务交付,而无需关心微服务治理的复杂细节。
接下来我们将学习 Kratos 的基本实现原理,学习掌握一个 Go 微服务框架包含哪些核心组件及其实现原理。首先我们将快速使用 Kratos 搭建一个极简的微服务示例项目。
安装 Kratos CLI 工具
Kratos 提供了官方的 CLI 工具 kratos,用于项目脚手架生成、Proto 文件管理和代码生成。安装方式如下:
1 go install github.com/go -kratos/kratos/cmd/kratos/v2@latest
安装完成后,可以通过以下命令验证:
1 2 $ kratos -v kratos version v2.7.0
使用 CLI 创建项目
Kratos 官方提供了 kratos-layout 模板项目,通过 CLI 工具可以快速创建基于该模板的项目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ kratos new kratos-demo 🚀 Creating service kratos-demo, layout repo is https://github.com/go-kratos/kratos-layout.git, please wait a moment. CREATED kratos-demo/Dockerfile (459 bytes) CREATED kratos-demo/Makefile (2475 bytes) CREATED kratos-demo/api/helloworld/v1/greeter.proto (679 bytes) CREATED kratos-demo/api/helloworld/v1/greeter.pb.go (8074 bytes) CREATED kratos-demo/api/helloworld/v1/greeter_grpc.pb.go (3560 bytes) CREATED kratos-demo/api/helloworld/v1/greeter_http.pb.go (2139 bytes) CREATED kratos-demo/cmd/kratos-demo/main.go (1745 bytes) CREATED kratos-demo/cmd/kratos-demo/wire.go (612 bytes) CREATED kratos-demo/cmd/kratos-demo/wire_gen.go (1108 bytes) CREATED kratos-demo/configs/config.yaml (291 bytes) CREATED kratos-demo/internal/biz/greeter.go (1152 bytes) CREATED kratos-demo/internal/data/greeter.go (836 bytes) CREATED kratos-demo/internal/server/grpc.go (829 bytes) CREATED kratos-demo/internal/server/http.go (834 bytes) CREATED kratos-demo/internal/service/greeter.go (690 bytes) ... 🍺 Project creation succeeded kratos-demo
国内用户可以使用 gitee 源:
1 kratos new kratos-demo -r https://gitee.com/go-kratos/kratos-layout.git
项目结构说明
使用 CLI 工具创建的项目结构遵循 DDD(领域驱动设计)分层架构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 kratos-demo/ ├── Dockerfile # 容器构建文件 ├── Makefile # 构建、生成等自动化命令 ├── openapi.yaml # OpenAPI/Swagger 文档 ├── api/ # Protobuf API 定义及生成的代码 │ └── helloworld/v1/ │ ├── greeter.proto # Greeter 服务的 Proto 定义 │ ├── greeter.pb.go # Protobuf 消息类型(自动生成) │ ├── greeter_grpc.pb.go # gRPC 服务代码(自动生成) │ ├── greeter_http.pb.go # HTTP 路由代码(自动生成) │ ├── error_reason.proto # 错误枚举定义 │ └── error_reason.pb.go ├── cmd/ # 启动入口 │ └── kratos-demo/ │ ├── main.go # 主入口 │ ├── wire.go # Wire 依赖注入声明 │ └── wire_gen.go # Wire 生成代码 ├── configs/ # 配置文件 │ └── config.yaml ├── internal/ # 内部实现(不对外暴露) │ ├── biz/ # 业务逻辑层(DDD domain 层) │ │ ├── biz.go # Wire ProviderSet │ │ └── greeter.go # Greeter 用例 + Repo 接口定义 │ ├── conf/ # 配置结构定义(Proto 生成) │ │ ├── conf.proto # Bootstrap/Server/Data 配置结构 │ │ └── conf.pb.go # 生成的 Go 配置结构体 │ ├── data/ # 数据访问层(DDD repo 实现) │ │ ├── data.go # Wire ProviderSet + Data 初始化 │ │ └── greeter.go # GreeterRepo 实现 │ ├── server/ # HTTP/gRPC Server 创建 │ │ ├── server.go # Wire ProviderSet │ │ ├── http.go # NewHTTPServer │ │ └── grpc.go # NewGRPCServer │ └── service/ # 服务层(DDD application 层) │ ├── service.go # Wire ProviderSet │ └── greeter.go # GreeterService 实现 └── third_party/ # 第三方 Proto 定义 ├── errors/ # 错误 Proto ├── google/api/ # Google API 注解(HTTP mapping) ├── google/protobuf/ # Protobuf 标准类型 ├── openapi/v3/ # OpenAPI 注解 └── validate/ # 校验规则注解
层级
目录
核心文件
职责
DDD 对应
API
api/
greeter.proto
Protobuf 定义 API,自动生成 HTTP/gRPC 代码
-
Service
internal/service/
greeter.go
处理 DTO 转换,协调 biz 交互
Application 层
Biz
internal/biz/
greeter.go
业务逻辑组装,定义 Repo 接口(依赖倒置)
Domain 层
Data
internal/data/
greeter.go, data.go
数据访问,实现 biz 的 Repo 接口
Infrastructure 层
Server
internal/server/
http.go, grpc.go
HTTP/gRPC 实例创建、中间件配置和路由注册
-
Conf
internal/conf/
conf.proto, conf.pb.go
配置结构定义(Bootstrap/Server/Data)
-
Conf(运行时)
configs/
config.yaml
本地调试用的样例配置文件
-
Wire
cmd/kratos-demo/
wire.go, wire_gen.go
依赖注入声明和生成代码
-
Third Party
third_party/
google/api/, validate/
第三方 Proto 定义(HTTP 注解、校验规则)
-
编译运行 CLI 生成的项目
接下来编译运行 CLI 生成的示例项目:
1 2 $ cd kratos-demo $ go build -o ./bin/ ./cmd/kratos-demo/
1 2 3 4 5 6 $ ./bin/kratos-demo -conf ./configs 2026/05/16 19:41:26 maxprocs: Leaving GOMAXPROCS=4: CPU quota undefined DEBUG msg=config loaded: config.yaml format: yaml INFO ts=2026-05-16T19:41:26+08:00 caller =http/server.go:330 service.id=OPS-3430 service.name= service.version= trace.id= span.id= msg=[HTTP] server listening on: [::]:8000 INFO ts=2026-05-16T19:41:26+08:00 caller =grpc/server.go:231 service.id=OPS-3430 service.name= service.version= trace.id= span.id= msg=[gRPC] server listening on: [::]:9000
测试 HTTP 服务
测试 HTTP 接口(Greeter 服务的 SayHello 通过 Proto 中的 google.api.http 注解暴露为 GET /helloworld/{name}):
1 2 $ curl http://localhost:8000/helloworld/kratos {"message" :"Hello kratos" }
测试 gRPC 服务
测试 gRPC 接口(使用 grpcurl 工具,Kratos 的 gRPC Server 默认开启了 reflection 服务):
1 2 3 4 5 6 7 $ grpcurl -plaintext localhost:9000 list grpc.health.v1.Health grpc.reflection.v1.ServerReflection grpc.reflection.v1alpha.ServerReflection helloworld.v1.Greeter kratos.api.Metadata
1 2 3 4 5 6 7 8 $ grpcurl -plaintext localhost:9000 describe helloworld.v1.Greeter helloworld.v1.Greeter is a service: service Greeter { rpc SayHello ( .helloworld.v1.HelloRequest ) returns ( .helloworld.v1.HelloReply ) { option (.google.api.http) = { get: "/helloworld/{name}" }; }; }
1 2 3 4 5 $ grpcurl -plaintext -d '{"name":"kratos"}' localhost:9000 helloworld.v1.Greeter/SayHello { "message" : "Hello kratos" }
可以看到,通过同一个 Proto 定义,Kratos 自动生成了 HTTP 和 gRPC 两套服务代码,客户端可以选择任一协议访问。
CLI 生成项目的入口代码
测试完服务后,我们再看一下通过 CLI 生成的示例项目的入口代码,以对 kratos 的基本结构有更直观的认识。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 package mainimport ( "flag" "os" "kratos-demo/internal/conf" "github.com/go-kratos/kratos/v2" "github.com/go-kratos/kratos/v2/config" "github.com/go-kratos/kratos/v2/config/file" "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/middleware/tracing" "github.com/go-kratos/kratos/v2/transport/grpc" "github.com/go-kratos/kratos/v2/transport/http" _ "go.uber.org/automaxprocs" ) var ( Name string Version string flagconf string id, _ = os.Hostname() ) func init () { flag.StringVar(&flagconf, "conf" , "../../configs" , "config path, eg: -conf config.yaml" ) } func newApp (logger log.Logger, gs *grpc.Server, hs *http.Server) *kratos.App { return kratos.New( kratos.ID(id), kratos.Name(Name), kratos.Version(Version), kratos.Metadata(map [string ]string {}), kratos.Logger(logger), kratos.Server( gs, hs, ), ) } func main () { flag.Parse() logger := log.With(log.NewStdLogger(os.Stdout), "ts" , log.DefaultTimestamp, "caller" , log.DefaultCaller, "service.id" , id, "service.name" , Name, "service.version" , Version, "trace.id" , tracing.TraceID(), "span.id" , tracing.SpanID(), ) c := config.New( config.WithSource( file.NewSource(flagconf), ), ) defer c.Close() if err := c.Load(); err != nil { panic (err) } var bc conf.Bootstrap if err := c.Scan(&bc); err != nil { panic (err) } app, cleanup, err := wireApp(bc.Server, bc.Data, logger) if err != nil { panic (err) } defer cleanup() if err := app.Run(); err != nil { panic (err) } }
可以看到几个关键点:
kratos.New() :通过 Option 模式配置应用,接受 ID、Name、Version、Logger、Server 等选项
config.New() + config.WithSource() :加载配置文件
wireApp() :通过 Wire 依赖注入组装所有组件
app.Run() :启动应用,管理所有 Server 的生命周期
手动构建一个极简微服务
虽然 CLI 工具可以快速生成完整的项目模板(包含 Wire、Proto、DDD 分层),但为了深入理解 Kratos 的核心概念,我们从头手动构建一个极简的微服务项目。这个项目同时支持 HTTP 和 gRPC 双协议,不依赖 Wire 和 Protobuf。
项目初始化
1 2 mkdir helloworld && cd helloworldgo mod init helloworld
编写主程序
Kratos 应用的核心是 kratos.New() 函数,它通过 Option 模式 来配置应用。一个最简的 Kratos 应用只需要创建 HTTP 和/或 gRPC Server,然后交给 kratos.App 管理生命周期:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 package mainimport ( "context" "encoding/json" "fmt" "log" "net/http" "github.com/go-kratos/kratos/v2" "github.com/go-kratos/kratos/v2/middleware/recovery" "github.com/go-kratos/kratos/v2/transport/grpc" khttp "github.com/go-kratos/kratos/v2/transport/http" ) func main () { httpSrv := khttp.NewServer( khttp.Address(":8000" ), khttp.Middleware( recovery.Recovery(), ), ) registerHTTPRoutes(httpSrv) grpcSrv := grpc.NewServer( grpc.Address(":9000" ), grpc.Middleware( recovery.Recovery(), ), ) app := kratos.New( kratos.Name("helloworld" ), kratos.Version("v1.0.0" ), kratos.Server(httpSrv, grpcSrv), kratos.AfterStart(func (ctx context.Context) error { fmt.Println("helloworld service started!" ) fmt.Println(" HTTP: http://localhost:8000" ) fmt.Println(" gRPC: localhost:9000" ) return nil }), ) if err := app.Run(); err != nil { log.Fatal(err) } } func registerHTTPRoutes (srv *khttp.Server) { srv.HandleFunc("/hello" , func (w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type" , "application/json" ) json.NewEncoder(w).Encode(map [string ]string { "message" : "Hello, Kratos!" , }) }) srv.Route("/v1" ).GET("/hello/{name}" , func (ctx khttp.Context) error { name := ctx.Vars().Get("name" ) return ctx.JSON(200 , map [string ]string { "message" : "Hello, " + name + "!" , }) }) srv.Route("/v1" ).POST("/hello" , func (ctx khttp.Context) error { var req struct { Name string `json:"name"` } if err := ctx.Bind(&req); err != nil { return err } return ctx.JSON(200 , map [string ]string { "message" : "Hello, " + req.Name + "!" , }) }) }
注意 transport/http 包与标准库 net/http 包名冲突,需要使用别名导入:
1 khttp "github.com/go-kratos/kratos/v2/transport/http"
这个例子展示了 Kratos 的几个核心概念:
kratos.New() :创建应用实例,通过 Option 模式配置
khttp.NewServer() / grpc.NewServer() :创建传输层 Server
kratos.Server() :将 Server 注册到 App,由 App 统一管理启动和停止
recovery.Recovery() :内置中间件,自动捕获 panic
kratos.AfterStart() :生命周期钩子,在服务启动后执行自定义逻辑
运行测试服务
通过如下命令启动服务:
1 2 3 4 5 6 7 INFO msg=[gRPC] server listening on: [::]:9000 INFO msg=[HTTP] server listening on: [::]:8000 helloworld service started! HTTP: http://localhost:8000 gRPC: localhost:9000
测试 HTTP 接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ curl http://localhost:8000/hello {"message" :"Hello, Kratos!" } $ curl http://localhost:8000/v1/hello/Kratos {"message" :"Hello, Kratos!" } $ curl -X POST http://localhost:8000/v1/hello \ -H "Content-Type: application/json" \ -d '{"name":"World"}' {"message" :"Hello, World!" }
查看 gRPC 服务:
1 2 3 4 5 6 grpc.channelz.v1.Channelz grpc.health.v1.Health grpc.reflection.v1.ServerReflection grpc.reflection.v1alpha.ServerReflection kratos.api.Metadata
Kratos HTTP Context 接口
上面的例子中,Kratos 的 HTTP Server 提供了两种路由注册方式:
标准库风格 :srv.HandleFunc(path, handler),handler 签名为 func(w http.ResponseWriter, r *http.Request)
Kratos Context 风格 :srv.Route(prefix).GET/POST(path, handler),handler 签名为 func(ctx http.Context) error
Kratos 的 Context 接口提供了丰富的请求处理能力:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 type Context interface { context.Context Vars() url.Values Query() url.Values Form() url.Values Header() http.Header Request() *http.Request Response() http.ResponseWriter Bind(any) error BindVars(any) error BindQuery(any) error Returns(any, error ) error JSON(int , any) error String(int , string ) error }
完整示例:带配置管理的微服务
接下来我们实现一个完整的示例,将配置管理、HTTP/gRPC 双协议、中间件组合在一起。
项目结构
如下是这个示例项目的结构
1 2 3 4 5 6 7 . ├── configs │ └── config.yaml ├── go.mod ├── go.sum ├── main.go
configs/config.yaml 配置文件的内容如下:
1 2 3 4 5 6 7 server: name: helloworld version: v1.0.0 http: addr: ":8000" grpc: addr: ":9000"
主程序
如下则展示了 main.go 的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 package mainimport ( "context" "encoding/json" "fmt" "log" "net/http" "os" "github.com/go-kratos/kratos/v2" "github.com/go-kratos/kratos/v2/config" "github.com/go-kratos/kratos/v2/config/file" klog "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/middleware/recovery" "github.com/go-kratos/kratos/v2/transport/grpc" khttp "github.com/go-kratos/kratos/v2/transport/http" ) type Bootstrap struct { Server *ServerConfig `json:"server"` } type ServerConfig struct { Name string `json:"name"` Version string `json:"version"` HTTP *EndpointConfig `json:"http"` GRPC *EndpointConfig `json:"grpc"` } type EndpointConfig struct { Addr string `json:"addr"` } func main () { logger := klog.NewStdLogger(os.Stdout) c := config.New( config.WithSource(file.NewSource("configs/config.yaml" )), ) if err := c.Load(); err != nil { log.Fatal(err) } var bc Bootstrap if err := c.Scan(&bc); err != nil { log.Fatal(err) } fmt.Printf("Loaded config: service=%s version=%s http=%s grpc=%s\n" , bc.Server.Name, bc.Server.Version, bc.Server.HTTP.Addr, bc.Server.GRPC.Addr) httpSrv := khttp.NewServer( khttp.Address(bc.Server.HTTP.Addr), khttp.Middleware(recovery.Recovery()), ) registerHTTPRoutes(httpSrv, &bc) grpcSrv := grpc.NewServer( grpc.Address(bc.Server.GRPC.Addr), grpc.Middleware(recovery.Recovery()), ) app := kratos.New( kratos.Name(bc.Server.Name), kratos.Version(bc.Server.Version), kratos.Server(httpSrv, grpcSrv), kratos.Logger(logger), kratos.AfterStart(func (ctx context.Context) error { fmt.Printf("%s service started!\n" , bc.Server.Name) fmt.Printf(" HTTP: http://localhost%s\n" , bc.Server.HTTP.Addr) fmt.Printf(" gRPC: localhost%s\n" , bc.Server.GRPC.Addr) return nil }), ) if err := app.Run(); err != nil { log.Fatal(err) } } func registerHTTPRoutes (srv *khttp.Server, bc *Bootstrap) { srv.HandleFunc("/hello" , func (w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type" , "application/json" ) json.NewEncoder(w).Encode(map [string ]string { "message" : "Hello, Kratos!" , "service" : bc.Server.Name, "version" : bc.Server.Version, }) }) srv.Route("/v1" ).GET("/hello/{name}" , func (ctx khttp.Context) error { name := ctx.Vars().Get("name" ) return ctx.JSON(200 , map [string ]string { "message" : "Hello, " + name + "!" , "service" : bc.Server.Name, "version" : bc.Server.Version, }) }) srv.Route("/v1" ).POST("/hello" , func (ctx khttp.Context) error { var req struct { Name string `json:"name"` } if err := ctx.Bind(&req); err != nil { return err } return ctx.JSON(200 , map [string ]string { "message" : "Hello, " + req.Name + "!" , "service" : bc.Server.Name, "version" : bc.Server.Version, }) }) }
运行测试服务
1 2 3 4 5 6 7 8 DEBUG msg=config loaded: config.yaml format: yaml Loaded config: service=helloworld version=v1.0.0 http=:8000 grpc=:9000 INFO msg=[gRPC] server listening on: [::]:9000 INFO msg=[HTTP] server listening on: [::]:8000 helloworld service started! HTTP: http://localhost:8000 gRPC: localhost:9000
测试 HTTP 接口:
1 2 3 4 5 6 7 8 9 10 $ curl http://localhost:8000/hello {"message" :"Hello, Kratos!" ,"service" :"helloworld" ,"version" :"v1.0.0" } $ curl http://localhost:8000/v1/hello/Kratos {"message" :"Hello, Kratos!" ,"service" :"helloworld" ,"version" :"v1.0.0" } $ curl -X POST http://localhost:8000/v1/hello \ -H "Content-Type: application/json" \ -d '{"name":"World"}' {"message" :"Hello, World!" ,"service" :"helloworld" ,"version" :"v1.0.0" }
查看 grpc 服务
1 2 3 4 5 6 grpc.channelz.v1.Channelz grpc.health.v1.Health grpc.reflection.v1.ServerReflection grpc.reflection.v1alpha.ServerReflection kratos.api.Metadata
小结
这篇文章我们学习了 Kratos 的快速使用方法:包含通过 kratos new 命令基于官方模板创建项目、手动基于 kratos 包创建微服务项目,这为我们后续详细分析 kratos 框架的实现打下了基础。