Commit 58e37bfe35c35abf16c41fe07802ba09c33b0b1a

Authored by zhangqijia
1 parent 29b6d86f

add sync.Pool to conn, agent

cmd/gameserver/agent.go
@@ -8,6 +8,7 @@ import ( @@ -8,6 +8,7 @@ import (
8 "pro2d/common/logger" 8 "pro2d/common/logger"
9 "pro2d/models" 9 "pro2d/models"
10 "pro2d/utils" 10 "pro2d/utils"
  11 + "sync"
11 "sync/atomic" 12 "sync/atomic"
12 ) 13 )
13 14
@@ -16,25 +17,21 @@ type Agent struct { @@ -16,25 +17,21 @@ type Agent struct {
16 Server components.IServer 17 Server components.IServer
17 18
18 Role *models.RoleModel 19 Role *models.RoleModel
19 -  
20 -  
21 - Quit chan *Agent  
22 -  
23 nextCheckTime int64 //下一次检查的时间 20 nextCheckTime int64 //下一次检查的时间
24 lastHeartCheckTime int64 21 lastHeartCheckTime int64
25 heartTimeoutCount int //超时次数 22 heartTimeoutCount int //超时次数
26 } 23 }
27 24
28 -func NewAgent(s components.IServer) *Agent {  
29 - return &Agent{  
30 - Server: s, 25 +var agentPool = sync.Pool{New: func() interface{} { return new(Agent)}}
31 26
32 - Quit: make(chan *Agent), 27 +func NewAgent(s components.IServer) *Agent {
  28 + a := agentPool.Get().(*Agent)
  29 + a.Server = s
33 30
34 - nextCheckTime: 0,  
35 - lastHeartCheckTime: utils.Timex(),  
36 - heartTimeoutCount: 0,  
37 - } 31 + a.nextCheckTime = 0
  32 + a.lastHeartCheckTime = utils.Timex()
  33 + a.heartTimeoutCount= 0
  34 + return a
38 } 35 }
39 36
40 func (c *Agent) OnConnection(conn components.IConnection) { 37 func (c *Agent) OnConnection(conn components.IConnection) {
@@ -45,16 +42,19 @@ func (c *Agent) OnMessage(msg components.IMessage) { @@ -45,16 +42,19 @@ func (c *Agent) OnMessage(msg components.IMessage) {
45 atomic.StoreInt64(&c.lastHeartCheckTime, utils.Timex()) 42 atomic.StoreInt64(&c.lastHeartCheckTime, utils.Timex())
46 md := c.Server.GetAction(msg.GetHeader().GetMsgID()) 43 md := c.Server.GetAction(msg.GetHeader().GetMsgID())
47 if md == nil { 44 if md == nil {
48 - logger.Debug("cmd: %d, md is nil", msg.GetHeader().GetMsgID()) 45 + logger.Debug("cmd: %d, handler is nil", msg.GetHeader().GetMsgID())
49 return 46 return
50 } 47 }
51 -  
52 - logger.Debug("protocode handler: %d", msg.GetHeader().GetMsgID())  
53 - //fmt.Printf("errCode: %d, protomsg:%v\n", errCode, protomsg) 48 + logger.Debug("protocolID: %d", msg.GetHeader().GetMsgID())
  49 + //fmt.Printf("errCode: %d, protoMsg:%v\n", errCode, protoMsg)
54 50
55 f := md.(func (msg components.IMessage) (int32, interface{})) 51 f := md.(func (msg components.IMessage) (int32, interface{}))
56 - errCode, protomsg := f(msg)  
57 - rsp, err := proto.Marshal(protomsg.(proto.Message)) 52 + errCode, protoMsg := f(msg)
  53 + if protoMsg == nil {
  54 + return
  55 + }
  56 +
  57 + rsp, err := proto.Marshal(protoMsg.(proto.Message))
58 if err != nil { 58 if err != nil {
59 conn := msg.GetSession() 59 conn := msg.GetSession()
60 if conn != nil { 60 if conn != nil {
@@ -65,9 +65,9 @@ func (c *Agent) OnMessage(msg components.IMessage) { @@ -65,9 +65,9 @@ func (c *Agent) OnMessage(msg components.IMessage) {
65 conn := msg.GetSession() 65 conn := msg.GetSession()
66 if conn != nil { 66 if conn != nil {
67 conn.Send(errCode, msg.GetHeader().GetMsgID(), rsp) 67 conn.Send(errCode, msg.GetHeader().GetMsgID(), rsp)
  68 + return
68 } 69 }
69 - return  
70 - logger.Error("protocode not handler: %d", msg.GetHeader().GetMsgID()) 70 + logger.Error("protocol not handler: %d", msg.GetHeader().GetMsgID())
71 } 71 }
72 72
73 func (c *Agent) OnTimer() { 73 func (c *Agent) OnTimer() {
@@ -91,6 +91,8 @@ func (c *Agent) OnClose() { @@ -91,6 +91,8 @@ func (c *Agent) OnClose() {
91 } 91 }
92 92
93 func (c *Agent) Close() { 93 func (c *Agent) Close() {
  94 + agentPool.Put(c)
  95 +
94 if c.Role == nil { 96 if c.Role == nil {
95 return 97 return
96 } 98 }
@@ -100,7 +102,7 @@ func (c *Agent) Close() { @@ -100,7 +102,7 @@ func (c *Agent) Close() {
100 102
101 func (c *Agent) checkHeartBeat(now int64) { 103 func (c *Agent) checkHeartBeat(now int64) {
102 lastHeartCheckTime := atomic.LoadInt64(&c.lastHeartCheckTime) 104 lastHeartCheckTime := atomic.LoadInt64(&c.lastHeartCheckTime)
103 - logger.Debug("checkHeartBeat ID: %d, last: %d, now: %d", c.GetID(), lastHeartCheckTime, now) 105 + //logger.Debug("checkHeartBeat ID: %d, last: %d, now: %d", c.GetID(), lastHeartCheckTime, now)
104 if math.Abs(float64(lastHeartCheckTime - now)) > common.HeartTimerInterval { 106 if math.Abs(float64(lastHeartCheckTime - now)) > common.HeartTimerInterval {
105 c.heartTimeoutCount++ 107 c.heartTimeoutCount++
106 if c.heartTimeoutCount >= common.HeartTimeoutCountMax { 108 if c.heartTimeoutCount >= common.HeartTimeoutCountMax {
cmd/gameserver/main.go
@@ -20,7 +20,7 @@ func main() { @@ -20,7 +20,7 @@ func main() {
20 20
21 s,err1 := NewGameServer(common.GlobalConf.GameConf) 21 s,err1 := NewGameServer(common.GlobalConf.GameConf)
22 if err1 != nil { 22 if err1 != nil {
23 - fmt.Errorf(err1.Error()) 23 + logger.Error(err1)
24 return 24 return
25 } 25 }
26 go func() { 26 go func() {
cmd/gameserver/plugin/plugin.go
@@ -15,7 +15,7 @@ func init() { @@ -15,7 +15,7 @@ func init() {
15 func GetActionMap() map[interface{}]interface{} { 15 func GetActionMap() map[interface{}]interface{} {
16 logger.Debug("init protocode...") 16 logger.Debug("init protocode...")
17 am := make(map[interface{}]interface{}) 17 am := make(map[interface{}]interface{})
18 - am[uint32(pb.ProtoCode_LoginReq)] = "LoginRpc" 18 + am[uint32(pb.ProtoCode_LoginReq)] = LoginRpc
19 19
20 return am 20 return am
21 } 21 }
common/components/conn.go
@@ -6,6 +6,7 @@ import ( @@ -6,6 +6,7 @@ import (
6 "net" 6 "net"
7 "pro2d/common" 7 "pro2d/common"
8 "pro2d/common/logger" 8 "pro2d/common/logger"
  9 + "sync"
9 "sync/atomic" 10 "sync/atomic"
10 "time" 11 "time"
11 ) 12 )
@@ -14,7 +15,7 @@ type Connection struct { @@ -14,7 +15,7 @@ type Connection struct {
14 IConnection 15 IConnection
15 net.Conn 16 net.Conn
16 Server IServer 17 Server IServer
17 - Id int 18 + Id uint32
18 19
19 scanner *bufio.Scanner 20 scanner *bufio.Scanner
20 writer *bufio.Writer 21 writer *bufio.Writer
@@ -31,30 +32,49 @@ type Connection struct { @@ -31,30 +32,49 @@ type Connection struct {
31 Status uint32 32 Status uint32
32 } 33 }
33 34
  35 +var connectionPool = &sync.Pool{
  36 + New: func() interface{} { return new(Connection)},
  37 +}
  38 +
34 func NewConn(id int, conn net.Conn, s IServer) *Connection { 39 func NewConn(id int, conn net.Conn, s IServer) *Connection {
35 - c := &Connection{  
36 - Id: id,  
37 - Conn: conn,  
38 - Server: s,  
39 -  
40 - scanner: bufio.NewScanner(conn),  
41 - writer: bufio.NewWriter(conn),  
42 - WBuffer: make(chan []byte, common.MaxMsgChan),  
43 - Quit: make(chan *Connection),  
44 - readFunc: make(chan func(), 10),  
45 - timerFunc: make(chan func(), 10),  
46 -  
47 - Status: 0, 40 + c := connectionPool.Get().(*Connection)
  41 + closed := atomic.LoadUint32(&c.Status)
  42 + if closed != 0 {
  43 + connectionPool.Put(c)
  44 + c = new(Connection)
48 } 45 }
49 - c.connectionCallback = c.defaultConnectionCallback  
50 - c.messageCallback = c.defaultMessageCallback  
51 - c.closeCallback = c.defaultCloseCallback  
52 - c.timerCallback = c.defaultTimerCallback 46 +
  47 + atomic.StoreUint32(&c.Id, uint32(id))
  48 + c.Conn = conn
  49 + c.Server = s
  50 +
  51 + c.scanner = bufio.NewScanner(conn)
  52 + c.writer = bufio.NewWriter(conn)
  53 +
  54 + c.reset()
  55 +
53 return c 56 return c
54 } 57 }
55 58
56 -func (c *Connection) GetID() int {  
57 - return c.Id 59 +func (c *Connection) reset() {
  60 + c.WBuffer = make(chan []byte, common.MaxMsgChan)
  61 + c.Quit = make(chan *Connection)
  62 +
  63 + if c.readFunc == nil {
  64 + c.readFunc = make(chan func(), 10)
  65 + }
  66 + if c.timerFunc == nil {
  67 + c.timerFunc = make(chan func(), 10)
  68 + }
  69 +
  70 + //c.connectionCallback = c.defaultConnectionCallback
  71 + //c.messageCallback = c.defaultMessageCallback
  72 + //c.closeCallback = c.defaultCloseCallback
  73 + //c.timerCallback = c.defaultTimerCallback
  74 +}
  75 +
  76 +func (c *Connection) GetID() uint32 {
  77 + return atomic.LoadUint32(&c.Id)
58 } 78 }
59 79
60 func (c *Connection) SetConnectionCallback(cb ConnectionCallback) { 80 func (c *Connection) SetConnectionCallback(cb ConnectionCallback) {
@@ -78,12 +98,14 @@ func (c *Connection) Start() { @@ -78,12 +98,14 @@ func (c *Connection) Start() {
78 go c.read() 98 go c.read()
79 go c.listen() 99 go c.listen()
80 100
81 - c.Status = 1 101 + atomic.StoreUint32(&c.Status, 1)
82 c.connectionCallback(c) 102 c.connectionCallback(c)
83 c.handleTimeOut() 103 c.handleTimeOut()
84 } 104 }
85 105
86 func (c *Connection) Stop() { 106 func (c *Connection) Stop() {
  107 + if atomic.LoadUint32(&c.Status) == 0 { return }
  108 +
87 sendTimeout := time.NewTimer(5 * time.Millisecond) 109 sendTimeout := time.NewTimer(5 * time.Millisecond)
88 defer sendTimeout.Stop() 110 defer sendTimeout.Stop()
89 // 发送超时 111 // 发送超时
@@ -125,7 +147,10 @@ func (c *Connection) defaultTimerCallback(conn IConnection) { @@ -125,7 +147,10 @@ func (c *Connection) defaultTimerCallback(conn IConnection) {
125 } 147 }
126 148
127 func (c *Connection) write() { 149 func (c *Connection) write() {
128 - defer c.quitting() 150 + defer func() {
  151 + logger.Debug("write close")
  152 + c.Stop()
  153 + }()
129 154
130 for msg := range c.WBuffer { 155 for msg := range c.WBuffer {
131 n, err := c.writer.Write(msg) 156 n, err := c.writer.Write(msg)
@@ -141,7 +166,11 @@ func (c *Connection) write() { @@ -141,7 +166,11 @@ func (c *Connection) write() {
141 } 166 }
142 167
143 func (c *Connection) read() { 168 func (c *Connection) read() {
144 - defer c.quitting() 169 + defer func() {
  170 + logger.Debug("read close")
  171 + c.Stop()
  172 + }()
  173 +
145 c.scanner.Split(c.Server.GetSplitter().ParseMsg) 174 c.scanner.Split(c.Server.GetSplitter().ParseMsg)
146 175
147 for c.scanner.Scan() { 176 for c.scanner.Scan() {
@@ -164,7 +193,10 @@ func (c *Connection) read() { @@ -164,7 +193,10 @@ func (c *Connection) read() {
164 193
165 //此设计目的是为了让网络数据与定时器处理都在一条协程里处理。不想加锁。。。 194 //此设计目的是为了让网络数据与定时器处理都在一条协程里处理。不想加锁。。。
166 func (c *Connection) listen() { 195 func (c *Connection) listen() {
167 - defer c.quitting() 196 + defer func() {
  197 + logger.Debug("listen close")
  198 + c.quitting()
  199 + }()
168 200
169 for { 201 for {
170 select { 202 select {
@@ -179,6 +211,8 @@ func (c *Connection) listen() { @@ -179,6 +211,8 @@ func (c *Connection) listen() {
179 } 211 }
180 212
181 func (c *Connection) handleTimeOut() { 213 func (c *Connection) handleTimeOut() {
  214 + if atomic.LoadUint32(&c.Status) == 0 { return }
  215 +
182 c.timerFunc <- func() { 216 c.timerFunc <- func() {
183 c.timerCallback(c) 217 c.timerCallback(c)
184 } 218 }
@@ -186,16 +220,16 @@ func (c *Connection) handleTimeOut() { @@ -186,16 +220,16 @@ func (c *Connection) handleTimeOut() {
186 } 220 }
187 221
188 func (c *Connection) quitting() { 222 func (c *Connection) quitting() {
189 - closed := atomic.LoadUint32(&c.Status)  
190 - if closed == 0 {  
191 - return  
192 - } 223 + if atomic.LoadUint32(&c.Status) == 0 { return }
193 atomic.StoreUint32(&c.Status, 0) 224 atomic.StoreUint32(&c.Status, 0)
194 225
195 logger.Debug("ID: %d close", c.Id) 226 logger.Debug("ID: %d close", c.Id)
196 close(c.WBuffer) 227 close(c.WBuffer)
197 close(c.Quit) 228 close(c.Quit)
198 - close(c.readFunc) 229 +
199 c.Conn.Close() 230 c.Conn.Close()
200 c.closeCallback(c) 231 c.closeCallback(c)
  232 +
  233 + //放回到对象池
  234 + connectionPool.Put(c)
201 } 235 }
common/components/connmanage.go
@@ -4,29 +4,29 @@ import &quot;sync&quot; @@ -4,29 +4,29 @@ import &quot;sync&quot;
4 4
5 type ConnManage struct { 5 type ConnManage struct {
6 mu sync.RWMutex 6 mu sync.RWMutex
7 - conns map[int]IConnection 7 + conns map[uint32]IConnection
8 } 8 }
9 9
10 func NewConnManage() *ConnManage { 10 func NewConnManage() *ConnManage {
11 return &ConnManage{ 11 return &ConnManage{
12 mu: sync.RWMutex{}, 12 mu: sync.RWMutex{},
13 - conns: make(map[int]IConnection), 13 + conns: make(map[uint32]IConnection),
14 } 14 }
15 } 15 }
16 16
17 -func (c *ConnManage) AddConn(id int, connection IConnection) { 17 +func (c *ConnManage) AddConn(id uint32, connection IConnection) {
18 c.mu.Lock() 18 c.mu.Lock()
19 defer c.mu.Unlock() 19 defer c.mu.Unlock()
20 c.conns[id] = connection 20 c.conns[id] = connection
21 } 21 }
22 22
23 -func (c *ConnManage) GetConn(id int) IConnection { 23 +func (c *ConnManage) GetConn(id uint32) IConnection {
24 c.mu.RLock() 24 c.mu.RLock()
25 defer c.mu.RUnlock() 25 defer c.mu.RUnlock()
26 return c.conns[id] 26 return c.conns[id]
27 } 27 }
28 28
29 -func (c *ConnManage) DelConn(id int) IConnection { 29 +func (c *ConnManage) DelConn(id uint32) IConnection {
30 c.mu.Lock() 30 c.mu.Lock()
31 defer c.mu.Unlock() 31 defer c.mu.Unlock()
32 conn := c.conns[id] 32 conn := c.conns[id]
@@ -35,14 +35,12 @@ func (c *ConnManage) DelConn(id int) IConnection { @@ -35,14 +35,12 @@ func (c *ConnManage) DelConn(id int) IConnection {
35 } 35 }
36 36
37 func (c *ConnManage) Range(f func(key interface{}, value interface{}) bool) { 37 func (c *ConnManage) Range(f func(key interface{}, value interface{}) bool) {
  38 + c.mu.Lock()
  39 + defer c.mu.Unlock()
38 for k, v := range c.conns { 40 for k, v := range c.conns {
39 - c.mu.Lock()  
40 if ok := f(k, v); !ok { 41 if ok := f(k, v); !ok {
41 - c.mu.Unlock()  
42 return 42 return
43 } 43 }
44 - c.mu.Unlock()  
45 -  
46 } 44 }
47 } 45 }
48 46
common/components/icompontents.go
@@ -36,7 +36,7 @@ type ( @@ -36,7 +36,7 @@ type (
36 TimerCallback func(IConnection) 36 TimerCallback func(IConnection)
37 //链接 37 //链接
38 IConnection interface { 38 IConnection interface {
39 - GetID() int 39 + GetID() uint32
40 Start() 40 Start()
41 Stop() 41 Stop()
42 Send(code int32, cmd uint32, b []byte) error 42 Send(code int32, cmd uint32, b []byte) error
@@ -48,9 +48,9 @@ type ( @@ -48,9 +48,9 @@ type (
48 } 48 }
49 //connManage 49 //connManage
50 IConnManage interface { 50 IConnManage interface {
51 - AddConn(id int, connection IConnection)  
52 - GetConn(id int) IConnection  
53 - DelConn(id int) IConnection 51 + AddConn(id uint32, connection IConnection)
  52 + GetConn(id uint32) IConnection
  53 + DelConn(id uint32) IConnection
54 Range(f func(key interface{}, value interface{}) bool) 54 Range(f func(key interface{}, value interface{}) bool)
55 StopAllConns() 55 StopAllConns()
56 } 56 }
common/components/server.go
@@ -137,7 +137,7 @@ func (s *Server) Start() error { @@ -137,7 +137,7 @@ func (s *Server) Start() error {
137 137
138 func (s *Server) Stop() { 138 func (s *Server) Stop() {
139 StopTimer() 139 StopTimer()
140 - 140 + s.connManage.StopAllConns()
141 } 141 }
142 142
143 func (s *Server) newConnection(conn IConnection) { 143 func (s *Server) newConnection(conn IConnection) {
@@ -146,7 +146,7 @@ func (s *Server) newConnection(conn IConnection) { @@ -146,7 +146,7 @@ func (s *Server) newConnection(conn IConnection) {
146 conn.SetMessageCallback(s.messageCallback) 146 conn.SetMessageCallback(s.messageCallback)
147 conn.SetTimerCallback(s.timerCallback) 147 conn.SetTimerCallback(s.timerCallback)
148 148
149 - go conn.Start() 149 + conn.Start()
150 } 150 }
151 151
152 func (s *Server) removeConnection(conn IConnection) { 152 func (s *Server) removeConnection(conn IConnection) {
common/components/timerwheel.go
@@ -2,7 +2,6 @@ package components @@ -2,7 +2,6 @@ package components
2 2
3 import ( 3 import (
4 "container/list" 4 "container/list"
5 - "pro2d/common"  
6 "sync" 5 "sync"
7 "sync/atomic" 6 "sync/atomic"
8 "time" 7 "time"
@@ -16,6 +15,10 @@ const ( @@ -16,6 +15,10 @@ const (
16 TimeLevel = 1 << TimeLevelShift 15 TimeLevel = 1 << TimeLevelShift
17 TimeNearMask = TimeNear - 1 16 TimeNearMask = TimeNear - 1
18 TimeLevelMask = TimeLevel - 1 17 TimeLevelMask = TimeLevel - 1
  18 +
  19 + //协程池 大小
  20 + WorkerPoolSize = 10
  21 + MaxTaskPerWorker = 20
19 ) 22 )
20 23
21 type bucket struct { 24 type bucket struct {
@@ -74,14 +77,16 @@ type TimeWheel struct { @@ -74,14 +77,16 @@ type TimeWheel struct {
74 77
75 WorkPool *WorkPool 78 WorkPool *WorkPool
76 exit chan struct{} 79 exit chan struct{}
  80 + exitFlag uint32
77 } 81 }
78 82
79 func NewTimeWheel() *TimeWheel { 83 func NewTimeWheel() *TimeWheel {
80 tw := &TimeWheel{ 84 tw := &TimeWheel{
81 tick: 10*time.Millisecond, 85 tick: 10*time.Millisecond,
82 time: 0, 86 time: 0,
83 - WorkPool: NewWorkPool(common.WorkerPoolSize, common.MaxTaskPerWorker), 87 + WorkPool: NewWorkPool(WorkerPoolSize, MaxTaskPerWorker),
84 exit: make(chan struct{}), 88 exit: make(chan struct{}),
  89 + exitFlag: 0,
85 } 90 }
86 for i :=0; i < TimeNear; i++ { 91 for i :=0; i < TimeNear; i++ {
87 tw.near[i] = newBucket() 92 tw.near[i] = newBucket()
@@ -183,6 +188,12 @@ func (tw *TimeWheel) Start() { @@ -183,6 +188,12 @@ func (tw *TimeWheel) Start() {
183 } 188 }
184 189
185 func (tw *TimeWheel) Stop() { 190 func (tw *TimeWheel) Stop() {
  191 + flag := atomic.LoadUint32(&tw.exitFlag)
  192 + if flag != 0 {
  193 + return
  194 + }
  195 +
  196 + atomic.StoreUint32(&tw.exitFlag, 1)
186 close(tw.exit) 197 close(tw.exit)
187 } 198 }
188 199
1 package common 1 package common
2 2
3 const ( 3 const (
4 - //协程池 大小  
5 - WorkerPoolSize = 10  
6 - MaxTaskPerWorker = 100  
7 -  
8 //最大包大 4 //最大包大
9 MaxPacketLength = 10 * 1024 * 1024 5 MaxPacketLength = 10 * 1024 * 1024
10 MaxMsgChan = 100 6 MaxMsgChan = 100
11 7
12 - //jwt  
13 - Pro2DTokenSignedString = "Pro2DSecret"  
14 -  
15 - //定时器  
16 - TickMS = 10  
17 - WheelSize = 3600  
18 -  
19 //心跳 8 //心跳
20 HeartTimerInterval = 5 //s 9 HeartTimerInterval = 5 //s
21 HeartTimeoutCountMax = 20 //最大超时次数 10 HeartTimeoutCountMax = 20 //最大超时次数
@@ -33,6 +33,7 @@ am[uint32(1)] = HotRpc @@ -33,6 +33,7 @@ am[uint32(1)] = HotRpc
33 2. 增加函数`HotRpc` 33 2. 增加函数`HotRpc`
34 ``` 34 ```
35 func HotRpc(msg components.IMessage) (int32, interface{}) { 35 func HotRpc(msg components.IMessage) (int32, interface{}) {
  36 + return 0, nil
36 } 37 }
37 ``` 38 ```
38 39