HTTP 协议与HTTP框架设计与优化 | 青训营

67 阅读4分钟

HTTP,文本传输协议(Hypertext Transfer Protocol),超在哪?超在支持传输各种类型的数据,图片、视频、超链接等。

协议组成

POST /api/data HTTP/1.1
Host: example.com
Content-Type: application/json

{
    "name": "John Doe",
    "age": 30,
    "email": "john@example.com"
}

请求行/状态行

POST /xxx HTTP/1.1

  1. Method:表示HTTP请求的方法或动作,通常是大写字母,例如GET、POST、PUT、DELETE等。不同的方法代表着不同的请求行为。
  2. Request-URI:表示请求的目标资源标识符(Uniform Resource Identifier),即请求的URL或路径。例如: /index.html、**/api/data**等。
  3. HTTP-Version:表示HTTP协议的版本。目前常见的版本有HTTP/1.0和HTTP/1.1。

请求头/响应头

HTTP请求头(HTTP Request Headers)是HTTP请求中的一组字段,用于向服务器传递额外的信息和参数。请求头包含在HTTP请求的头部,位于请求行之后,每个字段由键值对组成,键和值之间用冒号分隔,每个字段以换行符(CRLF,Carriage Return Line Feed)分隔(因为每个OS中对换行的定义都不同,有\n,有\r\n)

常见的HTTP请求头字段包括:

  1. User-Agent:用于标识发送请求的客户端应用程序或用户代理的信息。
  2. Host:指定目标服务器的主机名和端口号。
  3. Accept:指定客户端可以处理的媒体类型(MIME类型)。
  4. Content-Type:用于指定请求主体的MIME类型,表示请求中包含的数据类型。
  5. Content-Length:指定请求主体的长度,通常用于POST请求。
  6. Authorization:用于在请求中传递身份验证信息,例如基本身份验证或令牌。
  7. Referer:指定当前请求的来源URL,常用于记录页面跳转来源。
  8. Cookie:包含由服务器发送的cookie信息,用于向服务器发送存储在客户端的cookie数据。
  9. If-Modified-Since:用于条件性GET请求,表示只有在指定时间之后有修改时才会返回资源。
  10. Cache-Control:用于控制缓存的行为,例如指定缓存策略或禁止缓存。
  11. Origin:指定请求的来源,用于跨域请求时的安全检查。
  12. X-Requested-With:用于指示异步请求的来源,常用于判断是否是AJAX请求。

请求体

在HTTP请求中,请求体的存在与否取决于请求的类型和需要传递的数据。对于GET请求,通常不包含请求体,因为GET请求的参数会通过URL的查询字符串来传递。而对于POST、PUT等请求,请求体可以用来传递更大量的数据或复杂的数据结构,通常会包含在请求中。

请求体的格式和内容由请求头中的**Content-Type**字段来指定,它表示请求体中数据的媒体类型(MIME类型)。

不足和展望

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

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

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

设计HTTP框架

网路分层设计介绍——OSI

image.png

运用中间件设计——洋葱模型

Better:

  1. 外层:日志中间件
  2. 中层:Metrics中间件
  3. 内层:Biz、Handler。

请求由外向内,响应由内向外

路由设计

  1. 静态路由
  2. 动态路由
  3. 路由修复
  4. RestFul API规范实现
  5. 多处理函数(multi-handler)

可用前缀匹配树(map只适用于静态路由)来匹配路由。

协议层设计

  • 有error要及时抛出

网络层设计

  • BIO:阻塞IO。在接收数据时,阻塞。
  • NIO:非阻塞IO。可用goroutine。如在接收数据时,用Monitor来监听,不阻塞。

golang的net包用的是BIO,需要用户管理buffer。字节的netpoll用的是NIO,内部管理buffer。

优化

Headers解析

  1. 先找到\n,再找\r。
  2. 通过Header key的首字母快速筛选掉完全不可能的key
  3. 解析value到独立字段
  4. 可以使用byte slice管理header存储,方便复用。

Header key规范化

对大小写转换(user-key → User-Key)用表映射(打表)。

热点资源池化

就是缓存热点资源。

  1. 追求性能
  2. 追求易用,减少误用
  3. 文档建设、用户群建设。

Q/A

HTTP框架为什么要分层设计?优势和劣势?

为了提高代码的可维护性、可扩展性和代码的重用性。分层设计可以将不同的功能模块划分为独立的层,每个层都专注于特定的任务,使得整个框架更加模块化和易于管理、可扩展性高。**劣势:**分层设计可能引入一些额外的开销,因为不同层之间的通信可能需要序列化、反序列化等操作

中间件实现方式?

  1. 洋葱模型。
  2. 基于条件的洋葱模型。
  3. 装饰器模式。类似于python函数的装饰器。可想而知,这样可以支持更加高细粒度的业务。
  4. AOP。