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来存储和查找路由规则。