HTTP分层设计

34 阅读2分钟

HTTP是什么

HTTP:超文本传输协议(Hypertext Transfer Protocol)

为什么需要协议

需要明确的边界

  1. 开始
  2. 结束

携带的信息

  1. 什么消息
  2. 消息类型(text、图片...)
  3. ...

协议里有什么

请求行/状态行

方法名

GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATCH

URL

协议版本

状态码

  1. 1xx: 信息类
  2. 2xx: 成功
  3. 3xx: 重定向
  4. 4xx: 客户端错误
  5. 5xx: 服务端错误

状态码描述

请求头/响应头

协议约定业务相关

请求体/响应体

不足与展望

HTTP1

  1. 队头阻塞
  2. 传输效率低
  3. 明文传输不安全

HTTP2

  1. 多路复用
  2. 头部压缩
  3. 二进制协议

QUIC(Quick UDP Internet Connections)

  1. 是一种基于UDP的传输层协议
  2. 解决队头阻塞
  3. 加密减少握手次数
  4. 支持快速启动

应用层设计

提供合理的API

可理解性

  • 使用ctx.Body() ctx.GetBody()

  • 而不是用ctx.Body()

简单性

  • ctx.Reaquest.Header.Peek(key)
  • cts.GetHeader(key)

冗余性

  • 如果有ctx.Body()就没有必要有ctx.GetBody()
  • 不要一个接口是由宁外两个接口拼起来

兼容性

可测性

可见性

中间件设计

需求

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

洋葱模型

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

路由设计

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

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

方式

  • 使用map的方式映射
  • 路由前缀树

匹配HTTP请求

外层map,根据Method进行初步筛选,在通过路由前缀树进行匹配

协议层设计

抽象出合适的接口

type Server interface {
  Serve(c context.Context, coon network.Conn) error
}

Don't store Contexts inside a struct type; instead, pass a Context explicitly to each function that nedds it. The Context should be the first parameter.

在连接上读写数据

网络层设计

确保数据包能够高效、可靠、安全地从源地址传输到目标地址。

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)
      }()
    }
  }
}()

go net 是BIO

type Conn interface {
  Read(b []byte) (n int, err error)
  Write(b [] byte) (n int, err error)
  ...
}

netpoll 是NIO

type Reader interface {
  Peek(n int) ([]byte, error)
  ...
}

type Writer interface {
  Malloc(n int) (buf []byte, err error)
  Flush() error
  ...
}

type Conn interface {
  net.Conn
  Reader
  Writer
}