HTTP 框架修炼之道
1. 分层设计
1.1 应用层设计
提供合理的 API:可理解性 & 简单性 & 冗余性 & 兼容性 & 可测性 & 可见性
1.2 中间件设计
洋葱模型:
适用场景:日志记录、性能统计、安全控制、事务处理、异常处理
调用链
[!question] 中间件有没有其他实现方式?
1.3 路由设计
为 URL 匹配对应的处理函数(handlers),具体内容:
- 静态路由:
/a/b/c、/a/b/d - 参数路由:
/a/:id/c、/* - 路由修复:
/a/b->/a/b/ - 冲突路由以及优先级
- 匹配 HTTP 方法
- 多处理函数:方便添加中间件
- ……
具体实现:
- 匹配 URL:前缀匹配树
- 匹配 HTTP 方法:路由映射表
- 添加多处理函数:在每个节点上使用一个 list 存储 handler
[!question] 如何查找路由?
1.4 协议层
抽象出合适的接口:
type Server interface {
Server(c context.Context, conn network.Conn) error
}
1.5 网络层设计
分类:
- BIO (Block IO)
- NIO (Non-block IO)
标准库:
- go net:BIO,由用户管理 buffer
- netpoll:NIO,由网络库管理 buffer
2. 性能修炼之道
2.1 针对网络库的优化
go net
type Conn interface {
Read(b []byte) (n int, err error)
Write(b []byte) (n int, err error)
...
}
优化目标:
- 存下所有的 header
- 减少系统调用次数
- 复用内存
- 能多次读
优化方法:
- go net with bufio:给 go net 绑定一块缓冲区
优势:流式友好,小包性能好
netpoll
优化目标:
- 存下全部 header
- 拷贝出完整的 Body
优化方法:
- netpoll with nocopy peek
- 分配足够大的 buffer
- 限制最大的 buffer size
优势:中大包性能高,时延低
2.2 针对协议的优化
Headers 解析:
- 找到 Header Line 边界:
\r\n- 使用 SIMD
- bytedance/sonic:使用了 SIMD 技术的 JSON 序列化/反序列化库
- 针对协议相关的 Headers 快速解析