package f5 import ( "net/http" "sync" "sync/atomic" "fmt" "q5" ) type HttpServer struct { totalRequestTimes int64 okTimes int64 pageNotFoundTimes int64 maxHandleTime int64 startTimes int64 handlersMutex sync.RWMutex handlers map[string]HandlerFunc restHandlersMutex sync.RWMutex restHandlers map[string]*q5.ListHead } func (this *HttpServer) Init(serviceName string, logOutputTime int32) *HttpServer { this.handlers = make(map[string]HandlerFunc) this.restHandlers = make(map[string]*q5.ListHead) this.RegisterRestHandle("/webapp/index.php", this.dispatchRequest) this.RegisterHandle("Ops", "selfChecking", func (c *Context) { c.Response(`{"errcode":0, "errmsg":"", "healthy":1, "max_rundelay":10}`) }) GetSysLog().Info("HttpServer.Init") if logOutputTime > 0 { GetTimer().SetInterval( logOutputTime, func (ev int32, params *q5.Args) { if ev == q5.TIMER_EXEC_EVENT { GetSysLog().Info("%s maxHandleTime:%d totalRequestTimes:%d okTimes:%d pageNotFoundTimes:%d", serviceName, this.maxHandleTime, this.totalRequestTimes, this.okTimes, this.pageNotFoundTimes) this.maxHandleTime = 0 this.okTimes = 0 this.pageNotFoundTimes = 0 } }) } return this } func (this *HttpServer) UnInit() { GetSysLog().Info("HttpServer.UnInit") } func (this *HttpServer) Start(listen_port int32) { atomic.AddInt64(&this.totalRequestTimes, 1) GetSysLog().Info("HttpServer.Start listen_port:%d", listen_port) go http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", listen_port), nil) } func (this *HttpServer) dispatchRequest(c *Context) { atomic.AddInt64(&this.totalRequestTimes, 1) handleName := c.Request("c") + "$" + c.Request("a") handle := this.getHandle(handleName) if handle != nil { beginTick := q5.GetTickCount() defer func() { endTick := q5.GetTickCount() if oldVal := atomic.LoadInt64(&this.maxHandleTime); beginTick - endTick > oldVal { atomic.CompareAndSwapInt64(&this.maxHandleTime, oldVal, endTick - beginTick) } atomic.AddInt64(&this.okTimes, 1) if err := recover(); err != nil { GetSysLog().Error("handle name:%s error:%s", handleName, err) c.Response(`{"errcode":500, "errmsg":"server internal error"}`) } }() handle(c) } else { c.Response(`{"errcode":404, "errmsg":"interface not found"}`) atomic.AddInt64(&this.pageNotFoundTimes, 1) } } func (this *HttpServer) getHandle(handleName string) HandlerFunc { this.handlersMutex.Lock() defer this.handlersMutex.Unlock() if handle, ok := this.handlers[handleName]; ok { return handle } else { return nil } } func (this *HttpServer) RegisterHandle(c string, a string, handle HandlerFunc) { this.handlersMutex.Lock() defer this.handlersMutex.Unlock() handleName := c + "$" + a this.handlers[handleName] = handle } func (this *HttpServer) RegisterRestHandle(pattern string, handle HandlerFunc) { if this.totalRequestTimes > 0 { panic("") } this.restHandlersMutex.Lock() defer this.restHandlersMutex.Unlock() p := new(middleware) p.entry.Init(p) p.handlerFunc = handle if l, ok := this.restHandlers[pattern]; ok { l.AddTail(&p.entry) } else { l := q5.NewListHead() l.AddTail(&p.entry) this.restHandlers[pattern] = l http.HandleFunc(pattern, func (w http.ResponseWriter, r *http.Request) { c := new(Context) c.s = this c.w = &w c.r = r c.l = l c.do() }) } }