HTTP连接处理流程
一、一次完整的HTTP请求过程
cloud.tencent.com/developer/articl...
二、go Web中HTTP连接处理流程
1、流程图
这个解释了三个问题:怎么监听的?怎么接收请求的?怎么处理连接的?
2、路由器和处理器
Go语言中处理HTTP请求主要跟两个东西相关:ServeMux和Handler。
ServeMux
:请求路由器,也叫多路复用器,Multiplexer。路由器,就是把收到的请求与一组预定义的URL路径列表做对比,然后在匹配到路径的时候调用关联的处理器,相当于一个能自动化匹配的路由表呗;
Hanlder
:处理器,实现了http.Handler
接口的类型,处理HTTP请求并生成对应的响应;
DefaultServeMux
:是一个实现了http.Handler
接口的默认路由器(ServeMux),因此也是一个处理器(Handler)。http.ServeMux
实现了http.Handler
接口。
3、Go代码的执行流程
首先调用
http.HandleFunc
按顺序做了几件事:
1、调用了DefaultServeMux的HandleFunc
2、调用了DefaultServeMux的Handle
3、往DefaultServeMux的map[string]muxEntry中增加对应的handler和路由规则
其次调用了
http.ListenAndServe(":9090",nil)
按顺序做了几件事:
1、实例化Server
2、调用Server的ListenAndServe()
3、调用net.Listen(“tcp”,addr)监听端口
4、调用srv.Serve(l net.Listener)
启动一个for循环,在循环体中Accept请求
对每个请求实例化一个Conn,并且开启一个goroutine为这个请求进行服务 go c.serve()
5、读取每个请求的内容w,err:=c.readRequest()
6、判断handler是否为空,如果没有设置handler,handler就设置为DefaultServeMux
7、调用handler的ServeHTTP:即根据request选择handler,并且进入到这个handler的ServeHTTP
判断是否有路由能满足这个request(循环遍历ServeMux的muxEntry)
(1)如果有路由满足,调用这个路由handler的ServeHTTP
(2)如果没有路由满足,调用NotFoundHandler的ServeHTTP
【备注】调用ListenAndServe的第6步和第7步中的handler含义不一样,第6步是参数二的类型,路由器的含义;第7步是查询路由表看看是否有匹配的url以及对应的处理函数,即这里的handler是处理器的含义。所以两者不要混淆。
4、ServeMux
(1)解释
go自带的请求路由器,扮演角色是Multiplexer(多路复用器),用来将请求根据url路由给已注册的handler。
(2)结构
看看net/http/server.go文件中ServeMux的结构:
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
hosts bool // whether any patterns contain hostnames
}
type muxEntry struct {
h Handler
pattern string
}
一个字段mu是RWMutex,m是注册handler和pattern的,hosts用于判断pattern是否包含了host的匹配。
唯一需要注意的是,每个Handle()都会对ServeMux实例加上写锁。
以常用的DefaultServeMux为例,它是ServeMux的一个实例。当使用DefualtServeMux时,每调用一次Handle()或HandleFunc(),都意味着向这个DefaultServeMux的结构中的m字段添加pattern和对应的handler。由于加了写锁,如果使用多个goroutine同时启动多个web服务,在同一时刻将只能有一个goroutine启动的web服务能设置DefaultServeMux。当然,一般情况下不会使用goroutine的方式同时启动多个web服务。
(3)http.ServeMux的局限性
http.ServeMux 在 goblog 中使用,会遇到以下几个问题:
不支持 URI 路径参数
不支持请求方法过滤
不支持路由命名
(4)http.ServeMux 的优缺点
优点
标准库意味着随着 Go 打包安装,无需另行安装
测试充分
稳定、兼容性强
简单,高效
缺点
缺少 Web 开发常见的特性
在复杂的项目中使用,需要你写更多的代码
开发效率和运行效率,永远是对立面。
Go 因为其诞生的背景(Google 的大流量),以及核心成员的出身(底层语言和系统的缔造者),Go 标准库选择 运行效率 高于 开发效率,所以对一些常见的功能并没有添加到标准库中,这是情有可原的。
新手常常会认为标准库里的就是最好的。其实不然,标准库也是由 Go 语言编写的。
就拿 net/http
来讲,GitHub 上有一个项目专门对 Go 中知名的 HTTP 路由器性能做对比,结果是第三方包 HttpRouter 比 http.ServeMux 还要快不少。
事实上,标准库最大的优点是 Go 自带。
所以不止在选择 HTTP 服务器,在选择其他解决方案时,都可以大胆的使用一些 Go 开源社区优秀的第三方包。
本作品采用《CC 协议》,转载必须注明作者和本文链接