####环境准备
go >= 1.12
####项目编译方式
go build
|--- conf // 配置文件工具方法包
|--- core // gateway核心组件
|--- --- constant // 核心组件常量定义
|--- --- --- bytes.go // 常量byte slice版本(性能优化)
|--- --- --- const.go // 常量定义
|--- --- options // gateway核心组件配置选项
|--- --- --- option.go // gateway核心组件配置选项结构体定义
|--- --- routing // 路由及其相关组件
|--- --- --- base.go
|--- --- --- etcd.go // etcd存取方法
|--- --- --- health_check.go // 健康检查组件
|--- --- --- proxy.go // 代理模块, 处理预置/后置中间件
|--- --- --- routing.go // 路由模块
|--- --- --- tables.go // 协程安全的各式路由表定义
|--- --- utils
|--- --- --- utils.go // 工具方法集合
|--- --- watcher // Watcher组件
|--- --- --- base.go
|--- --- --- endpoint.go // endpoint/node watcher 定义
|--- --- --- health_check.go // healthCheck watcher 定义
|--- --- --- route.go // route watcher 定义
|--- --- --- service.go // service watcher 定义
|--- --- --- watcher.go // Watcher Interface
|--- dashboard // 监控平台Api
|--- middleware // 中间件组件
|--- --- auth.go // 认证中间件
|--- --- count.go // 计数器中间件
|--- --- limit.go // 限流中间件
|--- --- base.go // 中间件 Middleware Interface
|--- sdk
|--- --- golang
|--- --- --- const.go
|--- --- --- gw_sdk.go
|--- server.go // Server 入口
- server.go: 使用了 Tcp SO_REUSEPORT Option, 若后续部署时系统不支持该 Tcp 选项, 可以更换为普通Listener
- 不要在proxy.go中打印任何关于经由Api Gateway的请求报文的string类型日志, 大批量的打印日志将会导致频繁触发GC, 降低处理能力
- 请求的超时时间由两部分组成: 一是所有中间件中的最大处理时间; 二是转发请求的处理时间
- api gateway关闭了对 connection:keep-alive的支持, 若需要该特性, 可以考虑其他替代方案(comet/websocket/HTTP2)
- 新的预置中间件只需满足middleware/base.go中的 Middleware Interface, 即可在gateway初始化时绑定至RequestWrapperHandler; 所有中间件是并发无序执行, 不应期待不同中间件的执行顺序(中间件被缓存在一个队列中, 虽然执行开始的时间近乎相同, 但结束时间不一定相同); 你可以在Work函数的第一个参数 ctx *fasthttp.RequestCtx中拿到所有这次请求相关的数据, 甚至可以通过 ctx.UserValue("Table") 拿到全局的路由表
node := golang.NewNode("127.0.0.1", *flagPort, golang.NewHealthCheck(
"/check",
10,
5,
3,
true,
))
svr := golang.NewService("test", node)
gw := golang.NewApiGatewayRegistrant(
ConnectToEtcd(),
node,
svr,
[]*golang.Router{
golang.NewRouter("test1", "/front/$1", "/test/$1", svr),
golang.NewRouter("test2", "/api/v1/test/$1", "/test/$1", svr),
golang.NewRouter("test3", "/rd", "/redirect", svr),
},
)
go func(g *golang.ApiGatewayRegistrant) {
if err := g.Register(); err != nil {
logger.Error(err)
}
}(&gw)
在 http server启动之前, 完成对 node, service, gateway对象的初始化
其中Router的语法为:
- 参数1, router name, 同名的router会被视为同一个Api
- 参数2, frontend api, 对外Api 路由, '$x'代表正则替换的第x个URL Pattern
- 参数3, backend api, 内部Api 路由, '$x'代表正则替换的第x个URL Pattern
- 参数4, 绑定至的服务对象
func exit(gw *golang.ApiGatewayRegistrant) {
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
<-signalChan
logger.Infof("service exiting ...")
if err := gw.Unregister(); err != nil {
logger.Error(err)
}
os.Exit(0)
}
最后可以通过 exit 函数来实现优雅退出, 这样在服务重启/更新时, 将不会有新的请求抵达该服务