1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
func (srv *Server) ListenAndServe() error {
...
ln, err := net.Listen("tcp", addr)
...
return srv.Serve(ln)
}
func (srv *Server) Serve(l net.Listener) error {
...
// 将listener封装进server
ctx := context.WithValue(baseCtx, ServerContextKey, srv)
for {
// 无限循环,accept接收客户端的请求
rw, err := l.Accept()
if err != nil {
select {
case <-srv.getDoneChan():
return ErrServerClosed
default:
}
if ne, ok := err.(net.Error); ok && ne.Temporary() {
... // 设置默认超时时间
time.Sleep(tempDelay)
continue
}
return err
}
// 封装accept到的连接,起一个goroutine来处理这个连接,之后继续等待accept的返回
connCtx := ctx
if cc := srv.ConnContext; cc != nil {
connCtx = cc(connCtx, rw)
...
}
tempDelay = 0
c := srv.newConn(rw)
c.setState(c.rwc, StateNew) // before Serve can return
// 每次有连接进来都会起一个协程来处理
go c.serve(connCtx)
}
}
func (c *conn) serve(ctx context.Context) {
...
// 处理连接、tls处理之类的,从连接中读取数据,封装成request、response,交给serverHandler处理
...
if requestBodyRemains(req.Body) {
registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)
} else {
// 该方法会起一个新协程在后台读取连接,就靠它来实现请求还没处理完就能进行取消的功能
// 实际上,取消后,只是连接被中断了,业务代码该执行还是在执行,执行完才能收到cancel信号
w.conn.r.startBackgroundRead()
}
// 默认的serverHandler.ServeHTTP方法会进行判断:
// 如果handler为空就会使用默认的DefaultServeMux,否则就用用户定义的ServeHTTP来处理请求
serverHandler{c.server}.ServeHTTP(w, w.req)
...
// 请求结束之后cancel掉context
w.cancelCtx()
}
// 处理连接时,处理会把连接交给serverHandler,还会起一个协程监控连接的状态
func (cr *connReader) startBackgroundRead() {
cr.lock()
defer cr.unlock()
...
cr.inRead = true
cr.conn.rwc.SetReadDeadline(time.Time{})
go cr.backgroundRead()
}
// 如果连接有问题,就会cancel掉
func (cr *connReader) backgroundRead() {
n, err := cr.conn.rwc.Read(cr.byteBuf[:])
cr.lock()
if n == 1 {
cr.hasByte = true
}
// 如果连接超时了,就会收到EOF的错误
if ne, ok := err.(net.Error); ok && cr.aborted && ne.Timeout() {
} else if err != nil {
// 出错时就会触发cancel,从而结束掉请求
cr.handleReadError(err)
// handleReadError方法内就是下面这两句
// cr.conn.cancelCtx()
// cr.closeNotify()
}
cr.aborted = false
cr.inRead = false
cr.unlock()
cr.cond.Broadcast()
}
// DefaultServeMux的ServeHTTP方法,对请求进行路由匹配,用的就是http.HandleFunc里的map
// 根据path找到对应的handler,执行
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
w.WriteHeader(StatusBadRequest)
return
}
// 获取注册的路由handler
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
}
// 路由handler的逻辑非常简单,就是直接根据path在map里匹配找到处理的handler
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
mux.mu.RLock()
defer mux.mu.RUnlock()
if mux.hosts {
h, pattern = mux.match(host + path)
}
if h == nil {
h, pattern = mux.match(path)
}
if h == nil {
h, pattern = NotFoundHandler(), ""
}
return
}
// 只是做简单的路由匹配
func (mux *ServeMux) match(path string) (h Handler, pattern string) {
v, ok := mux.m[path]
if ok {
return v.h, v.pattern
}
for _, e := range mux.es {
if strings.HasPrefix(path, e.pattern) {
return e.h, e.pattern
}
}
return nil, ""
}
|