HTTP框架的设计学习
借老师的一张图来说明,一个完整的HTTP框架基本上包含这六大模块,最重要的是从上到下的五层,Common模块是其余模块都会使用,其中一些模块内容底层已经做了处理,不需要开发人员再次做处理。
一个好的HTTP框架应该满足以下条件:
- 高内聚,低耦合。
- 易复用。
- 高扩展性
整个流程就是client发送请求,经过middleware做了前置处理,如打日志什么的,再经过协议编解码(codec),网络传输(transport),再route找到请求的
Application
提供合理的API:
1.API应该见名知意,不要用拼音,也不要用无意义的名字,如func a(){},命名采用驼峰命名法。
2.可以简单就不要做的太复杂,如老师举例的ctx.Request.Header.Peek(key),可以改为ctx.GetHeader(key)。
3.安全性,重要的接口要做好隐蔽,因为里面可能会有重要数据不能对外暴露。
middleware
洋葱模型,跟java那个很像,本质上都是责任链设计模式,通用逻辑就是日志或者Metrics监控,这种核心逻辑与通用逻辑分离和AOP思想有点相似。
- 日志记录
- 性能统计与监控
- 安全控制,可以对请求进行校验
- 事务处理
- 异常处理
route
框架路由就是为URL匹配对应的处理函数,比如/delete会匹配到delete函数,路由又有以下几类:
- 静态路由:/a/b/c、/a/b/c
- 参数路由:/a/:id/c、/*all(其中:id表示这是一个动态的id,/*all代表可以匹配这个/后的所有路由,不是可以匹配all)
- 路由修复:/a/b变成/a/b/自动补/,有时候我们需要补/有时候不需要,就是因为有些框架可能没有路由修复能力
- 匹配HTTP方法,也就是用的是GET还是POST还是PUT等等,现在基本上都是用GET和POST
如何匹配路由?
我们可以选择用前缀匹配树来匹配,具体过程可以看前缀树的实现过程,简单来说就是匹配前缀是否符合要求,符合要求就继续匹配下一个
codec
协议层就是我的弱项了,比较抽象,但我们不是学习协议的具体内容,什么序列号,要多少个字节这样,而是学习如何使用协议。
type Server interface{
serve(c context.Context,conn network.Conn) error
}
我们需要一个环境不断传递下去,也要有连接,在连接上读写数据,有错误的话也要返回
transport
主要有 go-net,netpoll,前者用了BIO,后者用了NIO,两者都是IO模型,除了这两个还有一个AIO。 BIO是阻塞IO,比如Read和Write方法,如果没有数据的话会阻塞,什么也干不了。NIO是非阻塞IO,等足够的数据才会运行,我们不知道什么时候数据才满,所以会开辟一块内存空间(类似缓冲区),等Flush方法调用后才把数据发送出去。
type Write interface{
Malloc(n int) (buf []byte,err error)
Flush() error
...
}