- 需要go build cmd/traefik来进行编译,不能go build
每个entrypoint会listen and serve pkg/server/server_entrypoint_tcp.go
runCmd
--setupServer
NewTCPEntryPoints
NewTCPEntryPoint
会调用buildListener -> net.Listen 取得listener
createHTTPServer 两次,这里有点复杂,第一次注册h2c, 第二次注册http, 我们只看第二次
使用forwardedheaders.NewXForwarded来定制httpserve:
(x *XForwarded) ServeHTTP 会处理 x.rewrite,会改写XForwarded header 信任ip和 insecure, Xforwarded是个链表,后续继续处理:`x.next.ServeHTTP(w, r)` 妙
-- svr.Start
s.tcpEntryPoints.Start()
forwarder 会 (h *httpForwarder) Accept()
这个不调用listener的accept,而是借用了serve的壳。。。。conn := <-h.connChan
等待channel, 直到链接上,会有消息发过来
go serverEntryPoint.Start(ctx)
logger.Debugf("Start TCP Server")
conn, err := e.listener.Accept 这个是真正的accept
e.switcher.ServeTCP
(dlv) bt
0 0x0000000002002507 in github.com/containous/traefik/v2/pkg/server.(*Server).Start
at ./pkg/server/server.go:60
1 0x000000000200ceb5 in main.runCmd
at ./cmd/traefik/traefik.go:124
2 0x0000000002010c9c in main.main.func1
at ./cmd/traefik/traefik.go:54
3 0x0000000001f00a5c in github.com/containous/traefik/v2/pkg/cli.run
at ./pkg/cli/commands.go:133
4 0x0000000001f0079a in github.com/containous/traefik/v2/pkg/cli.execute
at ./pkg/cli/commands.go:57
5 0x000000000200c912 in github.com/containous/traefik/v2/pkg/cli.Execute
at ./pkg/cli/commands.go:51
6 0x000000000200c912 in main.main
at ./cmd/traefik/traefik.go:70
7 0x0000000000438ed2 in runtime.main
at /home/jinlei1/os/go/src/runtime/proc.go:203
8 0x0000000000469421 in runtime.goexit
at /home/jinlei1/os/go/src/runtime/asm_amd64.s:1373
(s *HandlerSwitcher) ServeTCP
(r *Router) ServeTCP(conn WriteCloser)
clientHelloServerName ---> 这里用了peek, 只拿出来看看,不影响reader,妙!
r.httpForwarder.ServeTCP --> 这里会给刚才那个channel 把conn给他
accept就执行完了,根据http框架,会执行 httpserve即:
(x *XForwarded) ServeHTTP
然后开始链式调用,妙!
forwardedheaders.(*XForwarded).ServeHTTP
accesslog.(*Handler).ServeHTTP
requestdecorator.(*RequestDecorator).ServeHTTP
accesslog.(*FieldHandler).ServeHTTP
accesslog.AddOriginFields
recovery.(*recovery).ServeHTTP
accesslog.(*FieldHandler).ServeHTTP
tracing.(*forwarderMiddleware).ServeHTTP
emptybackendhandler.(*emptyBackend).ServeHTTP
healthcheck.(*LbStatusUpdater).ServeHTTP
accesslog.(*FieldHandler).ServeHTTP
accesslog.AddServiceFields
pipelining.(*pipelining).ServeHTTP
service.buildProxy.func1
0 0x0000000001ff3f3a in github.com/containous/traefik/v2/pkg/server/service.buildProxy.func1
at ./pkg/server/service/proxy.go:38
1 0x0000000000c1f9b7 in net/http/httputil.(*ReverseProxy).ServeHTTP
at /home/jinlei1/os/go/src/net/http/httputil/reverseproxy.go:214
2 0x0000000001febcc7 in github.com/containous/traefik/v2/pkg/middlewares/pipelining.(*pipelining).ServeHTTP
at ./pkg/middlewares/pipelining/pipelining.go:36
3 0x0000000001f60724 in github.com/containous/traefik/v2/pkg/middlewares/accesslog.AddServiceFields
at ./pkg/middlewares/accesslog/field_middleware.go:47
4 0x0000000001f6054b in github.com/containous/traefik/v2/pkg/middlewares/accesslog.(*FieldHandler).ServeHTTP
at ./pkg/middlewares/accesslog/field_middleware.go:36
5 0x0000000001fe707d in github.com/vulcand/oxy/roundrobin.(*RoundRobin).ServeHTTP
at /home/jinlei1/ksyun/pkg/mod/github.com/vulcand/[email protected]/roundrobin/rr.go:147
6 0x0000000001feb75a in github.com/containous/traefik/v2/pkg/healthcheck.(*LbStatusUpdater).ServeHTTP
at <autogenerated>:1
7 0x0000000001feba68 in github.com/containous/traefik/v2/pkg/middlewares/emptybackendhandler.(*emptyBackend).ServeHTTP
at ./pkg/middlewares/emptybackendhandler/empty_backend_handler.go:31
8 0x0000000001f7e4d9 in github.com/containous/traefik/v2/pkg/middlewares/tracing.(*forwarderMiddleware).ServeHTTP
at ./pkg/middlewares/tracing/forwarder.go:38
9 0x0000000001f60584 in github.com/containous/traefik/v2/pkg/middlewares/accesslog.(*FieldHandler).ServeHTTP
at ./pkg/middlewares/accesslog/field_middleware.go:38
10 0x0000000000769cb2 in github.com/gorilla/mux.(*Router).ServeHTTP
at /home/jinlei1/ksyun/pkg/mod/github.com/containous/[email protected]/mux.go:133
11 0x0000000001fc40b4 in github.com/containous/traefik/v2/pkg/middlewares/recovery.(*recovery).ServeHTTP
at ./pkg/middlewares/recovery/recovery.go:33
12 0x0000000001f608f8 in github.com/containous/traefik/v2/pkg/middlewares/accesslog.AddOriginFields
at ./pkg/middlewares/accesslog/field_middleware.go:55
13 0x0000000001f6054b in github.com/containous/traefik/v2/pkg/middlewares/accesslog.(*FieldHandler).ServeHTTP
at ./pkg/middlewares/accesslog/field_middleware.go:36
14 0x00000000007432fd in net/http.Handler.ServeHTTP-fm
at /home/jinlei1/os/go/src/net/http/server.go:87
15 0x00000000008d6ddd in github.com/containous/traefik/v2/pkg/middlewares/requestdecorator.(*RequestDecorator).ServeHTTP
at ./pkg/middlewares/requestdecorator/request_decorator.go:47
16 0x00000000008d7373 in github.com/containous/traefik/v2/pkg/middlewares/requestdecorator.WrapHandler.func1.1
at ./pkg/middlewares/requestdecorator/request_decorator.go:84
17 0x0000000000714244 in net/http.HandlerFunc.ServeHTTP
at /home/jinlei1/os/go/src/net/http/server.go:2012
18 0x0000000001f623ee in github.com/containous/traefik/v2/pkg/middlewares/accesslog.(*Handler).ServeHTTP
at ./pkg/middlewares/accesslog/logger.go:210
19 0x0000000001f64eba in github.com/containous/traefik/v2/pkg/middlewares/accesslog.WrapHandler.func1.1
at ./pkg/middlewares/accesslog/logger.go:67
20 0x0000000000714244 in net/http.HandlerFunc.ServeHTTP
at /home/jinlei1/os/go/src/net/http/server.go:2012
21 0x0000000001f5fd30 in github.com/containous/traefik/v2/pkg/middlewares.(*HTTPHandlerSwitcher).ServeHTTP
at ./pkg/middlewares/handler_switcher.go:23
22 0x0000000001ffa21b in github.com/containous/traefik/v2/pkg/middlewares/forwardedheaders.(*XForwarded).ServeHTTP
at ./pkg/middlewares/forwardedheaders/forwarded_header.go:174
23 0x0000000001ffa7ea in golang.org/x/net/http2/h2c.h2cHandler.ServeHTTP
at /home/jinlei1/ksyun/pkg/mod/golang.org/x/[email protected]/http2/h2c/h2c.go:98
24 0x0000000001ffd18c in golang.org/x/net/http2/h2c.(*h2cHandler).ServeHTTP
at <autogenerated>:1
25 0x00000000007176d3 in net/http.serverHandler.ServeHTTP
at /home/jinlei1/os/go/src/net/http/server.go:2807
26 0x000000000071304c in net/http.(*conn).serve
at /home/jinlei1/os/go/src/net/http/server.go:1895
27 0x0000000000469421 in runtime.goexit
1 0x0000000000c1f9b7 in net/http/httputil.(*ReverseProxy).ServeHTTP
367 // Clone returns a deep copy of r with its context changed to ctx.¬
368 // The provided ctx must be non-nil.¬
369 //¬
370 // For an outgoing client request, the context controls the entire¬
371 // lifetime of a request and its response: obtaining a connection,¬
372 // sending the request, and reading the response headers and body.¬
- 373 func (r *Request) Clone(ctx context.Context) *Request {¬
| 374 ▸ if ctx == nil {¬
| 375 ▸ ▸ panic("nil context")¬
| 376 ▸ }¬
| 377 ▸ r2 := new(Request)¬
| 378 ▸ *r2 = *r¬
| 379 ▸ r2.ctx = ctx¬ -------------- 注意这里把之前的ctx 给新的req ctx, 也就是共享一个context,所以如果之前的cancel了,新的req也能收到cancel
buildProxy
Director: func(outReq *http.Request
257 ▸ res, err := transport.RoundTrip(outreq)¬ ---> (t *Transport) RoundTrip(req *Request) src/net/http/roundtrip.go:16
| 258 ▸ if err != nil {¬
| 259 ▸ ▸ p.getErrorHandler()(rw, outreq, err)¬
| 260 ▸ ▸ return¬
| 261 ▸ }¬
~/os/go/src/net/http/transport.go
| 2540 ▸ ▸ case <-ctxDoneChan:¬
| 2541 ▸ ▸ ▸ pc.t.cancelRequest(req.Request, req.Context().Err())¬
| 2542 ▸ ▸ ▸ cancelChan = nil¬
| 2543 ▸ ▸ ▸ ctxDoneChan = nil¬
curl http请求取消,触发golang http ctx取消的位置
go/src/net/http/server.go
---> Serve //启动http server
---> rw, err := l.Accept() //接收tcp连接
---> go c.serve(connCtx) //起协程处理连接
serve(ctx context.Context){
......
// HTTP/1.x from here on.
ctx, cancelCtx := context.WithCancel(ctx) //为ctx 设置CancelFunc
c.cancelCtx = cancelCtx //为tcp连接设置取消请求的ctx
......
for {
处理重定向逻辑
......
w.conn.r.startBackgroundRead() //实际读取数据
serverHandler{c.server}.ServeHTTP(w, w.req) //实际调用上层函数处理http数据
......
}
}
---> go cr.backgroundRead() //起go协程读数据
---> n, err := cr.conn.rwc.Read(cr.byteBuf[:]) //实际tcp连接读数据
---> cr.handleReadError(err) //处理tcp连接数据读取错误
---> cr.conn.cancelCtx() //客户断开tcp连接,比如终止curl,在此触发ctx取消