写在前面
由于还没有学过《计算机网络》这门课程,在实践时面对网络传输相关的代码总是发怵。今天就让我来恶补一下相关知识。
关于HTTP协议的基础知识
1.HTTP协议是什么?
HTTP的英文全称是Hypertext Transfer Ptotocal,直译过来就是超文本传输协议。在常见的开发中,HTTP协议是连接前后端的重要桥梁。
2.HTTP协议的基础框架是什么样子?
3.一个常见的POST请求在协议层做了什么?
客户端:
POST/sis HTTP/1.1
//请求行
//方法名(POST),URL(sis HTTP),协议版本(1.1)
Who:Alex
Content-Type:text/plain
Hoist:127.0.0.1:8080
//请求头
Let's watch a movie togethor!
//请求体
服务端:
HTTP/1.1 200 OK
//状态行
//HTTP版本号(1.1),状态码(200),对于状态码的描述(OK)
Server:hertz
Date:Thu,21 Apr 2022 11 11:46:32 GMT
Content-Type:text/plain;charset=utf-8
Content-Length:2
Upstream-Caught:165054159283580
//响应头
OK
//相应体
HTTP的各层具体设计
应用层设计
这是与用户直接打交道的一层,对于用户的请求进行抽象,提供丰富易用的API。 在设计时应该注重一下几点:
- 可理解性:如ctxBody(),不要用ctx.BodyA()
- 简单性:如ctx.GetHeader(key)
- 冗余性
- 兼容性
- 可测性
- 可见性
中间件层设计
这一层对于用户有预处理和后处理的逻辑。 在设计时应该要注意以下几点:
- 配合
Handlers层实现一个完整的请求处理生命周期 - 拥有预处理逻辑和后处理逻辑
- 可以注册使用多个中间件
- 对于上层模块用户逻辑模块易用
中间件设计(洋葱模型)
- 既然要实现预处理和后处理,那这个就很像调用了一个函数
func Middleware(some param) {
// some logic for pre-handle
……
nextMiddleware ( ) / bizlogic ( ) #可以统一变为next()
// some logic after-handle
……
}
-
路由上可以注册多个
Middleware,同时也可以满足请求级别有效。
只需要将Middleware设计为和业务和handler相同即可 -
用户如果不主动调用下一个函数怎么办?帮助用户主动实现
func (ctx *RequegstContext) Next() {
ctx.index++
for ctx.index < int8(len(ctx.handlers)) {
ctx.handlers[ctx.index]()
ctx.index++
}
}
核心:在任何场景下index保持递增
- 出现异常想停止怎么办?
func (ctx *RequegstContext) Abort() {
ctx.index = IndexMax
}
- 不同场景的中间件调用方式不同
不调用
Next:初始化逻辑且不需要在同一调用栈 调用Next:后处理逻辑或需要在统一调用栈上
路由层设计(前缀匹配树)
这一层主要用来注册、寻址等。框架路由实际上是为了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方法 - 多处理函数:方面添加中间件
协议层设计
Type Server interface {
Serve(c context.Context, conn network.Conn) error
}
抽象出合适的接口
- 不要把
Context存储到结构体当中,相反,应该把Context精准地传递到每一需要的function上去。同时Context应该是第一个参数 - 需要在连接上读写数据
网络层设计
网络模型(BIO)
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)
}()
}
}
}()