Commit 69d286a7c94629a66d3065140ade7d58ae77166b

Authored by zhangqijia
1 parent cd2f96ab

fix: 插件用来做部分热更

1. 调整逻辑代码位置
2. 插件里做部分逻辑热更
@@ -11,7 +11,7 @@ test: @@ -11,7 +11,7 @@ test:
11 http: 11 http:
12 go run -race cmd/httpserver/http.go cmd/httpserver/AccountAction.go 12 go run -race cmd/httpserver/http.go cmd/httpserver/AccountAction.go
13 13
14 -game:plugin 14 +game:
15 go run -race cmd/gameserver/*.go 15 go run -race cmd/gameserver/*.go
16 build: 16 build:
17 go build -race -o bin/account cmd/http.go 17 go build -race -o bin/account cmd/http.go
cmd/gameserver/plugin/RolePlugin.go renamed to cmd/gameserver/action/RoleAction.go
1 -package main 1 +package action
2 2
3 import ( 3 import (
4 "github.com/golang/protobuf/proto" 4 "github.com/golang/protobuf/proto"
@@ -9,12 +9,12 @@ import ( @@ -9,12 +9,12 @@ import (
9 "pro2d/pb" 9 "pro2d/pb"
10 ) 10 )
11 11
12 -func HeartRpc(msg components.IMessage) (int32, interface{}) { 12 +func HeartRpc(msg components.IMessage) (int32, interface{}) {
13 //msg.Conn.SetLastHeartCheckTime() 13 //msg.Conn.SetLastHeartCheckTime()
14 return 0, nil 14 return 0, nil
15 } 15 }
16 16
17 -func CreateRpc(msg components.IMessage) (int32, interface{}) { 17 +func CreateRpc(msg components.IMessage) (int32, interface{}) {
18 req := pb.CreateReq{} 18 req := pb.CreateReq{}
19 if err := proto.Unmarshal(msg.GetData(), &req); err != nil { 19 if err := proto.Unmarshal(msg.GetData(), &req); err != nil {
20 logger.Error("CreateRpc err: %v", err) 20 logger.Error("CreateRpc err: %v", err)
@@ -27,14 +27,14 @@ func CreateRpc(msg components.IMessage) (int32, interface{}) { @@ -27,14 +27,14 @@ func CreateRpc(msg components.IMessage) (int32, interface{}) {
27 27
28 roleId := common.SnowFlack.NextValStr() 28 roleId := common.SnowFlack.NextValStr()
29 role = models.NewRole(roleId) 29 role = models.NewRole(roleId)
30 - if err := role.Create(); err != nil { 30 + if err := role.Create(); err != nil {
31 logger.Error("CreateRpc role create err: %v", err) 31 logger.Error("CreateRpc role create err: %v", err)
32 return 3, nil 32 return 3, nil
33 } 33 }
34 return 0, nil 34 return 0, nil
35 } 35 }
36 36
37 -func LoginRpc(msg components.IMessage) (int32, interface{}) { 37 +func LoginRpc(msg components.IMessage) (int32, interface{}) {
38 //logger.Debug("11111111cmd: %v, msg: %s", msg.GetHeader().GetMsgID(), msg.GetData()) 38 //logger.Debug("11111111cmd: %v, msg: %s", msg.GetHeader().GetMsgID(), msg.GetData())
39 req := pb.LoginReq{} 39 req := pb.LoginReq{}
40 if err := proto.Unmarshal(msg.GetData(), &req); err != nil { 40 if err := proto.Unmarshal(msg.GetData(), &req); err != nil {
@@ -49,9 +49,9 @@ func LoginRpc(msg components.IMessage) (int32, interface{}) { @@ -49,9 +49,9 @@ func LoginRpc(msg components.IMessage) (int32, interface{}) {
49 role.SetProperty("Device", req.Device) 49 role.SetProperty("Device", req.Device)
50 50
51 return 0, &pb.RoleRsp{ 51 return 0, &pb.RoleRsp{
52 - Role: role.Role,  
53 - Hero: role.GetAllHero(),  
54 - Team: role.Teams.Team, 52 + Role: role.Role,
  53 + Hero: role.GetAllHero(),
  54 + Team: role.Teams.Team,
55 Equips: []*pb.Equipment{role.Equip.Equip}, 55 Equips: []*pb.Equipment{role.Equip.Equip},
56 } 56 }
57 -}  
58 \ No newline at end of file 57 \ No newline at end of file
  58 +}
cmd/gameserver/plugin/protocode.go renamed to cmd/gameserver/action/protocode.go
1 -package main 1 +package action
2 2
3 import ( 3 import (
4 "pro2d/common/logger" 4 "pro2d/common/logger"
@@ -8,9 +8,9 @@ import ( @@ -8,9 +8,9 @@ import (
8 func GetActionMap() map[interface{}]interface{} { 8 func GetActionMap() map[interface{}]interface{} {
9 logger.Debug("init protocode...") 9 logger.Debug("init protocode...")
10 am := make(map[interface{}]interface{}) 10 am := make(map[interface{}]interface{})
11 - am[pb.ProtoCode_HeartReq] = HeartRpc  
12 - am[pb.ProtoCode_LoginReq] = LoginRpc  
13 - am[pb.ProtoCode_CreateReq] = CreateRpc 11 + am[uint32(pb.ProtoCode_HeartReq)] = HeartRpc
  12 + am[uint32(pb.ProtoCode_LoginReq)] = LoginRpc
  13 + am[uint32(pb.ProtoCode_CreateReq)] = CreateRpc
14 14
15 return am 15 return am
16 -}  
17 \ No newline at end of file 16 \ No newline at end of file
  17 +}
cmd/gameserver/game.go
@@ -3,6 +3,7 @@ package main @@ -3,6 +3,7 @@ package main
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 _ "net/http/pprof" 5 _ "net/http/pprof"
  6 + "pro2d/cmd/gameserver/action"
6 "pro2d/common" 7 "pro2d/common"
7 "pro2d/common/components" 8 "pro2d/common/components"
8 "pro2d/common/db" 9 "pro2d/common/db"
@@ -29,6 +30,7 @@ func NewGameServer(sconf *common.SConf) (*GameServer, error) { @@ -29,6 +30,7 @@ func NewGameServer(sconf *common.SConf) (*GameServer, error) {
29 } 30 }
30 31
31 iserver := components.NewServer(sconf.Port, options...) 32 iserver := components.NewServer(sconf.Port, options...)
  33 + iserver.SetActions(action.GetActionMap())
32 s.IServer = iserver 34 s.IServer = iserver
33 35
34 //mgo init 36 //mgo init
cmd/gameserver/plugin/plugin.go 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +package main
  2 +
  3 +import (
  4 + "github.com/golang/protobuf/proto"
  5 + "pro2d/common/components"
  6 + "pro2d/common/logger"
  7 + "pro2d/models"
  8 + "pro2d/pb"
  9 +)
  10 +
  11 +func init() {
  12 + logger.Debug("init game server plugin")
  13 +}
  14 +
  15 +func GetActionMap() map[interface{}]interface{} {
  16 + logger.Debug("init protocode...")
  17 + am := make(map[interface{}]interface{})
  18 + am[uint32(pb.ProtoCode_LoginReq)] = LoginRpc
  19 +
  20 + return am
  21 +}
  22 +
  23 +func LoginRpc(msg components.IMessage) (int32, interface{}) {
  24 + //logger.Debug("11111111cmd: %v, msg: %s", msg.GetHeader().GetMsgID(), msg.GetData())
  25 + req := pb.LoginReq{}
  26 + if err := proto.Unmarshal(msg.GetData(), &req); err != nil {
  27 + logger.Error("loginRpc err: %v", err)
  28 + return 1, nil
  29 + }
  30 +
  31 + role := models.RoleExistByUid(req.Uid)
  32 + if role == nil {
  33 + return 2, nil
  34 + }
  35 + role.SetProperty("Device", req.Device)
  36 +
  37 + return 0, &pb.RoleRsp{
  38 + Role: role.Role,
  39 + Hero: role.GetAllHero(),
  40 + Team: role.Teams.Team,
  41 + Equips: []*pb.Equipment{role.Equip.Equip},
  42 + }
  43 +}
common/components/connmanage.go 0 → 100644
@@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
  1 +package components
  2 +
  3 +import "sync"
  4 +
  5 +type ConnManage struct {
  6 + mu sync.RWMutex
  7 + conns map[int]IConnection
  8 +}
  9 +
  10 +func NewConnManage() *ConnManage {
  11 + return &ConnManage{
  12 + mu: sync.RWMutex{},
  13 + conns: make(map[int]IConnection),
  14 + }
  15 +}
  16 +
  17 +func (c *ConnManage) AddConn(id int, connection IConnection) {
  18 + c.mu.Lock()
  19 + defer c.mu.Unlock()
  20 + c.conns[id] = connection
  21 +}
  22 +
  23 +func (c *ConnManage) GetConn(id int) IConnection {
  24 + c.mu.RLock()
  25 + defer c.mu.RUnlock()
  26 + return c.conns[id]
  27 +}
  28 +
  29 +func (c *ConnManage) DelConn(id int) IConnection {
  30 + c.mu.Lock()
  31 + defer c.mu.Unlock()
  32 + conn := c.conns[id]
  33 + delete(c.conns, id)
  34 + return conn
  35 +}
  36 +
  37 +func (c *ConnManage) Range(f func(key interface{}, value interface{}) bool) {
  38 + for k, v := range c.conns {
  39 + c.mu.Lock()
  40 + if ok := f(k, v); !ok {
  41 + c.mu.Unlock()
  42 + return
  43 + }
  44 + c.mu.Unlock()
  45 +
  46 + }
  47 +}
  48 +
  49 +func (c *ConnManage) StopAllConns() {
  50 + c.Range(func(key interface{}, value interface{}) bool {
  51 + conn := value.(IConnection)
  52 + conn.Stop()
  53 + return true
  54 + })
  55 +}
common/components/icompontents.go
@@ -62,6 +62,7 @@ type ( @@ -62,6 +62,7 @@ type (
62 GetSplitter() ISplitter 62 GetSplitter() ISplitter
63 GetPlugin() IPlugin 63 GetPlugin() IPlugin
64 GetAction(uint32) interface{} 64 GetAction(uint32) interface{}
  65 + SetActions(map[interface{}]interface{})
65 GetConnManage() IConnManage 66 GetConnManage() IConnManage
66 67
67 SetConnectionCallback(ConnectionCallback) 68 SetConnectionCallback(ConnectionCallback)
@@ -76,7 +77,7 @@ type ( @@ -76,7 +77,7 @@ type (
76 Stop() 77 Stop()
77 BindHandler(interface{}) 78 BindHandler(interface{})
78 } 79 }
79 - ActionHandler func(conn IConnection, msg IMessage) (int32, interface{}) 80 + ActionHandler func(msg IMessage) (int32, interface{})
80 //用于热更逻辑的插件接口 81 //用于热更逻辑的插件接口
81 IPlugin interface { 82 IPlugin interface {
82 LoadPlugin() error 83 LoadPlugin() error
common/components/plugin.go
@@ -3,23 +3,24 @@ package components @@ -3,23 +3,24 @@ package components
3 import ( 3 import (
4 "plugin" 4 "plugin"
5 "pro2d/common/logger" 5 "pro2d/common/logger"
6 - "pro2d/pb"  
7 "sync" 6 "sync"
8 ) 7 )
9 8
10 -type ActionMap sync.Map//map[pb.ProtoCode]ActionHandler  
11 -  
12 type PluginOption func(*Plugin) 9 type PluginOption func(*Plugin)
13 10
14 type Plugin struct { 11 type Plugin struct {
15 pluginPath string 12 pluginPath string
16 13
17 - Actions sync.Map 14 + Actions sync.Map
18 } 15 }
19 16
20 -func NewPlugin(path string, options ...PluginOption) IPlugin{ 17 +func NewPlugin(path string, options ...PluginOption) IPlugin {
  18 + if path == "" {
  19 + return nil
  20 + }
21 p := &Plugin{ 21 p := &Plugin{
22 pluginPath: path, 22 pluginPath: path,
  23 + Actions: sync.Map{},
23 } 24 }
24 for _, option := range options { 25 for _, option := range options {
25 option(p) 26 option(p)
@@ -41,7 +42,7 @@ func (p *Plugin) LoadPlugin() error { @@ -41,7 +42,7 @@ func (p *Plugin) LoadPlugin() error {
41 } 42 }
42 logger.Debug("func LoadPlugin Lookup success...") 43 logger.Debug("func LoadPlugin Lookup success...")
43 44
44 - if x, ok := f.(func()map[interface{}]interface{}); ok { 45 + if x, ok := f.(func() map[interface{}]interface{}); ok {
45 logger.Debug("func LoadPlugin GetActionMap success...") 46 logger.Debug("func LoadPlugin GetActionMap success...")
46 p.SetActions(x()) 47 p.SetActions(x())
47 } 48 }
@@ -50,7 +51,7 @@ func (p *Plugin) LoadPlugin() error { @@ -50,7 +51,7 @@ func (p *Plugin) LoadPlugin() error {
50 } 51 }
51 52
52 func (p *Plugin) GetAction(cmd uint32) interface{} { 53 func (p *Plugin) GetAction(cmd uint32) interface{} {
53 - f, ok := p.Actions.Load(pb.ProtoCode(cmd)) 54 + f, ok := p.Actions.Load(cmd)
54 if !ok { 55 if !ok {
55 return nil 56 return nil
56 } 57 }
@@ -59,7 +60,7 @@ func (p *Plugin) GetAction(cmd uint32) interface{} { @@ -59,7 +60,7 @@ func (p *Plugin) GetAction(cmd uint32) interface{} {
59 60
60 func (p *Plugin) SetActions(am map[interface{}]interface{}) { 61 func (p *Plugin) SetActions(am map[interface{}]interface{}) {
61 for k, v := range am { 62 for k, v := range am {
62 - cmd := k.(pb.ProtoCode) 63 + cmd := k.(uint32)
63 p.Actions.Delete(cmd) 64 p.Actions.Delete(cmd)
64 p.Actions.Store(cmd, v) 65 p.Actions.Store(cmd, v)
65 } 66 }
common/components/server.go
@@ -55,7 +55,8 @@ type Server struct { @@ -55,7 +55,8 @@ type Server struct {
55 timerCallback TimerCallback 55 timerCallback TimerCallback
56 56
57 port int 57 port int
58 - connManage *ConnManage 58 + connManage IConnManage
  59 + Actions map[interface{}]interface{}
59 } 60 }
60 61
61 func NewServer(port int, options ...ServerOption) IServer { 62 func NewServer(port int, options ...ServerOption) IServer {
@@ -79,7 +80,18 @@ func (s *Server) GetPlugin() IPlugin { @@ -79,7 +80,18 @@ func (s *Server) GetPlugin() IPlugin {
79 } 80 }
80 81
81 func (s *Server) GetAction(cmd uint32) interface{} { 82 func (s *Server) GetAction(cmd uint32) interface{} {
82 - return s.plugins.GetAction(cmd) 83 + if s.plugins != nil {
  84 + f := s.plugins.GetAction(cmd)
  85 + if f != nil {
  86 + return f
  87 + }
  88 + }
  89 +
  90 + return s.Actions[cmd]
  91 +}
  92 +
  93 +func (s *Server) SetActions(mi map[interface{}]interface{}) {
  94 + s.Actions = mi
83 } 95 }
84 96
85 func (s *Server) GetConnManage() IConnManage { 97 func (s *Server) GetConnManage() IConnManage {
@@ -103,8 +115,10 @@ func (s *Server) SetTimerCallback(cb TimerCallback) { @@ -103,8 +115,10 @@ func (s *Server) SetTimerCallback(cb TimerCallback) {
103 } 115 }
104 116
105 func (s *Server) Start() error { 117 func (s *Server) Start() error {
106 - if err := s.plugins.LoadPlugin(); err != nil {  
107 - return err 118 + if s.plugins != nil {
  119 + if err := s.plugins.LoadPlugin(); err != nil {
  120 + return err
  121 + }
108 } 122 }
109 123
110 port := fmt.Sprintf(":%d", s.port) 124 port := fmt.Sprintf(":%d", s.port)
@@ -22,7 +22,7 @@ server_account: @@ -22,7 +22,7 @@ server_account:
22 ip: "192.168.0.206" 22 ip: "192.168.0.206"
23 port: 8858 23 port: 8858
24 pool_size: 1 24 pool_size: 1
25 - debugport: 6061 25 + debugport: 6062
26 mongo: 26 mongo:
27 <<: *default-mongo 27 <<: *default-mongo
28 dbname: "account" 28 dbname: "account"
@@ -33,7 +33,8 @@ server_game: @@ -33,7 +33,8 @@ server_game:
33 ip: "192.168.0.206" 33 ip: "192.168.0.206"
34 port: 8850 34 port: 8850
35 pool_size: 1 35 pool_size: 1
36 - plugin_path: "./bin/plugin.so" 36 + debugport: 6061
  37 + # plugin_path: "./bin/plugin.so"
37 mongo: 38 mongo:
38 <<: *default-mongo 39 <<: *default-mongo
39 dbname: "game" 40 dbname: "game"
tools/protostostruct.go
@@ -11,16 +11,17 @@ import ( @@ -11,16 +11,17 @@ import (
11 ) 11 )
12 12
13 var ( 13 var (
14 - ProtoCode = "syntax = \"proto3\";\noption go_package = \"./pb;pb\";\n\npackage protocode;\n\nenum ProtoCode\n{\n UNKNOWN = 0;\n %s\n}" 14 + ProtoCode = "syntax = \"proto3\";\noption go_package = \"../pb;pb\";\n\npackage protocode;\n\nenum ProtoCode\n{\n UNKNOWN = 0;\n %s\n}"
15 ProtoCodeLineReq = "\t%sReq = %d;\n" 15 ProtoCodeLineReq = "\t%sReq = %d;\n"
16 ProtoCodeLineRsp = "\t%sRsp = %d;\n" 16 ProtoCodeLineRsp = "\t%sRsp = %d;\n"
17 17
18 - GoProtoCodeStr = "package main\n\nimport (\n\t\"pro2d/pb\"\n\t\"pro2d/utils/logger\"\n)\n\nfunc GetActionMap() map[interface{}]interface{} {\n\tlogger.Debug(\"init protocode...\")\n\tam := make(map[interface{}]interface{})\n%s\n\treturn am\n}"  
19 - GoProtoCodeLine = "\tam[pb.ProtoCode_%sReq] = %sRpc\n" 18 + GoProtoCodeStr = "package action\n\nimport (\n\t\"pro2d/common/logger\"\n\t\"pro2d/pb\"\n)\n\nfunc GetActionMap() map[interface{}]interface{} {\n\tlogger.Debug(\"init protocode...\")\n\tam := make(map[interface{}]interface{})\n%s\n\treturn am\n}"
  19 +
  20 + GoProtoCodeLine = "\tam[uint32(pb.ProtoCode_%sReq)] = %sRpc\n"
20 ) 21 )
21 22
22 func ProtoToCode(readPath, filename string) (string, string) { 23 func ProtoToCode(readPath, filename string) (string, string) {
23 - protofile , err := os.Open(readPath+filename) 24 + protofile, err := os.Open(readPath + filename)
24 code := 0x000 25 code := 0x000
25 protoData := "" 26 protoData := ""
26 goProtoData := "" 27 goProtoData := ""
@@ -57,45 +58,44 @@ func ProtoToCode(readPath, filename string) (string, string) { @@ -57,45 +58,44 @@ func ProtoToCode(readPath, filename string) (string, string) {
57 for _, v := range lb { 58 for _, v := range lb {
58 n1 := bytes.Index(v, []byte("Req")) 59 n1 := bytes.Index(v, []byte("Req"))
59 n2 := bytes.Index(v, []byte("Rsp")) 60 n2 := bytes.Index(v, []byte("Rsp"))
60 - if n1 < 0 && n2 < 0 { 61 + if n1 < 0 && n2 < 0 {
61 continue 62 continue
62 } 63 }
63 if n1 >= 0 { 64 if n1 >= 0 {
64 code++ 65 code++
65 - protoData += fmt.Sprintf(ProtoCodeLineReq, v[:n1],code) 66 + protoData += fmt.Sprintf(ProtoCodeLineReq, v[:n1], code)
66 goProtoData += fmt.Sprintf(GoProtoCodeLine, v[:n1], v[:n1]) 67 goProtoData += fmt.Sprintf(GoProtoCodeLine, v[:n1], v[:n1])
67 } 68 }
68 if n2 >= 0 { 69 if n2 >= 0 {
69 code++ 70 code++
70 - protoData += fmt.Sprintf(ProtoCodeLineRsp, v[:n2],code) 71 + protoData += fmt.Sprintf(ProtoCodeLineRsp, v[:n2], code)
71 } 72 }
72 } 73 }
73 } 74 }
74 75
75 - return protoData ,goProtoData 76 + return protoData, goProtoData
76 } 77 }
77 78
78 -func ReadProtos(readPath, OutPath string ) error { 79 +func ReadProtos(readPath, OutPath string) error {
79 files, err := ioutil.ReadDir(readPath) 80 files, err := ioutil.ReadDir(readPath)
80 if err != nil { 81 if err != nil {
81 return fmt.Errorf("ReadExcel|ReadDir is err:%v", err) 82 return fmt.Errorf("ReadExcel|ReadDir is err:%v", err)
82 } 83 }
83 84
84 -  
85 protoData, goProtoData := "", "" 85 protoData, goProtoData := "", ""
86 for _, file := range files { 86 for _, file := range files {
87 - if path.Ext(file.Name()) != ".proto"{ 87 + if path.Ext(file.Name()) != ".proto" {
88 continue 88 continue
89 } 89 }
90 tprotoData, tgoProtoData := ProtoToCode(readPath, file.Name()) 90 tprotoData, tgoProtoData := ProtoToCode(readPath, file.Name())
91 if tprotoData == "" || tgoProtoData == "" { 91 if tprotoData == "" || tgoProtoData == "" {
92 - continue 92 + continue
93 } 93 }
94 protoData += tprotoData 94 protoData += tprotoData
95 goProtoData += tgoProtoData 95 goProtoData += tgoProtoData
96 96
97 } 97 }
98 - fw, err := os.OpenFile( OutPath+"protos/protocode.proto", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) 98 + fw, err := os.OpenFile(OutPath+"protos/protocode.proto", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
99 if err != nil { 99 if err != nil {
100 return fmt.Errorf("WriteNewFile|OpenFile is err:%v", err) 100 return fmt.Errorf("WriteNewFile|OpenFile is err:%v", err)
101 } 101 }
@@ -106,7 +106,7 @@ func ReadProtos(readPath, OutPath string ) error { @@ -106,7 +106,7 @@ func ReadProtos(readPath, OutPath string ) error {
106 return fmt.Errorf("WriteNewFile|Write is err:%v", err) 106 return fmt.Errorf("WriteNewFile|Write is err:%v", err)
107 } 107 }
108 108
109 - fw, err = os.OpenFile( OutPath+"cmd/gameserver/plugin/protocode.go", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) 109 + fw, err = os.OpenFile(OutPath+"cmd/gameserver/action/protocode.go", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
110 if err != nil { 110 if err != nil {
111 return fmt.Errorf("WriteNewFile|OpenFile is err:%v", err) 111 return fmt.Errorf("WriteNewFile|OpenFile is err:%v", err)
112 } 112 }