go-kit
何为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 service
// 接口定义
type 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 endpoint
import (
"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 transport
import (
"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为基础展开,有兴趣可继续关注。