beego框架源码解析:启动和监听过程,路由信息是怎么给到 webserver的
E:\workspace_go\pkg\mod\github.com\beego\beego\v2@v2.0.1\server\web\server.go
func init() {
// create beego application
BeeApp = NewHttpSever() // ----------------------step1 初始化全局变量 BeeApp
}
// HttpServer defines beego application with a new PatternServeMux.
type HttpServer struct {
Handlers *ControllerRegister
Server *http.Server
Cfg *Config
}
// NewHttpSever returns a new beego application.
// this method will use the BConfig as the configure to create HttpServer
// Be careful that when you update BConfig, the server's Cfg will be updated too
func NewHttpSever() *HttpServer {
return NewHttpServerWithCfg(BConfig)
}
// NewHttpServerWithCfg will create an sever with specific cfg
func NewHttpServerWithCfg(cfg *Config) *HttpServer {
cr := NewControllerRegisterWithCfg(cfg)
app := &HttpServer{
Handlers: cr, // ----------------------step2 把所有的路由信息,赋值给 BeeApp.Handlers
Server: &http.Server{},
Cfg: cfg,
}
return app
}
// Run beego application.
func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
......
app.Server.Handler = app.Handlers // ----------------------step3 把 BeeApp.Handlers 赋值给 BeeApp.Server.Handler
......
if app.Cfg.Listen.EnableHTTP {
go func() {
app.Server.Addr = addr
logs.Info("http server Running on http://%s", app.Server.Addr)
if app.Cfg.Listen.ListenTCP4 {
ln, err := net.Listen("tcp4", app.Server.Addr)
if err != nil {
logs.Critical("ListenAndServe: ", err)
time.Sleep(100 * time.Microsecond)
endRunning <- true
return
}
if err = app.Server.Serve(ln); err != nil { // ----------------------step4 启动服务
logs.Critical("ListenAndServe: ", err)
time.Sleep(100 * time.Microsecond)
endRunning <- true
return
}
} else {
if err := app.Server.ListenAndServe(); err != nil {
logs.Critical("ListenAndServe: ", err)
time.Sleep(100 * time.Microsecond)
endRunning <- true
}
}
}()
}
<-endRunning
}
----------------------------------------
C:\Program Files\Go\src\net\http\server.go
// Serve accepts incoming connections on the Listener l, creating a
// new service goroutine for each. The service goroutines read requests and
// then call srv.Handler to reply to them.
//
// HTTP/2 support is only enabled if the Listener returns *tls.Conn
// connections and they were configured with "h2" in the TLS
// Config.NextProtos.
//
// Serve always returns a non-nil error and closes l.
// After Shutdown or Close, the returned error is ErrServerClosed.
func (srv *Server) Serve(l net.Listener) error {
if fn := testHookServerServe; fn != nil {
fn(srv, l) // call hook with unwrapped listener
}
origListener := l
l = &onceCloseListener{Listener: l}
defer l.Close()
if err := srv.setupHTTP2_Serve(); err != nil {
return err
}
if !srv.trackListener(&l, true) {
return ErrServerClosed
}
defer srv.trackListener(&l, false)
baseCtx := context.Background()
if srv.BaseContext != nil {
baseCtx = srv.BaseContext(origListener)
if baseCtx == nil {
panic("BaseContext returned a nil context")
}
}
var tempDelay time.Duration // how long to sleep on accept failure
ctx := context.WithValue(baseCtx, ServerContextKey, srv)
for {
rw, err := l.Accept() // ----------------------step5 接受 HTTP 请求
if err != nil {
select {
case <-srv.getDoneChan():
return ErrServerClosed
default:
}
if ne, ok := err.(net.Error); ok && ne.Temporary() {
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay)
time.Sleep(tempDelay)
continue
}
return err
}
connCtx := ctx
if cc := srv.ConnContext; cc != nil {
connCtx = cc(connCtx, rw)
if connCtx == nil {
panic("ConnContext returned nil")
}
}
tempDelay = 0
c := srv.newConn(rw) // ----------------------------step6.1 创建新的链接处理请求
c.setState(c.rwc, StateNew, runHooks) // before Serve can return
go c.serve(connCtx) // ----------------------------step7.1 处理新的 HTTP 请求
}
}
// Create new connection from rwc.
func (srv *Server) newConn(rwc net.Conn) *conn {
c := &conn{
server: srv, // ----------------------------step6.2 该 srv 就是 BeeApp.Server
rwc: rwc,
}
if debugServerConnections {
c.rwc = newLoggingConn("server", c.rwc)
}
return c
}
// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
......
serverHandler{c.server}.ServeHTTP(w, w.req) // ----------------------------step7.2 处理新的 HTTP 请求
......
}
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
if handler == nil {
handler = DefaultServeMux
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}
handler.ServeHTTP(rw, req) //------------------------------step8 真正处理请求
}
|