HTTP 框架修炼之道
课程引入
http协议大家应该很熟悉了,http协议也是当今使用的最多的协议之一。
大家的课程大作业,项目也接触过。
在学校老师 只会讲到http是什么,而不会谈到底层原理。
这样在工作中是万万不够的。
01. 再谈 HTTP 协议
最开始大规模使用的HTTP协议是 v0.9
1.1 为什么需要协议
协议有明确的边界
协议元数据:进行信息的描述,图片、音频、视频、超链接
1.2 协议里有什么
协议开始 请求方法
空格url空格协议版本元数据 由 : 分隔的键值对
请求回复
http版本
空格状态码空格OK (OK是对应状态码200 的描述)
各方法所在的版本(版本向下兼容)
patch 对应部分更新
put 对应整体更新
put 具有幂等性 而patch 无幂等性
一个小demo
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
)
func main() {
h := server.New()
h.POST("/sis", func(c context.Context, ctx *app.RequestContext) {
ctx.Data(200, "text/plain; charset=utf-8", []byte("OK"))
})
h.Spin()
}
1.3 请求流程
1.4 不足和展望
02. HTTP 框架的设计与实现
2.1 分层设计
一个切实可行的复杂系统势必是从一个切实可行的简单系统发展而来的。从头开始设计的复杂系统根本不切实可行,无法修修补补让它切实可行。你必须由一个切实可行的简单系统重新开始。 --- 盖尔定律
2.2 应用层设计
提供合理的 API
-
可理解行: 如 ctx.Body() ctx.GetBody()
ctx.BodyA() ==是不清晰的==
-
简单性: 如 ctx.Request.Header.Peek(key)
/ctx.GetHeader(key) ==高频==
-
冗余性 有了ctx.Body(),就不要有ctx.GetBody() ,不要一个接口是 两个接口拼接起的
-
兼容性
-
可测性
-
可见性 为了安全性 保障框架的安全性
2.3 中间件设计
需求
- 配合Handler实现一个完整的请求处理生命周期
- 拥有预处理逻辑与后处理逻辑
- 可以注册多中间件
- 对上层模块用户逻辑模块易用
洋葱模型
调用链
==思考== : 有没有其他的方式来处理 中间件
2.4 路由设计
路由匹配
参数路由
匹配 HTTP 方法
构造多个路由树
实现添加多处理函数
==思考== 如何查找路由
总结
2.5 协议层设计
2.6 网路层设计 传输层
BIO 阻塞IO Block
NIO
红圈内 go 经典对go func的一个处理 -》 先读完了, 再进行数据的 处理
设置监听器, 当有足够的 数据后 再处理
go net 需要用户来管理 buffer
字节开源 netpoll 的设计
2.7 总结
03. 性能修炼之道
3.1 针对网络库的优化
现状
go net 是 BIO
需求
3.2 针对协议的优化 --- Headers 解析
找到Header Line 边界 : \r\n
从有一定特征的字符串 中 找 杀鸡焉用牛刀
先找到\n 再看他前一个是不是\r
能不能更快呢?
SIMD Single Instruction Multiple Data
单指令集 多数据
一次处理多条数据
sm加速
取舍