HTTP代理【2】中间件开发

目录: 
1: 中间件的意义
2: 实现原理
3: 代码实现
4: 围绕中间件扩展功能(日志、统计、限流等等)

1、中间件意义
避免代码中出现多重嵌套if(如下), 提升复杂度。

func demo(){
    
    
	if condition1{
    
    
		if condition2{
    
    
			if condition3{
    
    
				if condition4{
    
    
					if condition5{
    
    
						...
					}
				}
			}
		}
	}
}
  • 提高复用、隔离业务。
  • 调用清晰、组合随意。
    在这里插入图片描述
    2、实现原理
    洋葱结构、每一层都是一个中间件。
    3、代码实现
    中间件一般都封装在路由上,路由是URL请求分发的管理器
    中间件选型:
  • 基于链表构建中间件:缺点是实现复杂、调用方式不灵活
  • 使用数组构建中间件:控制灵活方便,推荐使用。例如Gin也是基于该思路构建

3.1、使用方法数组构建中间件
实现思路:
在这里插入图片描述

(1) 方法组装

  • 构建中间件URL路由
  • 构建URL的中间件方法数组
  • 使用use方法整合路由与方法数组
    在这里插入图片描述

(2) 方法回调

  • 构建方法请求逻辑
  • 封装http.Handler接口与http.Server整合

3.2 基础案例: 使用数组构建的中间件实现一个HTTP服务
目录结构

- demo
  - middleware
    - slice_router.go
    - tracelog_slicemw.go
  - main.go

日志中间件(middleware/tracelog_slicemw.go)

package middleware
import "log"
func TraceLogSliceMW() func(c *SliceRouterContext) {
    
    
	return func(c *SliceRouterContext) {
    
    
		log.Println("trace_in")
		c.Next()
		log.Println("trace_out")
	}
}

路由器

package middleware
import (
	"context"
	"math"
	"net/http"
	"strings"
)
//目标定位是 tcp、http通用的中间件

const abortIndex int8 = math.MaxInt8 / 2 //最多 63 个中间件

type HandlerFunc func(*SliceRouterContext)

// router 结构体
type SliceRouter struct {
    
    
	groups []*SliceGroup
}

// group 结构体
type SliceGroup struct {
    
    
	*SliceRouter
	path     string
	handlers []HandlerFunc
}

// router上下文
type SliceRouterContext struct {
    
    
	Rw  http.ResponseWriter
	Req *http.Request
	Ctx context.Context
	*SliceGroup
	index int8
}

func newSliceRouterContext(rw http.ResponseWriter, req *http.Request, r *SliceRouter) *SliceRouterContext {
    
    
	newSliceGroup := &SliceGroup{
    
    }

	//最长url前缀匹配
	matchUrlLen := 0
	for _, group := range r.groups {
    
    
		//fmt.Println("req.RequestURI")
		//fmt.Println(req.RequestURI)
		if strings.HasPrefix(req.RequestURI, group.path) {
    
    
			pathLen := len(group.path)
			if pathLen > matchUrlLen {
    
    
				matchUrlLen = pathLen
				*newSliceGroup = *group //浅拷贝数组指针
			}
		}
	}

	c := &SliceRouterContext{
    
    Rw: rw, Req: req, SliceGroup: newSliceGroup, Ctx: req.Context()}
	c.Reset()
	return c
}

func (c *SliceRouterContext) Get(key interface{
    
    }) interface{
    
    } {
    
    
	return c.Ctx.Value(key)
}

func (c *SliceRouterContext) Set(key, val interface{
    
    }) {
    
    
	c.Ctx = context.WithValue(c.Ctx, key, val)
}

type SliceRouterHandler struct {
    
    
	coreFunc func(*SliceRouterContext) http.Handler
	router   *SliceRouter
}

func (w *SliceRouterHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
    
    
	c := newSliceRouterContext(rw, req, w.router)
	if w.coreFunc != nil {
    
    
		c.handlers = append(c.handlers, func(c *SliceRouterContext) {
    
    
			w.coreFunc(c).ServeHTTP(rw, req)
		})
	}
	c.Reset()
	c.Next()
}

func NewSliceRouterHandler(coreFunc func(*SliceRouterContext) http.Handler, router *SliceRouter) *SliceRouterHandler {
    
    
	return &SliceRouterHandler{
    
    
		coreFunc: coreFunc,
		router:   router,
	}
}

// 构造 router
func NewSliceRouter() *SliceRouter {
    
    
	return &SliceRouter{
    
    }
}

// 创建 Group
func (g *SliceRouter) Group(path string) *SliceGroup {
    
    
	return &SliceGroup{
    
    
		SliceRouter: g,
		path:        path,
	}
}

// 构造回调方法
func (g *SliceGroup) Use(middlewares ...HandlerFunc) *SliceGroup {
    
    
	g.handlers = append(g.handlers, middlewares...)
	existsFlag := false
	for _, oldGroup := range g.SliceRouter.groups {
    
    
		if oldGroup == g {
    
    
			existsFlag = true
		}
	}
	if !existsFlag {
    
    
		g.SliceRouter.groups = append(g.SliceRouter.groups, g)
	}
	return g
}

// 从最先加入中间件开始回调
func (c *SliceRouterContext) Next() {
    
    
	c.index++
	for c.index < int8(len(c.handlers)) {
    
    
		//fmt.Println("c.index")
		//fmt.Println(c.index)
		c.handlers[c.index](c)
		c.index++
	}
}

// 跳出中间件方法
func (c *SliceRouterContext) Abort() {
    
    
	c.index = abortIndex
}

// 是否跳过了回调
func (c *SliceRouterContext) IsAborted() bool {
    
    
	return c.index >= abortIndex
}

// 重置回调
func (c *SliceRouterContext) Reset() {
    
    
	c.index = -1
}

HTTP服务(main.go)

package main
var addr = "127.0.0.1:2002"
func main() {
    
    
	log.Println("Starting httpserver at " + addr)

	// 初始化(方法数组路由器)
	sliceRouter := middleware.NewSliceRouter()

	// 中间件可充当业务逻辑代码
	sliceRouter.Group("/middle").Use(middleware.TraceLogSliceMW(), func(c *middleware.SliceRouterContext) {
    
    
		c.Rw.Write([]byte("middleware func"))
	})

	routerHandler := middleware.NewSliceRouterHandler(nil, sliceRouter)
	log.Fatal(http.ListenAndServe(addr, routerHandler))

3.3、在以上基础上扩展一个转发代理中间件
思路:
1.先启动后端服务。
2.创建一个代理(教你开发一个代理服务器)
3.创建一个中间件,将代理逻辑写入
4.路由器use该中间件
目录

- demo
  - proxy                    // 新增代理
  	- proxt.go
  - backend                  // 新增后端服务
    - main.go
  - middleware               // 该目录下所有文件不变
    - slice_router.go
    - tracelog_slicemw.go
  - main.go                  // 稍作修改

1.后端服务(backend/main.go)

package main
type RealServer struct {
    
    
	Addr string
}
func (r *RealServer) HelloHandler(w http.ResponseWriter, req *http.Request) {
    
    
	io.WriteString(w, fmt.Sprintf("hit %v", r.Addr))
}
func (r *RealServer) Run() {
    
    
	log.Println("Starting httpserver at " + r.Addr)
	mux := &http.ServeMux{
    
    }
	mux.HandleFunc("/", r.HelloHandler)
	server := &http.Server{
    
    Addr: r.Addr, WriteTimeout: time.Second * 3, Handler: mux,}
	go func() {
    
    
		log.Fatal(server.ListenAndServe())
	}()
}

func main() {
    
    
	rs1 := RealServer{
    
    Addr: "127.0.0.1:2003"}
	rs2 := RealServer{
    
    Addr: "127.0.0.1:2004"}
	rs1.Run()
	rs2.Run()
	//监听关闭信号
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
}
  1. 代理(proxy/proxy.go)

待更新..

  1. 根函数(main.go)
package main

var addr = "127.0.0.1:2002"

func main() {
    
    
	reverseProxy := func(c *middleware.SliceRouterContext) http.Handler {
    
    
		url1, _ := url.Parse("http://127.0.0.1:2003")
		url2, _ := url.Parse("http://127.0.0.1:2004")
		_ = []*url.URL{
    
    url1, url2}
		return nil
	}

	log.Println("Starting httpserver at " + addr)

	// 初始化方法数组路由器
	sliceRouter := middleware.NewSliceRouter()

	// 中间件可充当业务逻辑代码
	sliceRouter.Group("/middle").Use(middleware.TraceLogSliceMW(), func(c *middleware.SliceRouterContext) {
    
    
		c.Rw.Write([]byte("middleware func"))
	})

	// 中间件请求到反向代理
	sliceRouter.Group("/proxt").Use(middleware.TraceLogSliceMW(), func(c *middleware.SliceRouterContext) {
    
    
		fmt.Println("reverse proxy")
		reverseProxy(c).ServeHTTP(c.Rw, c.Req)
	})
	routerHandler := middleware.NewSliceRouterHandler(nil, sliceRouter)
	log.Fatal(http.ListenAndServe(addr, routerHandler))
}

猜你喜欢

转载自blog.csdn.net/qq_38900565/article/details/115415587