HTTP框架的性能优化 | 青训营笔记

50 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天

针对网络库的优化

需求

Go net 是 BIO 模型

  • 存下全部Header
  • 减少系统调用次数
  • 能够复用内存
  • 能够多次读

优化

go net with bufio

绑定一块缓冲区,大部分的包都在4kb以下的

需求

netpoll

  • 存下全部 Header
  • 拷贝出完整的Body

优化

netpoll with nocopy peek

  • 分配足够大的buffer
  • 限制最大buffer size

不同网络库的优势

go net

  • 流式友好:用户没有调用,数据一直保留在缓冲区中
  • 小包性能高:连接上绑定内存,通常情况下,4kb足够,不过一旦超过4kb,buffer申请回收就导致性能低下

netpoll

  • 中大包性能高:由底层进行内存管理
  • 时延低

针对协议的优化

Header 解析

找到 Header Line 边界: \r\n

先找到 \n 再看它前一个是不是 \r ,这样复杂度就变成 O(N)了

SIMD : 单指令多数据流技术,golang自动使用SIMD加速技术进行匹配

2.jpg

针对协议相关的Headers快速解析:

  1. 通过 Header Key 首字母快速筛除掉完全不可能的 key
  2. 解析对应 value 到独立字段
  3. 使用 byte slice 管理对应 header 存储,方便复用

请求体中同样处理的key:

User-Agent、Content-Type、Content-Length、Connection、Transfer-Encoding

取:

  • 核心字段快速解析:
  • 使用byte slice 存储:更方便做内存管理,可以对内存进行复用
  • 额外存储到成员变量中:采用.方式拿出成员变量

舍:

  • 普通header性能较低
  • 没有map结构

Header Key 规范化

aaa-bbb --> Aaa-Bbb

取:

  • 超高的转换效率
  • 比 net.http提高40 倍

舍:

  • 额外的内存开销
  • 变更困难

热点资源池化

3.jpg

取:

  • 减少内存分配次数
  • 提高了内存复用
  • 降低了GC压力
  • 性能提升

舍:

  • 额外的 Reset 逻辑
  • 请求内有效
  • 问题定位难度增加

总结

  • 针对网络库的优化:buffer设计
  • 针对协议的优化:header 解析、热点资源池化