ghttp.Server增加事件回调特性,去掉Request ID生成器,采用性能更高的gtype包实现请求ID生成

This commit is contained in:
John
2018-04-09 17:55:46 +08:00
parent 0b877184a4
commit fdefc0f822
8 changed files with 80 additions and 121 deletions

View File

@ -19,10 +19,10 @@ import (
"path/filepath"
"gitee.com/johng/gf/g/util/gutil"
"gitee.com/johng/gf/g/net/grouter"
"gitee.com/johng/gf/g/util/gidgen"
"gitee.com/johng/gf/g/container/gmap"
"gitee.com/johng/gf/g/container/gqueue"
"gitee.com/johng/gf/g/container/glist"
"gitee.com/johng/gf/g/container/gtype"
)
const (
@ -41,7 +41,7 @@ type Server struct {
status int8 // 当前服务器状态(0未启动1运行中)
handlerMap HandlerMap // 所有注册的回调函数
methodsMap map[string]bool // 所有支持的HTTP Method(初始化时自动填充)
idgen *gidgen.Gen // 请求ID生成器
servedCount *gtype.Int // 已经服务的请求数(4-8字节不考虑溢出情况)
closeQueue *gqueue.Queue // 请求结束的关闭队列(存放的是需要异步关闭处理的*Request对象)
hooksMap *gmap.StringInterfaceMap // 钩子注册方法map键值为按照注册顺序生成的glist用于hook顺序调用
Router *grouter.Router // 路由管理对象
@ -77,7 +77,7 @@ func GetServer(names...string) (*Server) {
name : name,
handlerMap : make(HandlerMap),
methodsMap : make(map[string]bool),
idgen : gidgen.New(50000),
servedCount : gtype.NewInt(),
closeQueue : gqueue.New(),
hooksMap : gmap.NewStringInterfaceMap(),
Router : grouter.New(),
@ -492,6 +492,16 @@ func (s *Server)BindHookHandler(pattern string, hook string, handler HandlerFunc
return nil
}
// 通过map批量绑定回调函数
func (s *Server)BindHookHandlerByMap(pattern string, hookmap map[string]HandlerFunc) error {
for k, v := range hookmap {
if err := s.BindHookHandler(pattern, k, v); err != nil {
return err
}
}
return nil
}
//// 绑定URI服务注册的Init回调函数回调时按照注册顺序执行
//// Init回调调用时机为请求进入控制器之前初始化Request对象之后
//func (s *Server)BindHookHandlerInit(pattern string, handler HandlerFunc) error {

View File

@ -12,10 +12,14 @@ func (s *Server) startCloseQueueLoop() {
for {
if v := s.closeQueue.PopFront(); v != nil {
r := v.(*Request)
s.callHookHandler(r, "BeforeRequestClose")
// 关闭当前会话的Cookie
r.Cookie.Close()
// 更新Sssion会话超时时间
// 更新Session会话超时时间
r.Session.UpdateExpire()
s.callHookHandler(r, "AfterRequestClose")
}
}
}()

View File

@ -119,6 +119,16 @@ func (d *Domain)BindHookHandler(pattern string, hook string, handler HandlerFunc
return nil
}
// 通过map批量绑定回调函数
func (d *Domain)BindHookHandlerByMap(pattern string, hookmap map[string]HandlerFunc) error {
for domain, _ := range d.m {
if err := d.s.BindHookHandlerByMap(pattern + "@" + domain, hookmap); err != nil {
return err
}
}
return nil
}
//// 绑定URI服务注册的Init回调函数回调时按照注册顺序执行
//// Init回调调用时机为请求进入控制器之前初始化Request对象之后
//func (d *Domain)BindHookHandlerInit(pattern string, handler HandlerFunc) error {

View File

@ -38,7 +38,7 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
}
// 构造请求参数对象
request := &Request{
Id : s.idgen.Int(),
Id : s.servedCount.Add(1),
Server : s,
Request : *r,
Response : &Response {
@ -89,7 +89,9 @@ func (s *Server)callHandler(h *HandlerItem, r *Request) {
s.callHookHandler(r, "AfterCookieOutput")
// 输出缓冲区
s.callHookHandler(r, "BeforeBufferOutput")
r.Response.OutputBuffer()
s.callHookHandler(r, "AfterBufferOutput")
// 将Request对象指针丢到队列中异步处理
s.closeQueue.PushBack(r)

18
g/os/gtime/time_test.go Normal file
View File

@ -0,0 +1,18 @@
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
package gtime_test
import (
"testing"
"gitee.com/johng/gf/g/os/gtime"
)
func BenchmarkNanosecond(b *testing.B) {
for i := 0; i < b.N; i++ {
gtime.Nanosecond()
}
}

View File

@ -1,68 +0,0 @@
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
// ID生成器.
// 内部采用了通道+缓冲池来实现高效的ID递增生成
// 非常适合高并发下使用
package gidgen
import "math"
// ID生成器管理对象
type Gen struct {
ch chan uint
closeQueue chan struct{}
}
// 创建一个ID生成器并给定ID池大小
func New (bufsize int) *Gen {
g := &Gen {
ch : make(chan uint, bufsize),
closeQueue : make(chan struct{}),
}
go g.startLoop()
return g
}
// 关闭生成器
func (g *Gen) Close() {
close(g.closeQueue)
close(g.ch)
}
// 内部循环当最大值使用完之后重新从1开始获取
func (g *Gen) startLoop() {
for {
select {
case <- g.closeQueue:
return
default:
// 当ch达到缓冲池大小会阻塞只要有线程取出值再立即填充
for i := uint(1); i < uint(math.MaxUint64); i++ {
g.ch <- i
}
}
}
}
// 从池中获取一个ID返回(uint)
func (g *Gen) Uint() uint {
return <- g.ch
}
// 从池中获取一个ID返回(int)
func (g *Gen) Int() int {
i := <- g.ch
if i != 0 {
i = i & 0x7FFFFFFFFFFFFFFF
// 可能是int与uint之间的临界点
if i == 0 {
return g.Int()
}
}
return int(i)
}

29
geg/net/ghttp/events.go Normal file
View File

@ -0,0 +1,29 @@
package main
import (
"gitee.com/johng/gf/g/net/ghttp"
"fmt"
)
func main() {
pattern := "/"
ghttp.GetServer().BindHookHandlerByMap(pattern, map[string]ghttp.HandlerFunc{
"BeforeServe" : func(r *ghttp.Request){ fmt.Println("BeforeServe") },
"AfterServe" : func(r *ghttp.Request){ fmt.Println("AfterServe") },
"BeforeRouterPatch" : func(r *ghttp.Request){ fmt.Println("BeforeRouterPatch") },
"AfterRouterPatch" : func(r *ghttp.Request){ fmt.Println("AfterRouterPatch") },
"BeforeCookieOutput" : func(r *ghttp.Request){ fmt.Println("BeforeCookieOutput") },
"AfterCookieOutput" : func(r *ghttp.Request){ fmt.Println("AfterCookieOutput") },
"BeforeBufferOutput" : func(r *ghttp.Request){ fmt.Println("BeforeBufferOutput") },
"AfterBufferOutput" : func(r *ghttp.Request){ fmt.Println("AfterBufferOutput") },
"BeforeRequestClose" : func(r *ghttp.Request){ fmt.Println("BeforeRequestClose") },
"AfterRequestClose" : func(r *ghttp.Request){ fmt.Println("AfterRequestClose") },
})
ghttp.GetServer().BindHandler(pattern, func(r *ghttp.Request) {
r.Response.WriteString("Hello World!")
})
ghttp.GetServer().SetPort(10000)
ghttp.GetServer().Run()
select { }
}

View File

@ -1,56 +1,10 @@
package main
import (
"gitee.com/johng/gf/g/database/gdb"
"fmt"
"math"
)
type Model struct {
TableName string
}
var Db *gdb.Db
func init() {
gdb.AddDefaultConfigNode(gdb.ConfigNode {
Host : "127.0.0.1",
Port : "3306",
User : "root",
Pass : "123456",
Name : "test",
Type : "mysql",
Role : "master",
Charset : "utf8",
})
var err error
Db, err = gdb.Instance()
checkErr(err)
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
type UserModel struct {
Model
}
func (u *UserModel) Get() (user gdb.Map){
user, _ = Db.Table("user").Fields("uid, nickname, email").Where("uid = ?", 15).One()
return
}
func (u *UserModel) Insert(data gdb.Map) (id int64) {
ret, _ := Db.Table("user").Data(data).Insert()
id, _ = ret.LastInsertId()
return
}
func main() {
u := &UserModel{}
user := u.Get()
fmt.Println(user)
u.Insert(gdb.Map{"uid": 100, "name": "jack"})
fmt.Println(math.MaxInt64)
}