beego框架源码解析:启动和监听过程

6 篇文章 0 订阅
本文详细剖析了Beego框架的启动和监听过程,从`NewHttpServer`函数开始,逐步解析如何初始化全局变量`BeeApp`,并设置路由信息。接着,通过`Run`方法启动服务,`Serve`函数接收HTTP请求,并调用`Handle`处理请求。在处理过程中,`ControllerRegister`中的路由信息被用于响应HTTP请求,揭示了Beego框架内部路由分发的机制。
摘要由CSDN通过智能技术生成

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 真正处理请求,这里的 handler 根据第3步中的赋值,可推导到 step9
}

---------------------------------------------------
E:\workspace_go\pkg\mod\github.com\beego\beego\v2@v2.0.1\server\web
// Implement http.Handler interface.
func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) { ---step9: 又回到 beego 了 

	ctx := p.GetContext()

	ctx.Reset(rw, r)
	defer p.GiveBackContext(ctx)

	var preFilterParams map[string]string
	p.chainRoot.filter(ctx, p.getUrlPath(ctx), preFilterParams)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值