HTTP 框架修炼之道 | 青训营笔记

80 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第10篇笔记

课程背景

image.png

HTTP协议

HTTP协议是什么

HTTP:超文本传输协议(Hypertext Transfer Protocol)

image.png

为什么需要协议

需要明确的边界

  • 开始
  • 结束

能够携带信息

  • 什么消息
  • 消息类型

image.png

协议里面有什么

image.png

image.png

请求流程

image.png

不足与展望

image.png

HTTP 框架的设计与实现

分层设计

专注性
扩展性
复用性

image.png

高内聚低耦合

易复用

高扩展性

image.png

image.png

一个切实可行的复杂系统势必是从一个切实可行的简单系统发展而来的。从头开始设计的复杂系统根本不切实可行,无法修修补补让它切实可行。你必须由一个切实可行的简单系统重新开始。
--- 盖尔定律

应用层设计

image.png

提供合理的 API

  • 可理解性:如ctx.Body (), ctx.GetBody(),
    • 不要用ctx.BodyA()
  • 简单性:如ctx.Request.Header.Peek(key)
    • /ctx.GetHeader (key)
  • 冗余性
  • 兼容性
  • 可测性
  • 可见性

不要试图在文档中说明,很多用户不看文档

中间件设计

中间件需求:

  • 配合Handler实现一个完整的请求处理生命周期
  • 拥有预处理逻辑与后处理逻辑
  • 可以注册多中间件
  • 对上层模块用户逻辑模块易用

image.png


打印每个请求的request和 response

image.png


既然要实现预处理和后处理,那这个就很像调用了一个函数

image.png 路由上可以注册多Middleware,同时也可以满足请求级别有效,只需要将Middleware设计为和业务和 Handler相同即可。

用户如果不主动调用下一个处理函数怎么办?

image.png

image.png 出现异常想停止怎么办?

image.png

调用链

image.png 适用场景:

  • 不调用Next:
    • 初始化逻辑且不需要在同一调用栈
  • 调用Next:
    • 后处理逻辑或需要在同一调用栈上

路由设计

image.png

框架路由实际上就是为URL匹配对应的处理函数(Handlers)

  • 静态路由: /a/b/c、 /a/b/d
  • 参数路由: /a/:id/c (/a/b/c. /a/d/c)、 /*all
  • 路由修复: /a/b <-> /a/b/
  • 冲突路由以及优先级: /a/b、 /:id/c
  • 匹配HTTP方法
  • 多处理函数:方便添加中间件

image.png

青铜: map[string]handlers
    /a/b/c、/a/b/d  /a/:id/c、 /*all
黄金:前缀匹配树
/a/b/c、/a/b/d
如何处理带参数的路由注册?
(处理形如: /a/: id/b类型的路由)

image.png

如何匹配HTTP方法?

image.png 路由映射表

外层Map:根据method进行初步筛选

如何实现添加多处理函数? 在每个节点上使用一个list 存储handler

如何做设计

  1. 明确需求:考虑清楚要解决什么问题、有哪些需求
  2. 业界调研:业界都有哪些解决方案可供参考
  3. 方案权衡:思考不同方案的取舍
  4. 方案评审:相关同学对不同方案做评审
  5. 确定开发:确定最合适的方案进行开发

协议层设计

image.png

抽象出合适的接口 image.png

网络层设计

image.png

BIO

image.png

NIO

image.png

go get "BIO" 用户管理 buffer

image.png

netpoll NIO 网络库管理buffer

image.png

性能修炼之道

针对网络库的优化

go get

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

image.png go net

  • 存下全部Header
  • 减少系统调用次数
  • 能够复用内存
  • 能够多次读 go net with bufio
  • 绑定一块缓冲区

image.png

netpoll

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

image.png
netpoll with nocopy peek

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

image.png

image.png

不同网络库优势

image.png

针对协议的优化 -- Headers 解析

  • 找到Header Line边界: \r\n
  • 先找到\n再看它前一个是不是\r

image.png

image.png

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

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

请求体中同样处理的Key: User--Agent、Content--Type、 Content--Length、 Connection、Transfer-Encoding

image.png

image.png

针对协议的优化 -- Header key 规范化

image.png

image.png

热点资源池化

image.png

image.png