SEO优化
- golang如何进行AOP操作
- 怎样的AOP风格最好用
- gin的中间件是如何实现的
前言
我们将一个事件处理标记为handler, 那么AOP指代的,就是围绕这个handler的【执行前】【执行后】的切面操作,他可以形象地描述为:
这种执行流程,容易开发成以下样式:
beforeHandler()
handler()
AfterHandler()
一旦做成这样子,那么在同一个handler接入不同的切面操作时,便会需要无限侵入代码,变成:
...
countExecTime()
startRateLimit()
handler
endRateLimit()
endExecTime()
...
这样子的操作,不只是丑陋,而且随着aop操作增多,维护难度会剧增。
所以到底要如何设计一套可以复用的机制,来优雅使用AOP操作。熟悉golang Web开发的人都知道,github.com/gin-gonic/gin里,可以通过c.Next
和 c.Abort()
的机制,来优雅设计aop切面(中间件)。
那么,我们能否依照同类api,来达到类似的效果呢?
答案是,可以的。
合理的AOP设计,应该是这样的
它的执行流为:
限流start --> 熔断start —> handler —>熔断end --> 限流end
设计
设计前,考虑到大部分群体,都对http gin的中间件流,十分熟悉。所以我们也基于同样的方式,来实现aop操作。实现以前呢,我们同步一下设计的要求:
- 需要支持,对任意方法执行切面操作。
- 需要和gin共享相似度极高的api。
- 支持所有框架场景。
- 实现包体简单。
- 支持对【全局】【单个路由】两个维度支持中间件
中间件样例:
func AlertTimeout(c *irr.Context) {
// c.Abort() 阻断
// c.Next() 放行
}
使用时
wrapF := irr.WrapFunc(func(){
// 原本的handler逻辑
})
// 流程超时报警
wrapF.Use(AlertTimeout)
// 流程熔断报警
wrapF.Use(AlertFuse)
wrapF.Handle()
实现
目录层级
irr
| - context.go
| - core.go
context.go
package irr
import (
"math"
)
const ABORT = math.MaxInt32