HTTP框架设计与实现 | 青训营笔记

141 阅读2分钟

分层设计

OSI是Open System Interconnection的缩写,称为开放式系统互联。

OSI模型把网络通信分为7层,从下到上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

OSI分层太多,增加了网络工作的复杂性,后来进行了见后,将一些层进行合并形成了4层结构,从下到上分别为接口层、网络层、传输层和应用层,也就是TCP/IP模型。

分层设计可以提高专注性、扩展性、复用性。

在分层设计的时候应该考虑高内聚低耦合、易复用、高扩展。

应用层设计

应用层是和用户打交道的一层,提供合理的API。

在设计API时,需要考虑以下几点:

  • 可理解性
    • 如:ctx.Body()、ctx.GetBody(),而不是ctx.BodyA()。
  • 简单性
    • 如:ctx.Request.Header.Peek(key)封装为ctx.GetHeader(key)
  • 冗余性
  • 兼容性
  • 可测性
  • 可见性

中间件设计

中间件在工作中,常常有以下需求:

  • 配合Handler实现一个完整的请求处理声明周期
  • 拥有预处理逻辑与后处理逻辑
  • 可以注册多中间件
  • 对上层模块用户逻辑模块易用

如下图是一个洋葱模型,洋葱模型试用场景:

  • 日志记录
  • 性能统计
  • 安全控制
  • 事务处理
  • 异常处理

洋葱模型的思想是核心逻辑与通用逻辑分离。

预处理、后处理

中间件要实现预处理和后处理,很像调用了一个函数,如:

func Middleware(some param) {
	// some logic for pre-handler
	Next()
	// some logic for after-hanler
}

路由上可以注册多个中间件,同时也可以满足请求级别有效只需要将中间件设计为和业务和hanlder相同即可。

如果用户不主动调用下一个处理函数怎么办?

我们可以让用户在使用调用中间件时,先进行初始化,然后中间件处理调用的逻辑,如:

func (ctx *RequestContext) Next() {
    ctx.index++
    for ctx.index < int8(len(ctx.handlers)) {
        ctx.hanlers[ctx.index]()
        ctx.index++
    }
}

核心思想是在任何场景下index保证递增。

如果出现异常想停止怎么办?

只需要给index赋值一个最大值,跳出循环即可,如:

func (ctx *RequestContext) Abort() {
    ctx.index = IndexMax
}

路由设计

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

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

如何做设计

  1. 明确需求:考虑清楚要解决什么问题,有哪些需求
  2. 业界调研:业界都有哪些解决方案可供参考
  3. 方案权衡:思考不同方案的取舍
  4. 方案评审:相关同学对不同方案做评审
  5. 确定开发:确定最合适的方案进行开发