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:服务端错误;
- 余略
- 请求行分为:方法名,URL,协议版本;
How do HTTP?
- 建立连接-发送请求-服务器响应-传输数据-关闭连接
HTTP框架的设计
分层设计(特点:高内聚,低耦合,易复用,高扩展性)
应用层(Application)-中间件层(middleware)-路由层(route)-协议层(codec)-网络层(transport)
- 应用层设计-提供合理的API
- 可理解性:提供接口例如ctx.Body(),ctx.GetBody();
错误示范:ctx.BodyA; - 简单性:如ctx.Request.Header.Peek(key)可以简化为ctx.GetHeader(key);
- 冗余性
- 兼容性
- 可测性
- 可见性
- 可理解性:提供接口例如ctx.Body(),ctx.GetBody();
- 中间件设计-洋葱模型
- 日志->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)
}
- 收获-如何做设计
- 明确需求:考虑清楚要解决什么问题、有哪些需求
- 业界调研:业界都有哪些解决方案可供参考
- 方案权衡:思考不同方案的取舍
- 方案评审:对不同的方案进行评审
- 确定开发:确定最合适的方案进行开发