go-kit微服务入门

go-kit连接地址:https://github.com/go-kit/kit

简介

go-kit本身不是一个框架,而是一套微服务工具集, 它可以用来解决分布式系统开发中的大多数常见问题. 所以你可以专注于你的业务逻辑中
利用它提供的api和规范可以开发出健壮的,维护性高德微服务。

关注重点

Rate Limiter 限流器

Trasport 数据传输(序列化和反序列化)

Logging 日志

Metrics 指标

Circuit breaker 断路器

Request tracing 请求追踪

Service Discovery 服务发现

go-kit三层架构

  • Transport:通讯实现
    主要负责与http,gRPC,thrift等相关的逻辑
  • Endpoint:节点
    定义Request和Response格式,并可以使用装饰器包装函数,以此来实现各种中间件嵌套。
  • Service:业务层

一、简单栗子

服务端

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 —》节点实现

扫描二维码关注公众号,回复: 8875186 查看本文章
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,
	)

测试

再次使用apizza发起请求
控制台打印如下
在这里插入图片描述
未完待续

发布了53 篇原创文章 · 获赞 5 · 访问量 2315

猜你喜欢

转载自blog.csdn.net/qq_25490573/article/details/103985883