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

89 阅读3分钟

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

  • 再谈HTTP协议
    • HTTP协议是什么
      • HTTP:超文本传输协议(Hypertext Transfer Protocol)
      • 为什么需要协议
        • 需要明确的边界
          • 开始
          • 结束
        • 协议元数据
          • 能够携带信息
            • 消息内容
            • 消息类型
    • 协议里有什么
      • 请求行
        • 方法名
        • URL
        • 协议版本
      • 状态行
        • 协议版本
        • 状态码
        • 状态码描述
      • 请求头/响应头
        • 协议相关
        • 业务相关
      • 请求体/响应体
    • 请求流程
      • 业务层
      • 服务治理层/中间件层
      • 路由层
      • 协议编解码层
      • 传输层
    • 不足与展望
      • HTTP1
        • 队头阻塞
        • 传输效率低
        • 明文传输不安全
      • HTTP2
        • 多路复用
        • 头部压缩
        • 二进制协议
      • QUIC
        • 基于UDP实现
        • 解决队头阻塞
        • 加密减少握手次数
        • 支持快速启动
  • HTTP框架的设计与实现
    • 分层设计
      • 专注性
      • 扩展性
      • 复用性
      • 高内聚 低耦合
      • 易复用
      • 高扩展性
    • 应用层设计
      • 提供合理的API
        • 可理解性
        • 简单性
        • 冗余性
        • 兼容性
        • 可测性
        • 可见性
    • 中间件层
      • 需求
        • 配合Handler实现一个完整的请求处理生命周期
        • 拥有预处理逻辑与后处理逻辑
        • 可以注册多中间件
        • 对上层模块用户逻辑模块易用
      • 洋葱模型
        • 核心逻辑与通用逻辑分离
        • 适用场景
          • 日志记录
          • 性能统计
          • 安全控制
          • 事务处理
          • 异常处理
    • 路由设计
      • 框架路由实际上就是为URL匹配对应的处理函数
        • 静态路由
        • 参数路由
        • 路由修复
        • 冲突路由以及优先级
        • 匹配HTTP方法
        • 多处理函数:方便添加中间件
      • 前缀匹配树
        • 如何匹配HTTP方法
          • 外层Map:根据method进行初步筛选
        • 如何实现添加多处理函数
          • 在每个节点上使用一个list存储handler
        • 如何查找路由
    • 协议层
      • 抽象出合适接口
      type Server interface{
          Serve(c context.Context, conn network.Conn) error
      }
      
    • 网络层
      • BIO:Block IO 阻塞IO
      go func(){
          for{
              conn,_ := listener.Accept()
              go func(){
                  conn.Read(request)
                  handle...
                  conn.Write(response)
              }
          }
      }
      
      • NIO:
      go func(){
          for{
              readableConns,_ := Monitor(conns)
              for conn := range readableConns{
                  go func(){
                      conn.Read(request)
                      handle...
                      conn.Write(response)
                  }()
              }
          }
      }
      
      • 设计
        • netpoll
        • NIO
        • 网络库管理buffer
  • 性能修炼之道
    • 针对网络库的优化
      • 存下全部Header
      • 减少系统调用次数
      • 能够复用内存
      • 能够多次读
      • go net with bufio
        • 绑定一块缓冲区
      • netpoll
        • 存下全部Header
        • 拷贝出完整Body
        • netpoll with nocopy peek
          • 分配足够大的buffer
          • 限制最大buffer size
      • 不同网络库优势
        • go net
          • 流式友好
          • 小包性能高
        • netpoll
          • 中大包性能高
          • 时延低
    • 针对协议的优化
      • Headers解析
        • 找到Header Line边界:\r\n
          • 先找到\n再看它前一个是不是\r
          • SIMD
        • 针对协议相关的Headers快速解析
          • 通过Header key首字母快速筛除掉完全不可能的key
          • 解析对应value到独立字段
          • 使用byte slice管理对应header存储,方便复用
      • Header key规范化
        • 映射表
      • 热点资源池化
        • Request Context
          • 与请求一一对应,贯穿一个请求始终