Commit 69d286a7c94629a66d3065140ade7d58ae77166b

Authored by zhangqijia
1 parent cd2f96ab

fix: 插件用来做部分热更

1. 调整逻辑代码位置
2. 插件里做部分逻辑热更
Makefile
... ... @@ -11,7 +11,7 @@ test:
11 11 http:
12 12 go run -race cmd/httpserver/http.go cmd/httpserver/AccountAction.go
13 13  
14   -game:plugin
  14 +game:
15 15 go run -race cmd/gameserver/*.go
16 16 build:
17 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 3 import (
4 4 "github.com/golang/protobuf/proto"
... ... @@ -9,12 +9,12 @@ import (
9 9 "pro2d/pb"
10 10 )
11 11  
12   -func HeartRpc(msg components.IMessage) (int32, interface{}) {
  12 +func HeartRpc(msg components.IMessage) (int32, interface{}) {
13 13 //msg.Conn.SetLastHeartCheckTime()
14 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 18 req := pb.CreateReq{}
19 19 if err := proto.Unmarshal(msg.GetData(), &req); err != nil {
20 20 logger.Error("CreateRpc err: %v", err)
... ... @@ -27,14 +27,14 @@ func CreateRpc(msg components.IMessage) (int32, interface{}) {
27 27  
28 28 roleId := common.SnowFlack.NextValStr()
29 29 role = models.NewRole(roleId)
30   - if err := role.Create(); err != nil {
  30 + if err := role.Create(); err != nil {
31 31 logger.Error("CreateRpc role create err: %v", err)
32 32 return 3, nil
33 33 }
34 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 38 //logger.Debug("11111111cmd: %v, msg: %s", msg.GetHeader().GetMsgID(), msg.GetData())
39 39 req := pb.LoginReq{}
40 40 if err := proto.Unmarshal(msg.GetData(), &req); err != nil {
... ... @@ -49,9 +49,9 @@ func LoginRpc(msg components.IMessage) (int32, interface{}) {
49 49 role.SetProperty("Device", req.Device)
50 50  
51 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 55 Equips: []*pb.Equipment{role.Equip.Equip},
56 56 }
57   -}
58 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 3 import (
4 4 "pro2d/common/logger"
... ... @@ -8,9 +8,9 @@ import (
8 8 func GetActionMap() map[interface{}]interface{} {
9 9 logger.Debug("init protocode...")
10 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 15 return am
16   -}
17 16 \ No newline at end of file
  17 +}
... ...
cmd/gameserver/game.go
... ... @@ -3,6 +3,7 @@ package main
3 3 import (
4 4 "fmt"
5 5 _ "net/http/pprof"
  6 + "pro2d/cmd/gameserver/action"
6 7 "pro2d/common"
7 8 "pro2d/common/components"
8 9 "pro2d/common/db"
... ... @@ -29,6 +30,7 @@ func NewGameServer(sconf *common.SConf) (*GameServer, error) {
29 30 }
30 31  
31 32 iserver := components.NewServer(sconf.Port, options...)
  33 + iserver.SetActions(action.GetActionMap())
32 34 s.IServer = iserver
33 35  
34 36 //mgo init
... ...
cmd/gameserver/plugin/plugin.go 0 → 100644
... ... @@ -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 @@
  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 62 GetSplitter() ISplitter
63 63 GetPlugin() IPlugin
64 64 GetAction(uint32) interface{}
  65 + SetActions(map[interface{}]interface{})
65 66 GetConnManage() IConnManage
66 67  
67 68 SetConnectionCallback(ConnectionCallback)
... ... @@ -76,7 +77,7 @@ type (
76 77 Stop()
77 78 BindHandler(interface{})
78 79 }
79   - ActionHandler func(conn IConnection, msg IMessage) (int32, interface{})
  80 + ActionHandler func(msg IMessage) (int32, interface{})
80 81 //用于热更逻辑的插件接口
81 82 IPlugin interface {
82 83 LoadPlugin() error
... ...
common/components/plugin.go
... ... @@ -3,23 +3,24 @@ package components
3 3 import (
4 4 "plugin"
5 5 "pro2d/common/logger"
6   - "pro2d/pb"
7 6 "sync"
8 7 )
9 8  
10   -type ActionMap sync.Map//map[pb.ProtoCode]ActionHandler
11   -
12 9 type PluginOption func(*Plugin)
13 10  
14 11 type Plugin struct {
15 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 21 p := &Plugin{
22 22 pluginPath: path,
  23 + Actions: sync.Map{},
23 24 }
24 25 for _, option := range options {
25 26 option(p)
... ... @@ -41,7 +42,7 @@ func (p *Plugin) LoadPlugin() error {
41 42 }
42 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 46 logger.Debug("func LoadPlugin GetActionMap success...")
46 47 p.SetActions(x())
47 48 }
... ... @@ -50,7 +51,7 @@ func (p *Plugin) LoadPlugin() error {
50 51 }
51 52  
52 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 55 if !ok {
55 56 return nil
56 57 }
... ... @@ -59,7 +60,7 @@ func (p *Plugin) GetAction(cmd uint32) interface{} {
59 60  
60 61 func (p *Plugin) SetActions(am map[interface{}]interface{}) {
61 62 for k, v := range am {
62   - cmd := k.(pb.ProtoCode)
  63 + cmd := k.(uint32)
63 64 p.Actions.Delete(cmd)
64 65 p.Actions.Store(cmd, v)
65 66 }
... ...
common/components/server.go
... ... @@ -55,7 +55,8 @@ type Server struct {
55 55 timerCallback TimerCallback
56 56  
57 57 port int
58   - connManage *ConnManage
  58 + connManage IConnManage
  59 + Actions map[interface{}]interface{}
59 60 }
60 61  
61 62 func NewServer(port int, options ...ServerOption) IServer {
... ... @@ -79,7 +80,18 @@ func (s *Server) GetPlugin() IPlugin {
79 80 }
80 81  
81 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 97 func (s *Server) GetConnManage() IConnManage {
... ... @@ -103,8 +115,10 @@ func (s *Server) SetTimerCallback(cb TimerCallback) {
103 115 }
104 116  
105 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 124 port := fmt.Sprintf(":%d", s.port)
... ...
conf/conf.yaml
... ... @@ -22,7 +22,7 @@ server_account:
22 22 ip: "192.168.0.206"
23 23 port: 8858
24 24 pool_size: 1
25   - debugport: 6061
  25 + debugport: 6062
26 26 mongo:
27 27 <<: *default-mongo
28 28 dbname: "account"
... ... @@ -33,7 +33,8 @@ server_game:
33 33 ip: "192.168.0.206"
34 34 port: 8850
35 35 pool_size: 1
36   - plugin_path: "./bin/plugin.so"
  36 + debugport: 6061
  37 + # plugin_path: "./bin/plugin.so"
37 38 mongo:
38 39 <<: *default-mongo
39 40 dbname: "game"
... ...
tools/protostostruct.go
... ... @@ -11,16 +11,17 @@ import (
11 11 )
12 12  
13 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 15 ProtoCodeLineReq = "\t%sReq = %d;\n"
16 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 23 func ProtoToCode(readPath, filename string) (string, string) {
23   - protofile , err := os.Open(readPath+filename)
  24 + protofile, err := os.Open(readPath + filename)
24 25 code := 0x000
25 26 protoData := ""
26 27 goProtoData := ""
... ... @@ -57,45 +58,44 @@ func ProtoToCode(readPath, filename string) (string, string) {
57 58 for _, v := range lb {
58 59 n1 := bytes.Index(v, []byte("Req"))
59 60 n2 := bytes.Index(v, []byte("Rsp"))
60   - if n1 < 0 && n2 < 0 {
  61 + if n1 < 0 && n2 < 0 {
61 62 continue
62 63 }
63 64 if n1 >= 0 {
64 65 code++
65   - protoData += fmt.Sprintf(ProtoCodeLineReq, v[:n1],code)
  66 + protoData += fmt.Sprintf(ProtoCodeLineReq, v[:n1], code)
66 67 goProtoData += fmt.Sprintf(GoProtoCodeLine, v[:n1], v[:n1])
67 68 }
68 69 if n2 >= 0 {
69 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 80 files, err := ioutil.ReadDir(readPath)
80 81 if err != nil {
81 82 return fmt.Errorf("ReadExcel|ReadDir is err:%v", err)
82 83 }
83 84  
84   -
85 85 protoData, goProtoData := "", ""
86 86 for _, file := range files {
87   - if path.Ext(file.Name()) != ".proto"{
  87 + if path.Ext(file.Name()) != ".proto" {
88 88 continue
89 89 }
90 90 tprotoData, tgoProtoData := ProtoToCode(readPath, file.Name())
91 91 if tprotoData == "" || tgoProtoData == "" {
92   - continue
  92 + continue
93 93 }
94 94 protoData += tprotoData
95 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 99 if err != nil {
100 100 return fmt.Errorf("WriteNewFile|OpenFile is err:%v", err)
101 101 }
... ... @@ -106,7 +106,7 @@ func ReadProtos(readPath, OutPath string ) error {
106 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 110 if err != nil {
111 111 return fmt.Errorf("WriteNewFile|OpenFile is err:%v", err)
112 112 }
... ...