[Golang] go-kit 介绍和使用 (微服务实现工具)

发布于:2024-06-16 ⋅ 阅读:(22) ⋅ 点赞:(0)

1.go-kit 介绍

go-kit是一个分布式的开发工具集,在大型的组织(业务)中可以用来构建微服务,其解决了分布式系统中大多数常见问题,因此,使用者可以将精力集中在业务逻辑上。

他里面有用来帮助我们实现微服务的一些工具包, 和SpringBoot不同, 直接把框架搭好, 而需要手动的搭框架。go-kit 也存在3层架构。

微服务就是一个大项目中的一个小功能块,并且这个功能块可以不计语言差别的和其他功能模块通过API进行通讯和结合。

1.1 go-kit 三层结构

go-kit和SSM中的MVC一样也有三层结构endpoint,service, transport,通过这三层结构来实现,接收一个请求,然后返回一个结果。

  1. Transport
    Transport处于该微服务的最上层,主要负责于HTTP, gRPC,thrift等相关的逻辑,负责解析请求,并且调用endpoint来处理请求

  2. Endpoint
    endpoint属于客户端和服务端的转接器,他定义了request和response的格式,上层给Transport调用来处理请求,下层链接Service将Service所返回的结果转换成request需要的格式

  3. Service
    最底下的我们这个模块所需要实现的功能了

2.go-kit 实例

service -> endpoint -> transport

在这里插入图片描述

service.go

package service

import (
	"errors"
	"strings"
)

type StringServiceI interface {
	GetUppercase(string) (string, error)
	PostUppercase(string) (string, error)
	GetCount(string) int
}

type StringService struct {
}

func (StringService) GetUppercase(s string) (string, error) {
	if s == "" {
		return "", errors.New("error")
	}

	return strings.ToUpper(s), nil
}

func (StringService) PostUppercase(s string) (string, error) {
	if s == "" {
		return "", errors.New("error")
	}
	return strings.ToUpper(s), nil
}

func (StringService) GetCount(s string) (int, error) {
	if s == "" {
		return 0, errors.New("error")
	}
	return len(s), nil
}

endpoint.go

package endpoint

import (
	"context"
	"github.com/go-kit/kit/endpoint"
	"go-demo06/service"
)

type Endpoints struct {
	GetUppercase  endpoint.Endpoint
	PostUppercase endpoint.Endpoint
	GetCount      endpoint.Endpoint
}

type UppercaseRequest struct {
	S string `json:"s"`
}

type UppercaseResponse struct {
	V   string `json:"v"`
	Err error  `json:"err"`
}

type CountRequest struct {
	S string `json:"s"`
}

type CountResponse struct {
	V int `json:"v"`
}

func MakeEndpoints(svc service.StringService) Endpoints {
	return Endpoints{
		GetCount:      MakeGetCountEndpoint(svc),
		GetUppercase:  MakeGetUppercaseEndpoint(svc),
		PostUppercase: MakePostUppercaseEndpoint(svc),
	}
}

func MakeGetUppercaseEndpoint(svc service.StringService) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(UppercaseRequest)
		v, err := svc.GetUppercase(req.S)
		if err != nil {
			return UppercaseResponse{v, err}, nil
		}
		return UppercaseResponse{v, err}, nil
	}
}

func MakePostUppercaseEndpoint(svc service.StringService) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(UppercaseRequest)
		v, err := svc.PostUppercase(req.S)
		if err != nil {
			return UppercaseResponse{v, err}, nil
		}
		return UppercaseResponse{v, err}, nil
	}
}

func MakeGetCountEndpoint(svc service.StringService) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(CountRequest)
		v, err := svc.GetCount(req.S)
		if err != nil {
			return CountResponse{v}, nil
		}
		return CountResponse{v}, nil
	}
}

rest.go

package transport

import (
	"context"
	"encoding/json"
	httptransport "github.com/go-kit/kit/transport/http"
	"github.com/gorilla/mux"
	"go-demo06/endpoint"
	"go-demo06/service"
	"log"
	"net/http"
)

func RestRun() {
	svc := service.StringService{}
	r := makeHttpHandler(svc)
	log.Fatal(http.ListenAndServe(":8080", r))
}

func makeHttpHandler(svc service.StringService) http.Handler {
	r := mux.NewRouter()
	e := endpoint.MakeEndpoints(svc)
	r.Methods("GET").Path("/uppercase").Handler(httptransport.NewServer(e.GetUppercase, DecodeUppercaseRequest, EncodeUppercaseResponse))
	r.Methods("GET").Path("/count").Handler(httptransport.NewServer(e.GetCount, DecodeCountRequest, EncodeCountResponse))
	return r
}

func DecodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) {
	var req endpoint.UppercaseRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return req, nil
}

func EncodeUppercaseResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
	// transport body to json
	w.Header().Set("Content-type", "application/json")
	return json.NewEncoder(w).Encode(response)
}

func DecodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) {
	var req endpoint.CountRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return req, nil
}

func EncodeCountResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
	// transport body to json
	w.Header().Set("Content-type", "application/json")
	return json.NewEncoder(w).Encode(response)
}

main.go

package main

import (
	"go-demo06/transport"
)

func main() {
	transport.RestRun()
}
go run main.go

在这里插入图片描述

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到