HTTP框架相关介绍 | 青训营

77 阅读2分钟

HTTP框架相关介绍

What is HTTP?

  • HTTP:超文本传输协议(Hypertext Transfer Protocol)
    超文本:Text以上更高级的文件内容(图片,视频,超链接等)

Why need HTTP?

信息传输需要明确的边界(开始-结束)

  • HTTP结构:协议开始-协议元数据-Text-协议结束
    对应:请求行/状态行-请求头/响应头-请求体/响应体
    • 请求行分为:方法名,URL,协议版本;
      常见的方法名:GET,HEAD,POST,PUT,DELETE,CONNECT,OPTIONS,TRACE,PATCH
    • 状态行分为:协议版本,状态码,状态码描述; 常见的状态码:1xx:信息类;2xx:成功;3xx:重定向;4xx:客户端错误;5xx:服务端错误;
    • 余略

How do HTTP?

  • 建立连接-发送请求-服务器响应-传输数据-关闭连接

HTTP框架的设计

分层设计(特点:高内聚,低耦合,易复用,高扩展性)
应用层(Application)-中间件层(middleware)-路由层(route)-协议层(codec)-网络层(transport)

  • 应用层设计-提供合理的API
    • 可理解性:提供接口例如ctx.Body(),ctx.GetBody();
      错误示范:ctx.BodyA;
    • 简单性:如ctx.Request.Header.Peek(key)可以简化为ctx.GetHeader(key);
    • 冗余性
    • 兼容性
    • 可测性
    • 可见性
  • 中间件设计-洋葱模型
    • 日志->Metircs->Biz Handler,即预处理和后处理
func Middleware (some param){
    //预处理
    ...
    Next()
    //后处理
    ...
}

若用户不调用Next(),我们需要让逻辑自动执行

  • 路由设计 框架路由实际上就是为URL匹配对应的处理函数(Handers)
    • 构建路由树--匹配参数路由
    • 如何实现添加多处理函数
      在每个节点上使用一个list存储handler
    type node struct{
        prefix string 
        parent *node
        children children
        handlers app.HandlersChain
        ...
    }
    
  • 协议层设计 -抽象出合适的接口
    type Server interface {
        Serve(c context.Context,conn network.Conn)error
    }
    
  • 网络层(传输层)设计
    • 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)
            }()
          }
        }
    }()
    
  • 一些golang的net设计例子 EG:
//Client结构体
//Go语言中的`http.Client`结构体是用于发送`HTTP`请求并返回响应的组件。它的定义如下:
type Client struct {
    Transport     RoundTripper
    CheckRedirect func(req *Request, via []*Request) error
    Jar           CookieJar
    Timeout       time.Duration
}
//自定义请求 `Header`
req, err := http.NewRequest("GET", "https://www.example.com", nil)    
if err != nil {
        log.Fatal(err)    
}
req.Header.Set("Accept", "application/json")
req.Header.Set("Authorization", "Bearer my-token")
//自定义参数
query := url.Values{}    
query.Add("q", "golang")    
query.Add("page", "1")
url := &url.URL{
        Scheme:   "https",
        Host:     "www.example.com",
        Path:     "/search",
        RawQuery: query.Encode(),
}
req, err := http.NewRequest("GET", url.String(), nil)    
if err != nil {
        log.Fatal(err)
}
  • 收获-如何做设计
    • 明确需求:考虑清楚要解决什么问题、有哪些需求
    • 业界调研:业界都有哪些解决方案可供参考
    • 方案权衡:思考不同方案的取舍
    • 方案评审:对不同的方案进行评审
    • 确定开发:确定最合适的方案进行开发