net/http标准库
使用net/http库来创建一个http服务:
|
|
通过go doc net/http | grep "^func"
命令查询出net/http
库所有的对外函数:
|
|
去掉New和Set开头的函数,剩下的函数可以分为这三大类:
- 为服务端提供创建HTTP服务的函数,名字中一般包含
Serve
; - 为客户端提供调用HTTP服务的类库,以http的
method
同名,比如Get,Post,Head等; - 提供代理的一些函数,比如
ProxyURL
,ProxyFromEnvironment
等。
先分析Serve
函数:
|
|
先从启动服务的http.ListenAndServe
函数开始:
|
|
通过示例代码和http.ListenAndServe
源码可以看到,该方法创建一个Server
结构,调用Server.ListenAndServe
对外提供服务。接下来再看Server.ListenAdnServer
源码:
|
|
Server.ListenAdnServer
方法先定义了监听信息,再调用Serve
方法。在Serve
方法中,用一个for循环,通过l.Accept
不断接收从客户端传来的请求连接。当接收到一个新的请求时,通过srv.Conn
创建一个连接结构(http.conn),并创建一个goroutine
去处理这个请求。
|
|
从c.serve(connCtx)
开始就是单个连接的逻辑了。c.serve
函数先判断本次请求时候需要升级为https,然后创建都文本的reader
和写文本的buffer
,再进一步读取本次请求数据,然后调用serverHandler{c.server}.ServeHTTP(w, w.req)
来处理这次请求。
|
|
DefaultServeMux
是一个ServeMux
结构的实例,是一个多路复用器。在最前面调用http.ListenAndServe()
时,如果没有传入第二个参数hanler,则handler = DefaultServeMux
。
启动http服务的时候,可以使用http.HandleFunc()
来指定路由和处理函数。
|
|
通过源码可以看到,最终的调用是ServeMux.Handle
方法。ServeMux.Handle
是一个非常简单的map
实现,key
是路径(pattern),value
是这个pattern
对应的处理函数。它是通过mux.match(path)
寻找对应的Handler
,
也就是DefaultServeMux
内部的map中直接根据key
寻找到value
的。
总结
抛去关于HTTPS的处理,具体的刘城逻辑就是:
- 创建http服务是通过创建一个
Server
结构完成的; Server
在for循环里不断监听每一个连接;- 每个连接默认开启一个
goroutine
去处理; Server
如果没有设置处理函数Handler
,默认使用DefaultServeMux
处理请求;DefaultServeMux
是使用map来存储和查找路由规则。