这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记
在“HTTP框架修炼之道”这一课中,老师带大家讲了HTTP框架的设计与实现后,讲到了HTTP框架的优化。在这一篇笔记里,我总结了老师关于HTTP框架的优化的讲解。
针对新能优化,我们主要可以从两个方面下手,一个是针对网络库进行优化,另一个方向是针对协议进行优化
针对网络库
我们以Go Net为例,Go Net使用的是BIO,buffer全部交有用户端管理并且存放在用户端,使得gc负担较大
我们改进的需求有如下四点:
- 存下所有的Header
- 减少系统调用次数
- 能够复用内存
- 能够多次读
我们改进的方式为Go Net with bufio, 具体内容如下:
- 绑定一块缓冲区
- 提供release方法释放内存空间
对于另一个案子Netpoll,我们的目标有两点:
- 存下全部Header
- 拷贝出完整的Body
我们改进的方式为Netpoll with nocopy peek, 具体内容如下:
- 分配足够大的buffer 根据历史到来的数据大小,自适应的分配buffer大小,保证buffer可以容纳绝大多数的数据
- 限制最大buffer size 保障内存使用率,避免由于一两个特殊的大数据的到来,导致后续buffer分配都过大
针对协议
第一个方向在于如何高效的找到Header Line(\r\n)
这里没必要使用经典的字符串匹配算法,由于目标字符串是固定的且有明显特征
初步的优化是先找到\n,再看他前一个是不是\r
进一步的优化是使用SIMD进行加速
SIMD优化Header Line查询有如下优缺点
- pros:核心字段快速解析、使用byte slice存储、额外存储到成员变量中
- cons:不同header性能较低、没有map结构
另一个思路是对Header key进行规范化,例如驼峰命名
Header key规范化有如下优缺点
- pros:超高的转换效率、比net.http提高40倍
- cons:额外的内存开销、变更困难
还有一个很好的想法是使用热点资源池化技术 用热点资源池化有如下优缺点
- pros:减少内存非陪、提高内存复用、减少gc压力、性能提升
- cons:额外的Reset逻辑、请求内有效、问题定位难度增加(由高并发导致的数据不一致的问题在低并发测试场景中无法复现)