HTTP协议
HTTP:超文本传输协议 (Hypertext Transfer Protocol)
协议结构:
协议开始
协议元数据
Text
协议结束
协议里有什么
请求流程
缺点不足
HTTP1
队头阻塞
传输效率低
明文传输不安全
HTTP2
多路复用
头部压缩
二进制协议
QUIC
基于UDP实现
解决队头阻塞
加密减少握手次数
支持快速启动
分层设计
专注性
扩展性
复用性
高内聚 低耦合
易复用
高扩展性
应用层设计
提供合理的 API
冗余性
兼容性
可测性
可见性
中间件设计
中间件需求
配合 Handler 实现一个完整的请求处理生命周期
拥有预处理逻辑与后处理逻辑
可以注册多中间件
对上层模块用户逻辑模块易用
洋葱模型
1、既然要实现预处理和后处理,那这个就很像调用了一个函数
2、路由上可以注册多 Middleware,同时也可以满足请求级别有效只需要将 Middleware 设计为和业务和 Handler 相同即可。
3、用户如果不主动调用下一个处理函数怎么办?
- 核心:在任何场景下index保证递增
4、出现异常
- 调用链:
适用场景:
不调用 Next:初始化逻辑且不需要在同一调用栈
调用 Next:后处理逻辑或需要在同一调用栈上
路由设计
框架路由实际上就是为 URL 匹配对应的处理函数 (Handlers)
1、静态路由: /a/b/c、/a/b/d
2、参数路由: /a/:id/c (/a/b/c, /a/d/c)、/*all
3、路由修复: /a/b <-> /a/b/
4、冲突路由以及优先级: /a/b、/:id/c
5、匹配 HTTP 方法
6、多处理函数:方便添加中间件
解决方案
1、map[string]handlers
/a/b/c、/a/b/d /a/:id/c、/*all
2、前缀匹配树
/a/b/c、/a/b/d
设计案例
/a/b/c
/a/b/d
/a/:b/d
/a/:c/f
匹配HTTP
外层 Map; 根据 method 进行初步筛选
实现添加多处理函数
在每个节点上使用一个 list 存储handler
设计
1、明确需求: 考虑清楚要解决什么问题、有哪些需求
2、业界调研:业界都有哪些解决方案可供参考
3、方案权衡:思考不同方案的取舍
4、方案评审: 相关同学对不同方案做评审
5、确定开发:确定最合适的方案进行开发
协议层设计
1、不要将上下文存储在结构类型内;相反,将Context显式传递给每个需要它的函数。Context应该是第一个参数。
2、需要在连接上读写数据
网络层设计
BIO
go net
用户管理 buffer
NIO
net poll
网络库管理 buffer
总结
1、API设计:可理解性、简单性
2、中间件设计:洋葱模型
3、路由设计:前缀匹配树
4、协议层设计: 抽象出合适的接口
5、网络层设计: 网络模型
网络库的优化
go net
存下全部 Header减少系统调用次数能够复用内存能够多次读
go net with bufio
绑定一块缓冲区
net poll
存下全部 Header拷贝出完整的 Body
net poll with nocopy peek
分配足够大的 buffer
限制最大 buffer size
优势
go net
流式友好
小包性能高
net poll
中大包性能高
时延低
协议优化
Headers 解析
找到 Header Line 边界:\r \n
先找到\n 再看它前一个是不是 \r
针对协议相关的 Headers 快速解析:
1、通过 Header key 首字母快速筛除掉完全不可能的 key
2、解析对应 value 到独立字段
3、使用 byte slice 管理对应 header 存储,方便复用
请求体中同样处理的Key:User-Agent、Content-Type、 Content-Length、Connection、 Transfer-Encoding
取
核心字段快速解析使用byte slice存储额外存储到成员变量中
超高的转换效率比 net.http 提高 40倍
舍
额外的内存开销变更困难