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)
}

运行起来:

img

成功运行!

详细代码进githubgithub.com/puresai/go-example/tree/main/demo6-go-kit


留一个问题,对于json格式错误的请求,返回的不是json,如何改造,让接口返回json呢?

最近自己在研究go微服务这块的知识,后续几篇文字应该都会以go-kit为基础展开,有兴趣可继续关注。


go-kit
https://blog.puresai.com/2021/02/12/goexample6/
作者
puresai
许可协议