go-kit连接地址:https://github.com/go-kit/kit
go-kit本身不是一个框架,而是一套微服务工具集, 它可以用来解决分布式系统开发中的大多数常见问题. 所以你可以专注于你的业务逻辑中
利用它提供的api和规范可以开发出健壮的,维护性高德微服务。
Rate Limiter 限流器
Trasport 数据传输(序列化和反序列化)
Logging 日志
Metrics 指标
Circuit breaker 断路器
Request tracing 请求追踪
Service Discovery 服务发现
UserServices.go —》业务逻辑
//创建一个接口,在endpoint中需要用到
type IUserService interface {
GetName(userid int) string
}
//实现这个接口
type UserService struct {
}
//这里需要实现接口的方法
func (u *UserService) GetName(userid int) string {
if userid == 1 {
return "wd"
}
return "wyh"
}
UserEndpoint.go —》节点实现
import (
"context"
"github.com/go-kit/kit/endpoint"
)
//声明请求结构体
type UserRequest struct {
Uid int `json:"uid"`
}
//声明返回结构体
type UserResponse struct {
Result string `json:"result"`
}
//使用闭包的方式生成一个Endpoint节点
func GetUserEnpoint(userserver IUserService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(*UserRequest)
return UserResponse{
Result: userserver.GetName(r.Uid),
}, nil
}
}
UserTransport.go —》传输方式,这里使用http通信,以后的内容会贴出gRPC方式
import (
"context"
"encoding/json"
"errors"
"net/http"
"strconv"
)
//解码
func DecodeUserRequest(ctx context.Context, r *http.Request) (interface{}, error) {
//http://localhost:8080/?uid=""
if r.URL.Query().Get("uid") != "" {
uid, _ := strconv.Atoi(r.URL.Query().Get("uid"))
return &UserRequest{
Uid: uid,
}, nil
}
return nil, errors.New("参数错误")
}
//编码
func EncodeUserResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
//w.Header().Set("Content-Type", "application/json;charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
main.go —》主函数,注意我将上面三个脚本都放在 service 包里,吾懒,吾自知也,尔等勿学。
import (
"net/http"
httptransport "github.com/go-kit/kit/transport/http"
"github.com/service"
)
func main() {
//ctx := context.Background()
//声明一个实现了接口的结构体
userserver := &service.UserService{}
//生成一个Endpoint,getnamehandler是go-kit自带的包,这里是http传输方式的固定写法,注意不要放入ctx。
getnamehandler := httptransport.NewServer(
service.GetUserEnpoint(userserver),
service.DecodeUserRequest,
service.EncodeUserResponse,
)
http.Handle("/getname", getnamehandler)
http.ListenAndServe(":8080", nil)
}
启动服务,这里使用apizza测试,uid=1,返回{“result”: “wd”}
这里使用apizza测试,uid=2 返回{“result”: “wyh”}
这里使用装饰者模式,新建一个日志模块
UserMiddleware.go
import (
"context"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
)
//声明一个中间件类型
type Middleware func(endpoint.Endpoint) endpoint.Endpoint
//为这个中间件实现方法,这里再开始和结束打印日志
func LogMiddleware(logger log.Logger) Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
logger.Log("msg", "call start")
defer logger.Log("msg", "call end")
return next(ctx, request)
}
}
}
main.go —> 将endpoint 声明替换如下
logger := log.NewLogfmtLogger(os.Stderr)
userendpoint := service.GetUserEnpoint(userserver)
userendpoint = service.LogMiddleware(log.NewSyncLogger(logger))(userendpoint)
getnamehandler := httptransport.NewServer(
userendpoint,
service.DecodeUserRequest,
service.EncodeUserResponse,
)