HTTP 框架修炼之道 | 青训营

124 阅读2分钟

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 快速解析