Commit cd2f96ab70602424ec48f1ad23292ba7aa45c231
1 parent
364620cd
fix: 优化连接管理
只使用一份连接管理,把数据放在底层,操作放在应用层
Showing
4 changed files
with
69 additions
and
82 deletions
Show diff stats
cmd/gameserver/game.go
... | ... | @@ -9,20 +9,15 @@ import ( |
9 | 9 | "pro2d/models" |
10 | 10 | |
11 | 11 | "pro2d/common/etcd" |
12 | - "sync" | |
13 | 12 | ) |
14 | 13 | |
15 | 14 | type GameServer struct { |
16 | 15 | components.IServer |
17 | 16 | EtcdClient *etcd.EtcdClient |
18 | - | |
19 | - Agents *sync.Map | |
20 | 17 | } |
21 | 18 | |
22 | -func NewGameServer(sconf *common.SConf) (*GameServer, error) { | |
23 | - s := &GameServer{ | |
24 | - Agents: new(sync.Map), | |
25 | - } | |
19 | +func NewGameServer(sconf *common.SConf) (*GameServer, error) { | |
20 | + s := &GameServer{} | |
26 | 21 | |
27 | 22 | options := []components.ServerOption{ |
28 | 23 | components.WithPlugin(components.NewPlugin(sconf.PluginPath)), |
... | ... | @@ -57,40 +52,40 @@ func (s *GameServer) Start() error { |
57 | 52 | return s.IServer.Start() |
58 | 53 | } |
59 | 54 | |
60 | -func (s *GameServer) Stop() { | |
55 | +func (s *GameServer) Stop() { | |
61 | 56 | s.IServer.Stop() |
62 | 57 | |
63 | 58 | db.CloseMongo() |
64 | 59 | s.EtcdClient.Close() |
65 | 60 | } |
66 | 61 | |
67 | -func (s *GameServer) OnConnection(conn components.IConnection) { | |
62 | +func (s *GameServer) OnConnection(conn components.IConnection) { | |
68 | 63 | agent := NewAgent(s) |
69 | 64 | agent.OnConnection(conn) |
70 | - s.Agents.Store(conn.GetID(),agent) | |
65 | + s.GetConnManage().AddConn(conn.GetID(), agent) | |
71 | 66 | } |
72 | 67 | |
73 | -func (s *GameServer) OnMessage(msg components.IMessage) { | |
74 | - agent, ok := s.Agents.Load(msg.GetSession().GetID()) | |
75 | - if !ok { | |
68 | +func (s *GameServer) OnMessage(msg components.IMessage) { | |
69 | + agent := s.GetConnManage().GetConn(msg.GetSession().GetID()) | |
70 | + if agent == nil { | |
76 | 71 | return |
77 | 72 | } |
78 | 73 | agent.(*Agent).OnMessage(msg) |
79 | 74 | } |
80 | 75 | |
81 | -func (s *GameServer) OnTimer(conn components.IConnection) { | |
82 | - agent, ok := s.Agents.Load(conn.GetID()) | |
83 | - if !ok { | |
76 | +func (s *GameServer) OnTimer(conn components.IConnection) { | |
77 | + agent := s.GetConnManage().GetConn(conn.GetID()) | |
78 | + if agent == nil { | |
84 | 79 | return |
85 | 80 | } |
86 | 81 | agent.(*Agent).OnTimer() |
87 | 82 | } |
88 | 83 | |
89 | -func (s *GameServer) OnClose(conn components.IConnection) { | |
90 | - agent, ok := s.Agents.Load(conn.GetID()) | |
91 | - if !ok { | |
84 | +func (s *GameServer) OnClose(conn components.IConnection) { | |
85 | + agent := s.GetConnManage().GetConn(conn.GetID()) | |
86 | + if agent == nil { | |
92 | 87 | return |
93 | 88 | } |
94 | 89 | agent.(*Agent).OnClose() |
95 | - s.Agents.Delete(conn.GetID()) | |
90 | + s.GetConnManage().DelConn(conn.GetID()) | |
96 | 91 | } | ... | ... |
common/components/conn.go
... | ... | @@ -10,17 +10,16 @@ import ( |
10 | 10 | "time" |
11 | 11 | ) |
12 | 12 | |
13 | - | |
14 | 13 | type Connection struct { |
15 | 14 | IConnection |
16 | 15 | net.Conn |
17 | 16 | Server IServer |
18 | 17 | Id int |
19 | 18 | |
20 | - scanner *bufio.Scanner | |
21 | - writer *bufio.Writer | |
22 | - WBuffer chan []byte | |
23 | - Quit chan *Connection | |
19 | + scanner *bufio.Scanner | |
20 | + writer *bufio.Writer | |
21 | + WBuffer chan []byte | |
22 | + Quit chan *Connection | |
24 | 23 | readFunc chan func() |
25 | 24 | timerFunc chan func() |
26 | 25 | |
... | ... | @@ -34,18 +33,18 @@ type Connection struct { |
34 | 33 | |
35 | 34 | func NewConn(id int, conn net.Conn, s IServer) *Connection { |
36 | 35 | c := &Connection{ |
37 | - Id: id, | |
38 | - Conn: conn, | |
39 | - Server: s, | |
40 | - | |
41 | - scanner: bufio.NewScanner(conn), | |
42 | - writer: bufio.NewWriter(conn), | |
43 | - WBuffer: make(chan []byte, common.MaxMsgChan), | |
44 | - Quit: make(chan *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), | |
45 | 44 | readFunc: make(chan func(), 10), |
46 | 45 | timerFunc: make(chan func(), 10), |
47 | 46 | |
48 | - Status: 0, | |
47 | + Status: 0, | |
49 | 48 | } |
50 | 49 | c.connectionCallback = c.defaultConnectionCallback |
51 | 50 | c.messageCallback = c.defaultMessageCallback |
... | ... | @@ -74,7 +73,7 @@ func (c *Connection) SetTimerCallback(cb TimerCallback) { |
74 | 73 | c.timerCallback = cb |
75 | 74 | } |
76 | 75 | |
77 | -func (c *Connection) Start() { | |
76 | +func (c *Connection) Start() { | |
78 | 77 | go c.write() |
79 | 78 | go c.read() |
80 | 79 | go c.listen() |
... | ... | @@ -96,7 +95,7 @@ func (c *Connection) Stop() { |
96 | 95 | } |
97 | 96 | } |
98 | 97 | |
99 | -func (c *Connection) Send(errCode int32, cmd uint32, data []byte) error{ | |
98 | +func (c *Connection) Send(errCode int32, cmd uint32, data []byte) error { | |
100 | 99 | buf, err := c.Server.GetSplitter().Pack(cmd, data, errCode, 0) |
101 | 100 | if err != nil { |
102 | 101 | return err |
... | ... | @@ -113,25 +112,25 @@ func (c *Connection) Send(errCode int32, cmd uint32, data []byte) error{ |
113 | 112 | } |
114 | 113 | } |
115 | 114 | |
116 | -func (c *Connection) defaultConnectionCallback(conn IConnection) { | |
115 | +func (c *Connection) defaultConnectionCallback(conn IConnection) { | |
117 | 116 | } |
118 | 117 | |
119 | -func (c *Connection) defaultMessageCallback(msg IMessage) { | |
118 | +func (c *Connection) defaultMessageCallback(msg IMessage) { | |
120 | 119 | } |
121 | 120 | |
122 | -func (c *Connection) defaultCloseCallback(conn IConnection) { | |
121 | +func (c *Connection) defaultCloseCallback(conn IConnection) { | |
123 | 122 | } |
124 | 123 | |
125 | -func (c *Connection) defaultTimerCallback(conn IConnection) { | |
124 | +func (c *Connection) defaultTimerCallback(conn IConnection) { | |
126 | 125 | } |
127 | 126 | |
128 | -func (c *Connection) write() { | |
127 | +func (c *Connection) write() { | |
129 | 128 | defer c.quitting() |
130 | 129 | |
131 | 130 | for msg := range c.WBuffer { |
132 | 131 | n, err := c.writer.Write(msg) |
133 | - if err != nil{ | |
134 | - logger.Error("write fail err: " + err.Error(), "n: ", n) | |
132 | + if err != nil { | |
133 | + logger.Error("write fail err: "+err.Error(), "n: ", n) | |
135 | 134 | return |
136 | 135 | } |
137 | 136 | if err := c.writer.Flush(); err != nil { |
... | ... | @@ -164,16 +163,16 @@ func (c *Connection) read() { |
164 | 163 | } |
165 | 164 | |
166 | 165 | //此设计目的是为了让网络数据与定时器处理都在一条协程里处理。不想加锁。。。 |
167 | -func (c *Connection) listen(){ | |
166 | +func (c *Connection) listen() { | |
168 | 167 | defer c.quitting() |
169 | 168 | |
170 | - for { | |
169 | + for { | |
171 | 170 | select { |
172 | - case timerFunc := <- c.timerFunc: | |
171 | + case timerFunc := <-c.timerFunc: | |
173 | 172 | timerFunc() |
174 | - case readFunc := <- c.readFunc: | |
173 | + case readFunc := <-c.readFunc: | |
175 | 174 | readFunc() |
176 | - case <- c.Quit: | |
175 | + case <-c.Quit: | |
177 | 176 | return |
178 | 177 | } |
179 | 178 | } |
... | ... | @@ -186,7 +185,7 @@ func (c *Connection) handleTimeOut() { |
186 | 185 | TimeOut(1*time.Second, c.handleTimeOut) |
187 | 186 | } |
188 | 187 | |
189 | -func (c *Connection) quitting() { | |
188 | +func (c *Connection) quitting() { | |
190 | 189 | closed := atomic.LoadUint32(&c.Status) |
191 | 190 | if closed == 0 { |
192 | 191 | return |
... | ... | @@ -196,6 +195,7 @@ func (c *Connection) quitting() { |
196 | 195 | logger.Debug("ID: %d close", c.Id) |
197 | 196 | close(c.WBuffer) |
198 | 197 | close(c.Quit) |
198 | + close(c.readFunc) | |
199 | 199 | c.Conn.Close() |
200 | 200 | c.closeCallback(c) |
201 | 201 | } | ... | ... |
common/components/icompontents.go
... | ... | @@ -46,15 +46,23 @@ type ( |
46 | 46 | SetCloseCallback(CloseCallback) |
47 | 47 | SetTimerCallback(TimerCallback) |
48 | 48 | } |
49 | + //connManage | |
50 | + IConnManage interface { | |
51 | + AddConn(id int, connection IConnection) | |
52 | + GetConn(id int) IConnection | |
53 | + DelConn(id int) IConnection | |
54 | + Range(f func(key interface{}, value interface{}) bool) | |
55 | + StopAllConns() | |
56 | + } | |
49 | 57 | //server |
50 | 58 | IServer interface { |
51 | 59 | Start() error |
52 | 60 | Stop() |
53 | 61 | |
54 | 62 | GetSplitter() ISplitter |
55 | - GetIConnection(id int) IConnection | |
56 | 63 | GetPlugin() IPlugin |
57 | 64 | GetAction(uint32) interface{} |
65 | + GetConnManage() IConnManage | |
58 | 66 | |
59 | 67 | SetConnectionCallback(ConnectionCallback) |
60 | 68 | SetMessageCallback(MessageCallback) |
... | ... | @@ -75,8 +83,6 @@ type ( |
75 | 83 | SetActions(map[interface{}]interface{}) |
76 | 84 | GetAction(uint32) interface{} |
77 | 85 | } |
78 | - | |
79 | - | |
80 | 86 | ) |
81 | 87 | |
82 | 88 | //----------------- | ... | ... |
common/components/server.go
... | ... | @@ -4,7 +4,6 @@ import ( |
4 | 4 | "fmt" |
5 | 5 | "net" |
6 | 6 | "pro2d/common/logger" |
7 | - "sync" | |
8 | 7 | ) |
9 | 8 | |
10 | 9 | type ServerOption func(*Server) |
... | ... | @@ -45,25 +44,24 @@ func WithTimerCbk(cb TimerCallback) ServerOption { |
45 | 44 | } |
46 | 45 | } |
47 | 46 | |
48 | - | |
49 | 47 | type Server struct { |
50 | - PluginPath string | |
51 | - plugins IPlugin | |
52 | - splitter ISplitter | |
48 | + PluginPath string | |
49 | + plugins IPlugin | |
50 | + splitter ISplitter | |
53 | 51 | |
54 | - connectionCallback ConnectionCallback | |
55 | - messageCallback MessageCallback | |
56 | - closeCallback CloseCallback | |
57 | - timerCallback TimerCallback | |
52 | + connectionCallback ConnectionCallback | |
53 | + messageCallback MessageCallback | |
54 | + closeCallback CloseCallback | |
55 | + timerCallback TimerCallback | |
58 | 56 | |
59 | - port int | |
60 | - Clients *sync.Map | |
57 | + port int | |
58 | + connManage *ConnManage | |
61 | 59 | } |
62 | 60 | |
63 | 61 | func NewServer(port int, options ...ServerOption) IServer { |
64 | 62 | s := &Server{ |
65 | - port: port, | |
66 | - Clients: new(sync.Map), | |
63 | + port: port, | |
64 | + connManage: NewConnManage(), | |
67 | 65 | } |
68 | 66 | for _, option := range options { |
69 | 67 | option(s) |
... | ... | @@ -76,14 +74,6 @@ func (s *Server) GetSplitter() ISplitter { |
76 | 74 | return s.splitter |
77 | 75 | } |
78 | 76 | |
79 | -func (s *Server) GetIConnection(id int) IConnection { | |
80 | - c, ok := s.Clients.Load(id) | |
81 | - if !ok { | |
82 | - return nil | |
83 | - } | |
84 | - return c.(IConnection) | |
85 | -} | |
86 | - | |
87 | 77 | func (s *Server) GetPlugin() IPlugin { |
88 | 78 | return s.plugins |
89 | 79 | } |
... | ... | @@ -92,6 +82,10 @@ func (s *Server) GetAction(cmd uint32) interface{} { |
92 | 82 | return s.plugins.GetAction(cmd) |
93 | 83 | } |
94 | 84 | |
85 | +func (s *Server) GetConnManage() IConnManage { | |
86 | + return s.connManage | |
87 | +} | |
88 | + | |
95 | 89 | func (s *Server) SetConnectionCallback(cb ConnectionCallback) { |
96 | 90 | s.connectionCallback = cb |
97 | 91 | } |
... | ... | @@ -133,19 +127,12 @@ func (s *Server) Start() error { |
133 | 127 | } |
134 | 128 | } |
135 | 129 | |
136 | -func (s *Server)Stop() { | |
130 | +func (s *Server) Stop() { | |
137 | 131 | StopTimer() |
138 | 132 | |
139 | - s.Clients.Range(func(key, value interface{}) bool { | |
140 | - client := value.(IConnection) | |
141 | - client.Stop() | |
142 | - return true | |
143 | - }) | |
144 | 133 | } |
145 | 134 | |
146 | 135 | func (s *Server) newConnection(conn IConnection) { |
147 | - s.Clients.Store(conn.GetID(), conn) | |
148 | - | |
149 | 136 | conn.SetConnectionCallback(s.connectionCallback) |
150 | 137 | conn.SetCloseCallback(s.removeConnection) |
151 | 138 | conn.SetMessageCallback(s.messageCallback) |
... | ... | @@ -156,5 +143,4 @@ func (s *Server) newConnection(conn IConnection) { |
156 | 143 | |
157 | 144 | func (s *Server) removeConnection(conn IConnection) { |
158 | 145 | s.closeCallback(conn) |
159 | - s.Clients.Delete(conn.GetID()) | |
160 | 146 | } | ... | ... |