Commit 29b6d86fdeb4f3f61c1d0a0bcd8e562ea27d9442
1 parent
69d286a7
update plugin doc
Showing
8 changed files
with
105 additions
and
29 deletions
 
Show diff stats
Makefile
| 1 | 1 | all: gen game | 
| 2 | 2 | IMGTIME := $(shell date "+%G%m%d_%H%M%S") | 
| 3 | -pname = plugin-$(IMGTIME).so | |
| 4 | - | |
| 3 | +pname = plugin-$(IMGTIME) | |
| 4 | +race = -race | |
| 5 | +#DEBUG = -gcflags "-l -N" | |
| 6 | +DEBUG= | |
| 5 | 7 | gen: | 
| 6 | 8 | protoc -I./protos --go_out=./protos --go-grpc_out=./protos ./protos/*proto | 
| 7 | 9 | protoc-go-inject-tag -input=./pb/*.pb.go | 
| ... | ... | @@ -9,20 +11,20 @@ gen: | 
| 9 | 11 | test: | 
| 10 | 12 | go run cmd/test/client.go | 
| 11 | 13 | http: | 
| 12 | - go run -race cmd/httpserver/http.go cmd/httpserver/AccountAction.go | |
| 14 | + go run $(race) cmd/httpserver/http.go cmd/httpserver/AccountAction.go | |
| 13 | 15 | |
| 14 | 16 | game: | 
| 15 | 17 | go run -race cmd/gameserver/*.go | 
| 16 | 18 | build: | 
| 17 | - go build -race -o bin/account cmd/http.go | |
| 18 | - go build -race -o bin/game cmd/gameserver/*.go | |
| 19 | - go build -race -o bin/test cmd/test/client.go | |
| 19 | + go build $(race) -o bin/account cmd/http.go | |
| 20 | + go build $(race) -o bin/game cmd/gameserver/*.go | |
| 21 | + go build $(race) -o bin/test cmd/test/client.go | |
| 20 | 22 | regame:plugin | 
| 21 | 23 | lsof -i:8850 | grep "agent" | grep -v grep | awk '{print $$2}' | xargs -I {} kill -USR1 {} | 
| 22 | 24 | |
| 23 | 25 | plugin: | 
| 24 | 26 | cd bin && rm -rf ./plugin*.so && cd - | 
| 25 | - go build -race --buildmode=plugin -o bin/$(pname) cmd/gameserver/plugin/*.go | |
| 26 | - cd bin && ln -s $(pname) plugin.so && cd - | |
| 27 | + go build $(race) $(DEBUG) --buildmode=plugin -o bin/$(pname).so cmd/gameserver/plugin/*.go #--ldflags="-pluginpath=$(pname)" | |
| 28 | + cd bin && ln -s $(pname).so plugin.so && cd - | |
| 27 | 29 | |
| 28 | 30 | .PHONY: all build protos test cert plugin | 
| 29 | 31 | \ No newline at end of file | ... | ... | 
README.md
| ... | ... | @@ -7,16 +7,15 @@ | 
| 7 | 7 | * 日志 | 
| 8 | 8 | * 集群 | 
| 9 | 9 | * 分布式 | 
| 10 | +* 热更 | |
| 10 | 11 | |
| 11 | 12 | |
| 12 | -技术点 | |
| 13 | -* golang 热更 | |
| 14 | - | |
| 15 | -组件名字 | |
| 13 | +技术点: | |
| 16 | 14 | * mongo | 
| 15 | +* redis | |
| 17 | 16 | * etcd | 
| 18 | 17 | * proto + models 查询 | 
| 19 | -* redis | |
| 18 | +* golang plugin | |
| 20 | 19 | |
| 21 | 20 | ## 目录结构 | 
| 22 | 21 | ```text | 
| ... | ... | @@ -60,17 +59,20 @@ $ go get google.golang.org/grpc/cmd/protoc-gen-go-grpc | 
| 60 | 59 | $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc | 
| 61 | 60 | ``` | 
| 62 | 61 | ## 文档 | 
| 63 | -[证书制作](doc/cret.md) | |
| 64 | -[包组成结构](doc/proto.md) | |
| 65 | - | |
| 62 | +* [证书制作](doc/cret.md) | |
| 63 | +* [包组成结构](doc/proto.md) | |
| 64 | +* [go plugin热更的使用](doc/plugin.md) | |
| 66 | 65 | |
| 67 | 66 | ## Usage | 
| 68 | -编译 & 运行 游戏服 & 登录服务 | |
| 67 | +### 编译 & 运行 && 游戏服 & 登录服务 | |
| 69 | 68 | ```shell | 
| 70 | -$ make account | |
| 71 | 69 | $ make game | 
| 70 | +$ make account | |
| 72 | 71 | ``` | 
| 72 | + | |
| 73 | 73 | 测试 | 
| 74 | 74 | ```shell | 
| 75 | 75 | $ make test | 
| 76 | -``` | |
| 77 | 76 | \ No newline at end of file | 
| 77 | +``` | |
| 78 | + | |
| 79 | +### | |
| 78 | 80 | \ No newline at end of file | ... | ... | 
cmd/gameserver/plugin/plugin.go
| ... | ... | @@ -15,13 +15,13 @@ func init() { | 
| 15 | 15 | func GetActionMap() map[interface{}]interface{} { | 
| 16 | 16 | logger.Debug("init protocode...") | 
| 17 | 17 | am := make(map[interface{}]interface{}) | 
| 18 | - am[uint32(pb.ProtoCode_LoginReq)] = LoginRpc | |
| 18 | + am[uint32(pb.ProtoCode_LoginReq)] = "LoginRpc" | |
| 19 | 19 | |
| 20 | 20 | return am | 
| 21 | 21 | } | 
| 22 | 22 | |
| 23 | 23 | func LoginRpc(msg components.IMessage) (int32, interface{}) { | 
| 24 | - //logger.Debug("11111111cmd: %v, msg: %s", msg.GetHeader().GetMsgID(), msg.GetData()) | |
| 24 | + logger.Debug("11111111cmd: %v, msg: %s", msg.GetHeader().GetMsgID(), msg.GetData()) | |
| 25 | 25 | req := pb.LoginReq{} | 
| 26 | 26 | if err := proto.Unmarshal(msg.GetData(), &req); err != nil { | 
| 27 | 27 | logger.Error("loginRpc err: %v", err) | ... | ... | 
| ... | ... | @@ -0,0 +1,22 @@ | 
| 1 | +package main | |
| 2 | + | |
| 3 | +import ( | |
| 4 | + "plugin" | |
| 5 | + "pro2d/common/logger" | |
| 6 | + "testing" | |
| 7 | +) | |
| 8 | + | |
| 9 | +func TestGetActionMap(t *testing.T) { | |
| 10 | + p, err := plugin.Open("./bin/plugin.so") | |
| 11 | + if err != nil { | |
| 12 | + logger.Error("open error: ", err) | |
| 13 | + return | |
| 14 | + } | |
| 15 | + logger.Debug("open success") | |
| 16 | + symbol, err := p.Lookup("GetActionMap") | |
| 17 | + if err != nil { | |
| 18 | + logger.Error(err) | |
| 19 | + return | |
| 20 | + } | |
| 21 | + logger.Debug("%v", symbol) | |
| 22 | +} | ... | ... | 
common/components/plugin.go
| ... | ... | @@ -59,9 +59,12 @@ func (p *Plugin) GetAction(cmd uint32) interface{} { | 
| 59 | 59 | } | 
| 60 | 60 | |
| 61 | 61 | func (p *Plugin) SetActions(am map[interface{}]interface{}) { | 
| 62 | + p.Actions.Range(func(key, value interface{}) bool { | |
| 63 | + p.Actions.Delete(key.(uint32)) | |
| 64 | + return true | |
| 65 | + }) | |
| 62 | 66 | for k, v := range am { | 
| 63 | 67 | cmd := k.(uint32) | 
| 64 | - p.Actions.Delete(cmd) | |
| 65 | 68 | p.Actions.Store(cmd, v) | 
| 66 | 69 | } | 
| 67 | 70 | } | ... | ... | 
common/components/server.go
| ... | ... | @@ -115,12 +115,6 @@ func (s *Server) SetTimerCallback(cb TimerCallback) { | 
| 115 | 115 | } | 
| 116 | 116 | |
| 117 | 117 | func (s *Server) Start() error { | 
| 118 | - if s.plugins != nil { | |
| 119 | - if err := s.plugins.LoadPlugin(); err != nil { | |
| 120 | - return err | |
| 121 | - } | |
| 122 | - } | |
| 123 | - | |
| 124 | 118 | port := fmt.Sprintf(":%d", s.port) | 
| 125 | 119 | l, err := net.Listen("tcp", port) | 
| 126 | 120 | if err != nil { | ... | ... | 
conf/conf.yaml
| ... | ... | @@ -0,0 +1,53 @@ | 
| 1 | + | |
| 2 | +## 热更golang有状态服务 | |
| 3 | +1. golang是有状态的 | |
| 4 | +2. 数据+逻辑代码分离 | |
| 5 | +3. 主要热更的是逻辑代码 | |
| 6 | + | |
| 7 | + | |
| 8 | +## 启用插件 | |
| 9 | +1. 启用插件, 配置文件 conf.yaml, 填入插件.so文件的路径 | |
| 10 | +``` | |
| 11 | +server_game: | |
| 12 | + plugin_path: "./bin/plugin.so" | |
| 13 | + mongo: | |
| 14 | + <<: *default-mongo | |
| 15 | + dbname: "game" | |
| 16 | +``` | |
| 17 | +2. 编译程序 & 插件. | |
| 18 | +```shell | |
| 19 | +$ make plugin | |
| 20 | +``` | |
| 21 | +* 程序和插件需要同一个golang的环境。 | |
| 22 | +* golang对同一个插件只能加载一次。可以修改.so文件名字 + 软连接的方式来处理 | |
| 23 | + | |
| 24 | + | |
| 25 | +## 写插件代码 | |
| 26 | +插件中的代码主要是对线上程序 `协议=>逻辑` 的热更. | |
| 27 | + | |
| 28 | +比如我们要修改游戏服务协议号为`1`的逻辑。 则在`cmd/gameserver/plugin/plugin.go`文件中修改。 | |
| 29 | +1. 在函数`GetActionMap`中增加一行 | |
| 30 | +``` | |
| 31 | +am[uint32(1)] = HotRpc | |
| 32 | +``` | |
| 33 | +2. 增加函数`HotRpc` | |
| 34 | +``` | |
| 35 | +func HotRpc(msg components.IMessage) (int32, interface{}) { | |
| 36 | +} | |
| 37 | +``` | |
| 38 | + | |
| 39 | +3. 编译插件 & 可以参考Makefile:plugin | |
| 40 | +```Makefile | |
| 41 | +IMGTIME := $(shell date "+%G%m%d_%H%M%S") | |
| 42 | +pname = plugin-$(IMGTIME).so | |
| 43 | +plugin: | |
| 44 | + cd bin && rm -rf ./plugin*.so && cd - | |
| 45 | + go build -race --buildmode=plugin -o bin/$(pname) cmd/gameserver/plugin/*.go | |
| 46 | + cd bin && ln -s $(pname) plugin.so && cd - | |
| 47 | +``` | |
| 48 | + | |
| 49 | +4. 把插件放到指定位置, 并给游戏服发送热更指令。可以参考Makefile:regame | |
| 50 | +```Makefile | |
| 51 | +regame:plugin | |
| 52 | + lsof -i:8850 | grep "agent" | grep -v grep | awk '{print $$2}' | xargs -I {} kill -USR1 {} | |
| 53 | +``` | |
| 0 | 54 | \ No newline at end of file | ... | ... |