HTTP连接处理流程

一、一次完整的HTTP请求过程

cloud.tencent.com/developer/articl...

二、go Web中HTTP连接处理流程

1、流程图

这个解释了三个问题:怎么监听的?怎么接收请求的?怎么处理连接的?

img

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。

HTTP连接处理流程

(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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!