HTTP修炼之道|青训营笔记

81 阅读3分钟

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

HTTP协议

定义

HTTP:超文本传输协议(Hypertext Transfer Protocol),能够附加如图片、链接、视频等这样的文本叫做超文本
协议明确了传播的消息的边界(开始点和结束点)、记录了消息数据、类型

组成

请求行:包含方法名、URL、协议版本
状态行:包含协议版本、状态码、状态码描述
POST /sis HTTP/1.1

元数据(请求头/响应头):协议相关数据
Who: Alex
Content-Type: text/plain
Host: 127.0.0.1:8888
Content-Length: 28

请求体/响应体:业务相关数据
Hello world

请求流程

image.png

不足与发展

HTTP1:队头阻塞、传输效率低、明文传输不安全

HTTP2:多路复用、头部压缩、二进制协议

QUIC:基于UDP实现、解决队头阻塞、加密减少握手次数、支持快速启动

HTTP框架的设计与实现

应用层设计

提供合理的API

  1. 可理解性
  2. 简单性
  3. 冗余性
  4. 兼容性
  5. 可测性
  6. 可见性

中间件层设计

中间件层的需求

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

洋葱模型

image.png 适用场景:日志记录、性能统计、安全控制、事务处理、异常处理

路由层设计

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

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

实现方案

  1. map映射,但是只能处理静态路由
  2. 前缀匹配树

如何匹配http方法?

image.png

协议层设计

image.png

  1. Do not store Contexts inside a struct type; instead, pass a Context explicitly to each function that needs it. The Context should be the first parameter(不要把Context放在结构体里面,而是应该当作需要他的函数的第一个参数传入函数中)
  2. 需要在连接上写数据

传输层设计

  1. BIO:读数据的时候会先阻塞,直到读到足够的数据再进行处理
  2. NIO:监听数据,当存在足够的数据才读取,不会阻塞

网路层设计

go net网络库

框架优化

针对网络库的优化

go net——流式友好、小包性能好

  1. 存下全部的Header
  2. 减少系统调用次数
  3. 能够复用内存
  4. 能够多次读

netpoll——大包性能好,时延低

  1. 存下全部的Header
  2. 拷贝出完整的body

针对

Headers解析

  1. 找到Header Line变价:\r\n——先找到\n再看它前一个是不是\r

针对协议相关的Header快速解析

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

Header key规范化 aaa-bbb -> Aaa-Bbb:使用表映射的方式将字节存储到map中