Kratos 一套轻量级 Go 微服务框架,包含大量微服务相关框架及工具。
1. 介绍
1.1 特性
- APIs :协议通信以 HTTP/gRPC 为基础,通过 Protobuf 进行定义;
- Errors :通过 Protobuf 的 Enum 作为错误码定义,以及工具生成判定接口;
- Metadata :在协议通信 HTTP/gRPC 中,通过 Middleware 规范化服务元信息传递;
- Config :支持多数据源方式,进行配置合并铺平,通过 Atomic 方式支持动态配置;
- Logger :标准日志接口,可方便集成三方 log 库,并可通过 fluentd 收集日志;
- Metrics :统一指标接口,可以实现各种指标系统,默认集成 Prometheus;
- Tracing :遵循 OpenTelemetry 规范定义,以实现微服务链路追踪;
- Encoding :支持 Accept 和 Content-Type 进行自动选择内容编码;
- Transport :通用的 HTTP /gRPC 传输层,实现统一的 Middleware 插件支持;
- Registry :实现统一注册中心接口,可插件化对接各种注册中心;
- Validation: 通过 Protobuf 统一定义校验规则,并同时适用于 HTTP/gRPC 服务.
- SwaggerAPI: 通过集成第三方 Swagger插件 能够自动生成 Swagger API json 并启动一个内置的 Swagger UI 服务.
1.2 架构
1.3 代码结构
可参考这个项目: https://github.com/go-kratos/kratos-layout
它包含一个参考了 DDD 和简洁架构设计的项目结构、Makefile 脚本和 Dockerfile 文件。但这个项目模板不是必需的,您可以任意修改它,或使用自己设计的项目结构,Kratos 依然可以正常工作。框架本身不对项目结构做任何假设和限制,您可以按照自己的想法来使用,具有很强的可定制性。
使用如下命令即可基于 kratos-layout 创建项目: kratos new projiect-name
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
| . ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── api // 下面维护了微服务使用的proto文件以及根据它们所生成的go文件 │ └── helloworld │ └── v1 │ ├── error_reason.pb.go │ ├── error_reason.proto │ ├── error_reason.swagger.json │ ├── greeter.pb.go │ ├── greeter.proto │ ├── greeter.swagger.json │ ├── greeter_grpc.pb.go │ └── greeter_http.pb.go ├── cmd // 整个项目启动的入口文件 │ └── server │ ├── main.go │ ├── wire.go // 我们使用wire来维护依赖注入 │ └── wire_gen.go ├── configs // 这里通常维护一些本地调试用的样例配置文件 │ └── config.yaml ├── generate.go ├── go.mod ├── go.sum ├── internal // 该服务所有不对外暴露的代码,通常的业务逻辑都在这下面,使用internal避免错误引用 │ ├── biz // 业务逻辑的组装层,类似 DDD 的 domain 层,data 类似 DDD 的 repo,而 repo 接口在这里定义,使用依赖倒置的原则。 │ │ ├── README.md │ │ ├── biz.go │ │ └── greeter.go │ ├── conf // 内部使用的config的结构定义,使用proto格式生成 │ │ ├── conf.pb.go │ │ └── conf.proto │ ├── data // 业务数据访问,包含 cache、db 等封装,实现了 biz 的 repo 接口。我们可能会把 data 与 dao 混淆在一起,data 偏重业务的含义,它所要做的是将领域对象重新拿出来,我们去掉了 DDD 的 infra层。 │ │ ├── README.md │ │ ├── data.go │ │ └── greeter.go │ ├── server // http和grpc实例的创建和配置 │ │ ├── grpc.go │ │ ├── http.go │ │ └── server.go │ └── service // 实现了 api 定义的服务层,类似 DDD 的 application 层,处理 DTO 到 biz 领域实体的转换(DTO -> DO),同时协同各类 biz 交互,但是不应处理复杂逻辑 │ ├── README.md │ ├── greeter.go │ └── service.go └── third_party // api 依赖的第三方proto ├── README.md ├── google │ └── api │ ├── annotations.proto │ ├── http.proto │ └── httpbody.proto └── validate ├── README.md └── validate.proto
|
2. 使用
2.1 proto文件
Kratos 默认仅生成 gRPC 接口的代码,如果需要生成 HTTP 代码,请在 proto 文件中使用 option (google.api.http)
来添加 HTTP 部分的定义后再进行生成。
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
| syntax = "proto3"; package helloworld.v1; import "google/api/annotations.proto"; option go_package = "github.com/go-kratos/kratos-layout/api/helloworld/v1;v1"; // The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) { option (google.api.http) = { get: "/helloworld/{name}" }; } } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }
|
2.2 生成 proto
1 2 3 4 5 6 7 8 9
|
kratos proto add api/helloworld/helloworld.proto
kratos proto client api/helloworld/helloworld.proto
kratos proto server api/helloworld/helloworld.proto -t internal/service
|
2.3 错误
Kratos 的 errors 模块提供了 error 的封装。框架也预定义了一系列 标准错误 供使用。
错误处理这一块的设计也经过了很久的讨论才定下来,主要设计理念如下:
code
语义近似 HTTP 的 Status Code(例如客户端传参数错误用 400)同时也作为大类错误,在 HTTP 接口中的 HTTP Code 会使用它,好处是网关层可以根据这个 code 触发相应策略(重试、限流、熔断等)。reason
业务的具体错误码,为可读的字符串,能够表明,在同一个服务中应该唯一。message
用户可读的信息,可以在客户端(App、浏览器等)进行相应的展示给用户看。metadata
为一些附加信息,可以作为补充信息使用。
在 API 返回的错误信息中,以 HTTP 接口为例,消息结构大概是长这个样子的:
1 2 3 4 5 6 7 8 9 10
| { // 错误码,跟 http-status 一致,并且在 grpc 中可以转换成 grpc-status "code": 500, // 错误原因,定义为业务判定错误码 "reason": "USER_NOT_FOUND", // 错误信息,为用户可读的信息,可作为用户提示内容 "message": "invalid argument error", // 错误元信息,为错误添加附加可扩展信息 "metadata": {"some-key": "some-value"} }
|
3. 参考文档