Commit 2e0aa29811785c6f64b79661328b8adee619c8eb
1 parent
38dd96b4
update 每条连接新增一条协程,用于接受处理网络数据的逻辑和定时器的逻辑, 防止数据竞争
Showing
8 changed files
with
49 additions
and
53 deletions
Show diff stats
src/components/net/conn.go
| @@ -30,6 +30,9 @@ type Connection struct { | @@ -30,6 +30,9 @@ type Connection struct { | ||
| 30 | 30 | ||
| 31 | WBuffer chan []byte | 31 | WBuffer chan []byte |
| 32 | 32 | ||
| 33 | + updateFunc chan func() | ||
| 34 | + readFunc chan func() | ||
| 35 | + | ||
| 33 | Quit chan *Connection | 36 | Quit chan *Connection |
| 34 | 37 | ||
| 35 | Role *models.RoleModel | 38 | Role *models.RoleModel |
| @@ -54,9 +57,11 @@ func NewConn(id int, conn net.Conn, s *Server) *Connection { | @@ -54,9 +57,11 @@ func NewConn(id int, conn net.Conn, s *Server) *Connection { | ||
| 54 | scanner: bufio.NewScanner(conn), | 57 | scanner: bufio.NewScanner(conn), |
| 55 | writer: bufio.NewWriter(conn), | 58 | writer: bufio.NewWriter(conn), |
| 56 | WBuffer: make(chan []byte), | 59 | WBuffer: make(chan []byte), |
| 60 | + updateFunc: make(chan func()), | ||
| 61 | + readFunc: make(chan func()), | ||
| 57 | Quit: make(chan *Connection), | 62 | Quit: make(chan *Connection), |
| 58 | lastHeartCheckTime: utils.Timex(), | 63 | lastHeartCheckTime: utils.Timex(), |
| 59 | - heartTimeoutCount: 0, | 64 | + heartTimeoutCount: 0, |
| 60 | } | 65 | } |
| 61 | } | 66 | } |
| 62 | 67 | ||
| @@ -87,10 +92,7 @@ func (c *Connection) read() { | @@ -87,10 +92,7 @@ func (c *Connection) read() { | ||
| 87 | } | 92 | } |
| 88 | 93 | ||
| 89 | req.Conn = c | 94 | req.Conn = c |
| 90 | - //得到需要处理此条连接的workerID | ||
| 91 | - workerID := c.Id % c.Server.SConf.WorkerPoolSize | ||
| 92 | - //将请求消息发送给任务队列 | ||
| 93 | - c.Server.TaskQueue[workerID] <- func() { | 95 | + c.readFunc <- func() { |
| 94 | c.Server.DoMsgHandler(req) | 96 | c.Server.DoMsgHandler(req) |
| 95 | } | 97 | } |
| 96 | 98 | ||
| @@ -132,26 +134,41 @@ func (c *Connection) update() { | @@ -132,26 +134,41 @@ func (c *Connection) update() { | ||
| 132 | } | 134 | } |
| 133 | 135 | ||
| 134 | if c.Role != nil { | 136 | if c.Role != nil { |
| 135 | - c.Server.TaskQueue[c.Id % c.Server.SConf.WorkerPoolSize] <- func() { | ||
| 136 | - //role 获取Recover | 137 | + c.updateFunc <- func() { |
| 138 | + //role 恢复数据 | ||
| 137 | c.Role.OnRecoverTimer(now) | 139 | c.Role.OnRecoverTimer(now) |
| 138 | } | 140 | } |
| 139 | } | 141 | } |
| 140 | } | 142 | } |
| 141 | 143 | ||
| 144 | +func (c *Connection) flush() { | ||
| 145 | + defer c.Stop() | ||
| 146 | + for { | ||
| 147 | + select { | ||
| 148 | + case rf := <- c.readFunc: | ||
| 149 | + rf() | ||
| 150 | + case uf := <- c.updateFunc: | ||
| 151 | + uf() | ||
| 152 | + case <- c.Quit: | ||
| 153 | + return | ||
| 154 | + } | ||
| 155 | + } | ||
| 156 | +} | ||
| 142 | 157 | ||
| 143 | func (c *Connection) Start() { | 158 | func (c *Connection) Start() { |
| 144 | go c.write() | 159 | go c.write() |
| 145 | go c.read() | 160 | go c.read() |
| 161 | + c.flush() | ||
| 146 | } | 162 | } |
| 147 | 163 | ||
| 148 | func (c *Connection) Stop() { | 164 | func (c *Connection) Stop() { |
| 165 | + logger.Debug("ID: %d close", c.Id) | ||
| 149 | c.Conn.Close() | 166 | c.Conn.Close() |
| 167 | + c.Server.OnClose(c) | ||
| 150 | } | 168 | } |
| 151 | 169 | ||
| 152 | func (c *Connection) Quiting() { | 170 | func (c *Connection) Quiting() { |
| 153 | - logger.Debug("ID: %d close", c.Id) | ||
| 154 | - c.Server.OnClose(c) | 171 | + c.Quit <- c |
| 155 | } | 172 | } |
| 156 | 173 | ||
| 157 | func (c *Connection) SendMsgByCode(errCode int32, cmd int32, data []byte){ | 174 | func (c *Connection) SendMsgByCode(errCode int32, cmd int32, data []byte){ |
src/components/net/msg.go
| @@ -54,4 +54,4 @@ func EncodeMsg(pkg *MsgPkg) ([]byte, error) { | @@ -54,4 +54,4 @@ func EncodeMsg(pkg *MsgPkg) ([]byte, error) { | ||
| 54 | return nil, err | 54 | return nil, err |
| 55 | } | 55 | } |
| 56 | return buf.Bytes(), nil | 56 | return buf.Bytes(), nil |
| 57 | -} | 57 | -} |
| 58 | +} | ||
| 58 | \ No newline at end of file | 59 | \ No newline at end of file |
src/components/net/server.go
| 1 | package net | 1 | package net |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | + "context" | ||
| 4 | "fmt" | 5 | "fmt" |
| 5 | "github.com/golang/protobuf/proto" | 6 | "github.com/golang/protobuf/proto" |
| 6 | "net" | 7 | "net" |
| 7 | "plugin" | 8 | "plugin" |
| 8 | "pro2d/conf" | 9 | "pro2d/conf" |
| 9 | "pro2d/protos/pb" | 10 | "pro2d/protos/pb" |
| 10 | - "pro2d/src/common" | ||
| 11 | "pro2d/src/components/db" | 11 | "pro2d/src/components/db" |
| 12 | "pro2d/src/components/etcd" | 12 | "pro2d/src/components/etcd" |
| 13 | "pro2d/src/components/logger" | 13 | "pro2d/src/components/logger" |
| @@ -19,14 +19,11 @@ import ( | @@ -19,14 +19,11 @@ import ( | ||
| 19 | 19 | ||
| 20 | type ActionHandler func (msg *MsgPkg) (int32, proto.Message) | 20 | type ActionHandler func (msg *MsgPkg) (int32, proto.Message) |
| 21 | var ActionMap map[pb.ProtoCode]ActionHandler | 21 | var ActionMap map[pb.ProtoCode]ActionHandler |
| 22 | -var TimeWheel *timewheel.TimeWheel | ||
| 23 | 22 | ||
| 24 | type Server struct { | 23 | type Server struct { |
| 25 | SConf *conf.SConf | 24 | SConf *conf.SConf |
| 26 | Clients *sync.Map | 25 | Clients *sync.Map |
| 27 | EtcdClient *etcd.EtcdClient | 26 | EtcdClient *etcd.EtcdClient |
| 28 | - | ||
| 29 | - TaskQueue []chan func() | ||
| 30 | } | 27 | } |
| 31 | 28 | ||
| 32 | func NewServer(sConf *conf.SConf) *Server { | 29 | func NewServer(sConf *conf.SConf) *Server { |
| @@ -34,34 +31,6 @@ func NewServer(sConf *conf.SConf) *Server { | @@ -34,34 +31,6 @@ func NewServer(sConf *conf.SConf) *Server { | ||
| 34 | SConf: sConf, | 31 | SConf: sConf, |
| 35 | Clients: new(sync.Map), | 32 | Clients: new(sync.Map), |
| 36 | EtcdClient: new(etcd.EtcdClient), | 33 | EtcdClient: new(etcd.EtcdClient), |
| 37 | - | ||
| 38 | - TaskQueue: make([]chan func(), common.WorkerPoolSize), | ||
| 39 | - } | ||
| 40 | -} | ||
| 41 | - | ||
| 42 | -//StartWorkerPool 启动worker工作池 | ||
| 43 | -func (s *Server) StartWorkerPool() { | ||
| 44 | - //遍历需要启动worker的数量,依此启动 | ||
| 45 | - for i := 0; i < s.SConf.WorkerPoolSize; i++ { | ||
| 46 | - //一个worker被启动 | ||
| 47 | - //给当前worker对应的任务队列开辟空间 | ||
| 48 | - s.TaskQueue[i] = make(chan func(), common.MaxTaskPerWorker) | ||
| 49 | - //启动当前Worker,阻塞的等待对应的任务队列是否有消息传递进来 | ||
| 50 | - go s.StartOneWorker(i, s.TaskQueue[i]) | ||
| 51 | - } | ||
| 52 | -} | ||
| 53 | - | ||
| 54 | -//StartOneWorker 启动一个Worker工作流程 | ||
| 55 | -func (s *Server) StartOneWorker(workerID int, taskQueue chan func()) { | ||
| 56 | - //不断的等待队列中的消息 | ||
| 57 | - for { | ||
| 58 | - select { | ||
| 59 | - //有消息则取出队列的Request,并执行绑定的业务方法 | ||
| 60 | - case f:= <-taskQueue: | ||
| 61 | - _ = workerID | ||
| 62 | - f() | ||
| 63 | - //s.DoMsgHandler(request) | ||
| 64 | - } | ||
| 65 | } | 34 | } |
| 66 | } | 35 | } |
| 67 | 36 | ||
| @@ -131,9 +100,6 @@ func (s *Server)Start() error { | @@ -131,9 +100,6 @@ func (s *Server)Start() error { | ||
| 131 | return err | 100 | return err |
| 132 | } | 101 | } |
| 133 | 102 | ||
| 134 | - //启动协程池 | ||
| 135 | - s.StartWorkerPool() | ||
| 136 | - | ||
| 137 | //启动定时器 | 103 | //启动定时器 |
| 138 | s.handleTimeOut() | 104 | s.handleTimeOut() |
| 139 | 105 | ||
| @@ -154,5 +120,13 @@ func (s *Server)Start() error { | @@ -154,5 +120,13 @@ func (s *Server)Start() error { | ||
| 154 | } | 120 | } |
| 155 | 121 | ||
| 156 | func (s *Server)Stop() { | 122 | func (s *Server)Stop() { |
| 157 | - TimeWheel.Stop() | 123 | + timewheel.StopTimer() |
| 124 | + | ||
| 125 | + s.Clients.Range(func(key, value interface{}) bool { | ||
| 126 | + client := value.(*Connection) | ||
| 127 | + client.Stop() | ||
| 128 | + return true | ||
| 129 | + }) | ||
| 130 | + | ||
| 131 | + db.MongoClient.Disconnect(context.TODO()) | ||
| 158 | } | 132 | } |
| 159 | \ No newline at end of file | 133 | \ No newline at end of file |
src/components/timewheel/timerwheel.go
| @@ -83,7 +83,7 @@ func NewTimeWheel() *TimeWheel { | @@ -83,7 +83,7 @@ func NewTimeWheel() *TimeWheel { | ||
| 83 | tick: 10*time.Millisecond, | 83 | tick: 10*time.Millisecond, |
| 84 | time: 0, | 84 | time: 0, |
| 85 | WorkPool: workpool.NewWorkPool(common.WorkerPoolSize, common.MaxTaskPerWorker), | 85 | WorkPool: workpool.NewWorkPool(common.WorkerPoolSize, common.MaxTaskPerWorker), |
| 86 | - exit: nil, | 86 | + exit: make(chan struct{}), |
| 87 | } | 87 | } |
| 88 | for i :=0; i < TimeNear; i++ { | 88 | for i :=0; i < TimeNear; i++ { |
| 89 | tw.near[i] = newBucket() | 89 | tw.near[i] = newBucket() |
| @@ -198,4 +198,8 @@ func (tw *TimeWheel) afterFunc(expiration time.Duration, f func()) { | @@ -198,4 +198,8 @@ func (tw *TimeWheel) afterFunc(expiration time.Duration, f func()) { | ||
| 198 | 198 | ||
| 199 | func TimeOut(expire time.Duration, f func()) { | 199 | func TimeOut(expire time.Duration, f func()) { |
| 200 | TimingWheel.afterFunc(expire, f) | 200 | TimingWheel.afterFunc(expire, f) |
| 201 | +} | ||
| 202 | + | ||
| 203 | +func StopTimer() { | ||
| 204 | + TimingWheel.Stop() | ||
| 201 | } | 205 | } |
| 202 | \ No newline at end of file | 206 | \ No newline at end of file |
src/models/role.go
| @@ -99,10 +99,10 @@ func (m *RoleModel) AddHero(hero *pb.Hero) { | @@ -99,10 +99,10 @@ func (m *RoleModel) AddHero(hero *pb.Hero) { | ||
| 99 | m.Heros[fmt.Sprintf("%s%s", m.Role.Id, h.Hero.Id)] = h | 99 | m.Heros[fmt.Sprintf("%s%s", m.Role.Id, h.Hero.Id)] = h |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | -func (m *RoleModel) GetAllHero() map[string]*pb.Hero { | ||
| 103 | - h := make(map[string]*pb.Hero) | ||
| 104 | - for k, hero := range m.Heros { | ||
| 105 | - h[k] = hero.Hero | 102 | +func (m *RoleModel) GetAllHero() []*pb.Hero { |
| 103 | + var h []*pb.Hero | ||
| 104 | + for _, hero := range m.Heros { | ||
| 105 | + h = append(h, hero.Hero) | ||
| 106 | } | 106 | } |
| 107 | return h | 107 | return h |
| 108 | } | 108 | } |
src/plugin/RolePlugin.go
| @@ -54,6 +54,7 @@ func LoginRpc(msg *net.MsgPkg) (int32, proto.Message) { | @@ -54,6 +54,7 @@ func LoginRpc(msg *net.MsgPkg) (int32, proto.Message) { | ||
| 54 | // Team: nil, | 54 | // Team: nil, |
| 55 | // Equips: nil, | 55 | // Equips: nil, |
| 56 | //} | 56 | //} |
| 57 | + msg.Conn.Role = role | ||
| 57 | return 0, &pb.RoleRsp{ | 58 | return 0, &pb.RoleRsp{ |
| 58 | Role: role.Role, | 59 | Role: role.Role, |
| 59 | Hero: role.GetAllHero(), | 60 | Hero: role.GetAllHero(), |
test/client.go
| @@ -69,7 +69,7 @@ func main() { | @@ -69,7 +69,7 @@ func main() { | ||
| 69 | return | 69 | return |
| 70 | } | 70 | } |
| 71 | logger.Debug("recv: %s, n: %d\n", b1, n) | 71 | logger.Debug("recv: %s, n: %d\n", b1, n) |
| 72 | - time.Sleep(5*time.Second) | 72 | + time.Sleep(1*time.Second) |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | } | 75 | } |
| 76 | \ No newline at end of file | 76 | \ No newline at end of file |