Kratos - 使用指北
前言
- Kratos是一个Go语言的微服务框架,由B站开源,用于构建高可用、高性能、可扩展的微服务。
- 文档地址:https://go-kratos.dev/
- 代码地址:https://github.com/go-kratos/kratos
- 文档说明已经足够详细,本文主要是对文档中没有提到的一些问题进行补充,以及一些使用心得。
- 这里是我在使用Kratos时写的一个Demo。里面会包含这部分使用的代码。
文件上传
在kratos中,API是使用proto文件定义的,所以我们不好直接在proto文件中定义文件上传的接口。
官方做法:
- https://github.com/go-kratos/examples/blob/main/http/upload/main.go
- 官方的demo是在http服务中单独注册一个上传文件的接口,然后在业务中调用这个接口。
- 这种方式会导致你的上传文件的Service和你的业务Service分开,不太符合整个代码架构的逻辑。
Service中使用原生的http服务:
- 实现
encoding.Codec接口实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22var _ encoding.Codec = FormCodec{}
const (
// Name is form codec name
Name = "form-data"
)
type FormCodec struct {
}
func (f FormCodec) Marshal(v interface{}) ([]byte, error) {
return nil, nil
}
func (f FormCodec) Unmarshal(data []byte, v interface{}) error {
// todo 参数解析为结构体,或者直接不处理就返回
return nil
}
func (f FormCodec) Name() string {
return Name
}FormCodec接口,然后在service中使用原生的http服务来处理文件上传。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24func (f FileUploadService) UploadFile(ctx context.Context, request *file_upload.UploadFileRequest) (*file_upload.UploadFileReply, error) {
req, ok := http.RequestFromServerContext(ctx)
if !ok {
return nil, errors.New("http.RequestFromContext error")
}
// 设置内存大小
err := req.ParseMultipartForm(32 << 20)
if err != nil {
return nil, err
}
fil := req.MultipartForm.File["file_content"]
if len(fil) == 0 {
return nil, errors.New("file_content is empty")
}
for _, header := range fil {
// 打开文件
file, err := header.Open()
if err != nil {
return nil, err
}
defer file.Close()
}
return &file_upload.UploadFileReply{}, nil
}
重定向
- 在官方文档中也有重定向的例子,但是是基于 中间件的方式来实现的。无法直接在业务中使用。
- 并且其实在源码中有留下一个接口
http.Redirect,但是没有实现。我这里就是用这个接口来实现重定向。
自定义 Encoder 方法
完整代码可以查看这里
1 | |
定义API接口
1 | |
API 实现 http.Redirect
1 | |
重定向总结
- 通过实现
http.Redirector接口,可以在MyResponseEncoder中判断是否是重定向的接口,然后调用Redirect方法进行重定向。 - 业务代码就可以在Service层中处理,并且通过API的方式来定义重定向的接口。
- 相比于官方的中间件方式,这种方式更加灵活,可以在业务中直接使用。
错误处理
- kratos 是用了 protoc-gen-go-errors 插件来生成错误码的。
- 生成的错误码是一个枚举类型,每个错误码都有一个Code,Reason,Message。
- Code 你可以自己定义,但是 Reason 和 Message 是根据你的 proto 文件中定义的错误码来生成的。
- 在使用中,你需要通过 Reason 来判断错误,Message 是用来给用户看的。而 Code 是在不同场景下有不同的含义。
Kratos - 使用指北
https://blog.codefish.net/2024/10/06/golang-kratos-guide/