網易開源遊戲伺服器框架pomelo0.9版釋出

美人遲暮發表於2017-06-05

pomelo 0.9版於2月26日釋出,以下是該版本的新特性。

pomelo rpc支援zeromq通訊

在pomelo 0.9中提供了基於zmq的rpc呼叫,開發者可以根據需要選擇原有的pomelo-rpc或者pomelo-rpc-zeromq。基於zeromq和原有的pomelo-rpc的效能對比測試結果可以參考:

具體使用方法:

  1. 安裝zeromq
  2. 在app.js中進行配置,具體配置如下所示:
var zmq = require(`pomelo-rpc-zeromq`);
app.configure(`production|development`, function() {
app.set(`proxyConfig`, {
rpcClient: zmq.client
});
app.set(`remoteConfig`, {
rpcServer: zmq.server
});
});

具體使用示例可以參考 chatofpomelo zmq分支

pomelo-rpc-zeromq效能測試報告與原有的pomelo-rpc的效能測試報告可以參考。

pomelo命令列改進

根據網友的建議,在pomelo 0.9版本中增加了重啟的命令和伺服器單獨啟動的命令;具體命令如下:

pomelo start -t [server type] 啟動某型別的伺服器,如果需要分開啟動不同型別伺服器時候使用,首先必須啟動master伺服器,例如:

pomelo start -t master
pomelo start -t connector

pomelo start -i [server id] 啟動具體某個伺服器,同上首先需要啟動master,master伺服器無需提供具體id, 例如:


pomelo start -i master
pomelo start -i chat-server-1

pomelo restart 重啟除了master以為的其它伺服器,可能會出現重啟失敗的情況。

pomelo restart -t [server type] 重啟某型別的伺服器,不包括master伺服器

pomelo restart -i [server id] 重啟具體某個伺服器,不包括master伺服器

pomelo restart -t connector
pomelo restart -i chat-server-1

pomelo rpc增加回撥超時機制

針對之前網友提出的rpc回撥函式積壓問題, 在新版本的pomelo-rpc中通過增加了回撥函式的超時機制解決,rpc客戶端在記錄應用層的回撥函式的同時新增對應的定時器,如果rpc服務端收到對應的訊息則將定時器清除,如果定時器超時則將對應的回撥函式清除。定時器的超時時間開發者可以進行設定,預設是10s, 具體使用如下:


app.set(`proxyConfig`, {
timeout: 1000 * 20
});


## pomelo支援連線黑名單機制

在新版本的pomelo中連線伺服器支援靜態或者動態新增ip黑名單功能,服務端可以在連線伺服器中增加黑名單對攻擊的ip進行遮蔽。

### 原理

connector每接受一個連線都會丟擲一個連線事件, 這個事件中含有該連線的客戶端IP. connector會捕獲該連線事件, 並呼叫使用者傳入的獲取IP黑名單的函式, 如果該客戶端IP在黑名單中, 則立刻將對應的socket斷開. 以此來實現連線伺服器的黑名單過濾功能.

### 使用方法

#### 靜態新增黑名單

使用時只需要向在connector的connectionConfig配置中傳入一個獲取IP黑名單的函式即可, 這個函式需要接受一個回撥函式作為其引數, 該回撥函式形如`function(err, list) {...}`. 在獲取IP黑名單的函式內, 拿到IP黑名單時(該黑名單應為一維`JS Array`), 以類似於`cb(null, self.list)`的形式呼叫IP過濾回撥函式,具體使用方法如下:

./game-server/app/util/blackList.js
… …
var self = this;
self.blackList = [`192.168.100.1`, `192.168.100.2`];
module.exports.blackListFun = function(cb) {
cb(null, self.blackList);
};
… …

./game-server/app.js
var blackList = require(`./app/util/blackList`);
… …
app.configure(`production|development`, function() {
… …
app.set(`connectorConfig`, {
blacklistFun: blackList.blackListFun
});
… …
}


#### 動態新增黑名單

動態新增黑名單可以通過pomelo-cli完成,其中執行輸入具體ip或者正規表示式,具體命令如下:

blacklist 192.168.100.1
blacklist (([01]?d?d|2[0-4]d|25[0-5]).){3}([01]?d?d|2[0-4]d|25[0-5])


## channel 序列化介面

在新版本的pomelo中提供channel的序列化介面,開發者可以通過實現該介面將系統中建立的channel進行儲存;同時當伺服器重新啟動後,系統會將之前儲存的channel恢復到系統中。開發者需要實現如下四個介面:

#### add(key, value, cb)
add key value pairs

#### remove(key, value, cb)
remove key value pairs

#### load(key, cb)
load all values

#### removeAll(key, cb)
remove all values

具體的使用方法如下所示:

var store = require(`./store`);
app.set(`channelConfig`, {
store : store,
prefix : `pomelo`
});

//store.js
var redis = require(`redis`);
var StoreManager = function() {
this.redis = redis.createClient(6379, `127.0.0.1`, {});
};
module.exports = new StoreManager();
StoreManager.prototype.add = function(key, value, cb) {
this.redis.sadd(key, value, function(err) {

cb(err);

});
};

StoreManager.prototype.remove = function(key, value, cb) {
this.redis.srem(key, value, function(err) {
cb(err);
});
};

StoreManager.prototype.load = function(key, cb) {
this.redis.smembers(key, function(err, list) {
cb(err, list);
});
};

StoreManager.prototype.removeAll = function(key, cb) {
this.redis.del(key, function(err) {

cb(err);

});
};

## 熱重啟的部分支援

在新版本的pomelo中對rpc模組進行了改進,在rpc服務端斷開連線後,上層應用的rpc請求會在rpc客戶端快取;當rpc服務端恢復後,再次發起rpc請求時,會把之前的rpc請求一起發到rpc服務端。

在系統中如果是rpc單向依賴,也就是說系統中只有A類伺服器傳送rpc請求到B類伺服器,沒有B類伺服器傳送rpc請求到A類伺服器,同時B類伺服器是沒有任何狀態資訊和例項化資訊,這樣B類伺服器就可以在pomelo 0.9版本中重啟,且不會影響系統的正常執行。

具體可以參考[chatofpomelo](https://github.com/NetEase/chatofpomelo) store分支。在chatofpomelo中只有connector到chat伺服器的單向rpc依賴,對於chat伺服器有channel的例項存在,所以使用channel序列化介面將channel儲存,所以需要使用到redis。

操作步驟如下:

1. 在不同的命令列介面分別執行 pomelo start -t master, pomelo start -t connector, pomelo start -t gate, pomelo start -t chat;
2. 開啟web伺服器,執行chatofpomelo;
3. 關閉chat伺服器,並重新啟動;

## pomelo支援decodeIO protobuf

在pomelo 0.9版本中提供了對decodeIO的protobuf的支援,對於decodeIO的protobuf的介紹可以參考[decodeIO-protobufjs](https://github.com/dcodeIO/ProtoBuf.js).

###使用方法

####客戶端

使用最新的pomelo-jsclient-websocket, 同時在客戶端新增命名為pomelo-decodeIO-protobuf的component,並將其掛載到window物件下。對應的component.js如下所示:

{
“name”: “boot”,
“description”: “Main app boot component”,
“dependencies”: {

"component/emitter":"master",
"NetEase/pomelo-protocol": "master",
"pomelonode/pomelo-decodeIO-protobuf": "master",
"pomelonode/pomelo-jsclient-websocket": "master",
"component/jquery": "*"

},
“scripts”: [“index.js”]
}


對應的index.js如下所示:

var Emitter = require(`emitter`);
window.EventEmitter = Emitter;

var protocol = require(`pomelo-protocol`);
window.Protocol = protocol;

var protobuf = require(`pomelo-decodeIO-protobuf`);
window.decodeIO_protobuf = protobuf;

var pomelo = require(`pomelo-jsclient-websocket`);
window.pomelo = pomelo;

var jquery = require(`jquery`);
window.$ = jquery;


####服務端

在服務端需要使用pomelo-protobuf-plugin,並在app.js中使用對應的外掛,具體配置如下:

app.configure(`production|development`, function() {
app.use(protobuf, {
protobuf: {
}
});
});


####注意事項

pomelo原有的protobuf和decodeIO-protobufjs不能同時使用,即不能同時使用pomelo-protobuf-plugin外掛並在前端伺服器開啟useProtobuf。


考慮到與原有的protobuf保持一致,pomelo 0.9版本中支援的decodeIO-protobuf同樣採用serverProtos.json和clientProtos.json,不支援decodeIO-protobufjs中的*.proto格式,對於*.proto格式可以採用decodeIO-protobufjs提供的命令列工具轉換成json格式。


具體的使用示例可以參考[lordofpomelo](https://github.com/NetEase/lordofpomelo/tree/decodeIO_protobuf) decodeIO-protobuf分支。

## pomelo websocket支援自動重連

在pomelo 0.9版本中,pomelo-jsclient-websocket 支援自動重連。重連發生在連線斷開後的5s後,在重連失敗後下次重連的時間將是上次重連時間的2倍;所以重連時間依次為5s, 10s,20s,依次類推。預設最大的重連次數是10次,該引數可以在連線初始化過程中進行配置。

//設定客戶端重連

pomelo.init({
host: 127.0.0.1,
port: 3050,
reconnect: true
}, function() {

});

//設定客戶端重連最大次數

pomelo.init({
host: 127.0.0.1,
port: 3050,
reconnect: true,
maxReconnectAttempts: 20
}, function() {

});


相關文章