何为go-kit
Go kit is a programming toolkit for building microservices (or elegant monoliths) in Go. We solve common problems in distributed systems and application architecture so you can focus on delivering business value.
go kit是一个用于在Go中构建微服务(或优雅的整体)的编程工具包,解决了分布式系统和应用程序体系结构中的常见问题,以便开发者能够专注于业务交付。
go-kit主要分为三层结构:Transport层,Endpoint层,Service层。
Transport 负责与传输协议HTTP、GRPC等相关的逻辑
Endpoint 负责request/response格式的转换,以及公用拦截器相关的逻辑
Service 业务逻辑。
另外,go-kit提供log日志,metric计数器,tracing请求跟踪,circuitbreaker服务熔断,rate-limiter限流器等模块。简单说,go-kit提供了微服务架构常见的基础模块,可以让开发者省去很多时间。
开始 了解还不够,show code。
我们先定义下service,不如就做个简单的计算器,仅仅做演示,有加减功能即可,不整太复杂了。
package servicetype CalculateService interface { Add(a, b int ) int Reduce(a, b int ) int Multi(a, b int ) int } type calculateService struct {}func NewService () *calculateService { return &calculateService{} } func (s *calculateService) Add(a, b int ) int { return a + b } func (s *calculateService) Reduce(a, b int ) int { return a - b } func (s *calculateService) Multi(a, b int ) int { return a * b }
注意:Go 接口是一组方法的集合,可以理解为抽象的类型。它提供了一种非侵入式的接口。任何类型,只要实现了该接口中方法集,那么就属于这个类型。(这是go中非常常用的特性,切记)
endpoint格式化请求,调用service服务,并格式化输出
package endpointimport ( "context" "demo6/service" "fmt" "github.com/go-kit/kit/endpoint" ) type Request struct { A int `json:"a" form:"a"` B int `json:"b" form:"b"` } type Res struct { Res int `json:"res"` Err error `json:"err"` } func MakeAddEndpoint (s service.CalculateService) endpoint.Endpoint { return func (_ context.Context, request interface {}) (interface {}, error ) { req := request.(Request) return Res{Res: s.Add(req.A, req.B)}, nil } } func MakeReduceEndpoint (s service.CalculateService) endpoint.Endpoint { return func (_ context.Context, request interface {}) (interface {}, error ) { req := request.(Request) return Res{Res: s.Reduce(req.A, req.B)}, nil } } func MakeMultiEndpoint (s service.CalculateService) endpoint.Endpoint { return func (_ context.Context, request interface {}) (interface {}, error ) { req := request.(Request) return Res{Res: s.Multi(req.A, req.B)}, nil } }
接下来,定义transport定义请求方式(这里我们使用json):
package transportimport ( "context" "demo6/endpoint" "encoding/json" "errors" "net/http" ) func DecodeRequest (_ context.Context, r *http.Request) (interface {}, error ) { var req endpoint.Request if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil , errors.New("params error" ) } return req, nil } func EncodeResponse (_ context.Context, w http.ResponseWriter, res interface {}) error { return json.NewEncoder(w).Encode(res) }
最后我们将它们endpoint和transport粘合起来,跑起来go~
package main import ( "demo6/endpoint" "demo6/service" "demo6/transport" "net/http" httpTransport "github.com/go-kit/kit/transport/http" ) func main() { s := service.NewService() add := httpTransport.NewServer( endpoint.MakeAddEndpoint(s), transport.DecodeRequest, transport.EncodeResponse, ) reduce := httpTransport.NewServer( endpoint.MakeReduceEndpoint(s), transport.DecodeRequest, transport.EncodeResponse, ) multi := httpTransport.NewServer( endpoint.MakeMultiEndpoint(s), transport.DecodeRequest, transport.EncodeResponse, ) http.Handle("/add", add) http.Handle("/reduce", reduce) http.Handle("/multi", multi) http.ListenAndServe(":9009", nil) }
运行起来:
成功运行!
详细代码进githubgithub.com/puresai/go-example/tree/main/demo6-go-kit
留一个问题,对于json格式错误的请求,返回的不是json,如何改造,让接口返回json呢?
最近自己在研究go微服务这块的知识,后续几篇文字应该都会以go-kit为基础展开,有兴趣可继续关注。