这是我参与「第三届青训营 - 后端场」笔记创作活动的的第 4 篇笔记。
一、再谈HTTP协议
1.1 HTTP请求
协议组成: 开始+元数据+Text+结束
- 请求行
- 常见方法名
- GET
- HEAD
- POST
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
- URL
- 协议版本
- 常见方法名
- 状态行
- 协议版本
- 状态码
- 1xx: 信息类
- 2xx: 成功
- 3xx:重定向
- 4xx:客户端错误
- 5xx: 服务端错误
- 状态码描述
- 请求头
- 响应头
- 请求体
- 响应体
1.2 不足与展望
- HTTP1
- 队头阻塞
- 传输效率低
- 明文传输不安全
- HTTP2
- 多路复用
- 头部压缩
- 二进制协议
- QUIC
- 基于UDP实现
- 解决队头阻塞
- 加密减少握手次数
- 支持快速启动
二、HTTP框架设计与实现
2.1 分层设计
分层的好处
- 专注性
- 扩展性
- 复用性
2.2 应用层设计
- 冗余性
- 兼容性
- 可测性
- 可见性
2.3 中间件设计
- 洋葱模型
- 日志
- Metrics
- Biz Handler
- 使用场景
- 日志记录
- 性能统计
- 安全控制
- 事务处理
- 异常处理
2.4 路由设计
- 静态路由: /a/b/c、/a/b/d
- 参数路由: /a/:id/c (/a/blc,la/d/c)、/*all
- 路由修复: /a/b<-> la/bl
- 冲突路由以及优先级: /a/b./:id/c
- 匹配HTTP方法
- 多处理函数:方便添加中间件
如何做设计?
- 明确需求
- 业界调研
- 方案权衡
- 方案评审
- 确定开发
三、性能修炼之道
- 针对网络库的优化
- go net
- 流式友好
- 小包性能好
- netpoll
- 中大包性能好
- 时延低
- go net
- 针对协议库的优化
- Header解析
- 根据Header Key首字母快速过滤不可能的Key
- 解析对应Value到独立字段
- 使用Byte slice管理对应header存储,方便复用
- 取:
- 核心字段快速解析
- 使用byte slice存储
- 额外存储到成员变量中
- 舍:
- 普通header性能较低
- 没有map结构
- Header key规范化
- 取:
- 超高的转换效率
- 比 net.http提高40倍
- 舍:
- 额外的内存开销
- 变更困难
- 取:
- 热点数据池化
- 取:
- 减少了内存分配
- 提高了内存复用
- 降低了GC压力
- 性能提升
- 舍:
- 额外的Reset逻辑
- 请求内有效
- 问题定位难度增加
- 取:
- Header解析