铁匠 铁匠
首页
golang
java
架构
常用算法
  • Java
  • nginx
  • 系统运维
  • 系统安全
  • mysql
  • redis
参考文档
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

铁匠

不予评判的专注当下
首页
golang
java
架构
常用算法
  • Java
  • nginx
  • 系统运维
  • 系统安全
  • mysql
  • redis
参考文档
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • golang 入门学习指南
  • go-kit

    • go-kit学习指南 - 基础概念和架构
    • go-kit学习指南 - 多协议支持
    • go-kit学习指南 - 中间件
      • 介绍
      • 实现步骤
        • 参考代码
        • 启动服务
        • 测试
    • go-kit开发微服务 - 服务注册与发现
  • go
  • go-kit
fengjx
2024-04-19
目录

go-kit学习指南 - 中间件

# 介绍

go-kit的分层设计可以看成是一个洋葱,有许多层。这些层可以划分为我们的三个领域。

  • Service: 最内部的服务领域是基于你特定服务定义的,也是所有业务逻辑实现的地方
  • Endpoint: 中间的端点领域是将你的每个服务方法抽象为通用的 endpoint.Endpoint,并在此处实现安全性和反脆弱性逻辑。
  • Transport: 最外部的传输领域是将端点绑定到具体的传输方式,如 HTTP 或 gRPC。

可以通过定义一个接口并提供具体实现来实现核心业务逻辑。然后通过编写中间件来组合额外的功能,比如日志记录、监控、权限控制等。

go-kit 内置了一些的中间件

  • basic 认证 中间件 (opens new window)
  • jwt 认证中间件 (opens new window)
  • 限流中间件 (opens new window)
  • 熔断、降级中间件 (opens new window)
  • 指标监控中间件 (opens new window)
  • 链路跟踪中间件 (opens new window)

这些中间件可以与你的业务逻辑组合起来实现功能复用。你也可以自己实现中间件,为项目提供基础能力。

中间件在设计模式中属于装饰器模式,实现了关注点分离,代码逻辑清晰,可扩展性强。

# 实现步骤

我们在第一章greetsvc的基础上增加一个内置basic认证中间件,再自定义一个中间件打印请求耗时。

githu: https://github.com/fengjx/go-kit-demo/tree/master/greetmiddleware (opens new window)

# 参考代码

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/go-kit/kit/auth/basic"
	"github.com/go-kit/kit/endpoint"
	httptransport "github.com/go-kit/kit/transport/http"
)

func main() {

	svc := greetService{}

	// 中间件组合实现功能扩展
	helloEndpoint := makeHelloEndpoint(svc)
	helloEndpoint = basic.AuthMiddleware("foo", "bar", "hello")(helloEndpoint)
	helloEndpoint = timeMiddleware("hello")(helloEndpoint)

	satHelloHandler := httptransport.NewServer(
		helloEndpoint,
		decodeRequest,
		encodeResponse,
		httptransport.ServerBefore(func(ctx context.Context, request *http.Request) context.Context {
			authorization := request.Header.Get("Authorization")
			// 增加一个拦截器
			ctx = context.WithValue(ctx, httptransport.ContextKeyRequestAuthorization, authorization)
			return ctx
		}),
	)

	http.Handle("/say-hello", satHelloHandler)
	log.Println("http server start")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

type helloReq struct {
	Name string `json:"name"`
}

type helloResp struct {
	Msg string `json:"msg"`
}

type greetService struct {
}

func (svc greetService) SayHi(_ context.Context, name string) string {
	return fmt.Sprintf("hi: %s", name)
}

func makeHelloEndpoint(svc greetService) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		req := request.(*helloReq)
		msg := svc.SayHi(ctx, req.Name)
		return helloResp{
			Msg: msg,
		}, nil
	}
}

func decodeRequest(_ context.Context, r *http.Request) (interface{}, error) {
	name := r.URL.Query().Get("name")
	req := &helloReq{
		Name: name,
	}
	return req, nil
}

func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
	data := map[string]any{
		"status": 0,
		"msg":    "ok",
		"data":   response,
	}
	return json.NewEncoder(w).Encode(data)
}

// timeMiddleware 自定义中间件,打印耗时
func timeMiddleware(endpointName string) endpoint.Middleware {
	return func(next endpoint.Endpoint) endpoint.Endpoint {
		return func(ctx context.Context, request interface{}) (interface{}, error) {
			start := time.Now()
			defer func() {
				duration := time.Since(start)
				log.Printf("%s take %v\r\n", endpointName, duration)
			}()
			return next(ctx, request)
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

# 启动服务

go run main.go
1

# 测试

认证失败

# sya-hello
curl http://localhost:8080/say-hello?name=fengjx
1
2

认证成功

curl -H 'Authorization: Basic Zm9vOmJhcg==' http://localhost:8080/say-hello?name=fengjx
1
# server 日志输出
2024/04/21 12:34:37 hello take 6.542µs
1
2
#go-kit
Last Updated: 2024/05/12, 15:25:49
go-kit学习指南 - 多协议支持
go-kit开发微服务 - 服务注册与发现

← go-kit学习指南 - 多协议支持 go-kit开发微服务 - 服务注册与发现→

最近更新
01
go-kit学习指南 - 多协议支持
04-19
02
go-kit开发微服务 - 服务注册与发现
04-19
03
go-kit学习指南 - 基础概念和架构
04-18
更多文章>
Theme by Vdoing | Copyright © 2016-2024 铁匠 | 粤ICP备15021633号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式