连接组件connection
connection连接组件是一个功能相对简单的组件,仅被前端服务器加载,为connectionService连接服务提供一个组件包装。
connection连接组件主要进行连接的统计,当连接组件接收到客户端连接请求时、客户端离线时、用户登录下线等情况都会向其汇报。
连接服务connectionService
获取连接服务
const connectionService = app.components.__connection__;
连接服务提供的方法
方法 | 描述 |
---|---|
addLoginedUser(uid, info) | 添加已登录的用户 |
removeLoginedUser(uid) | 删除已登录的用户 |
updateUserInfo(uid, info) | 更新用户信息 |
increaseConnectionCount() | 连接数量自增1 |
decreaseConnectionCount(uid) | 连接数量自减1,若传入uid则会删除用户。 |
getStaticstisInfo() | 获取连接统计信息 |
连接统计getStaticstisInfo
获取连接的统计信息
const connectionService = app.components.__connection__;
const data = connectionService .getStatisticsInfo();
console.log(data);
输出打印信息
{
serverId: 'connector-server-1',
totalConnCount: 0,
loginedCount: 0,
loginedList: []
}
getStaticstisInfo返回值信息
字段 | 描述 |
---|---|
serverId | 当前connector连接服务器的编号 |
totalConnCount | 连接数量 |
loginedCount | 已登录用户的数量 |
loginedList | 已登录用户列表 |
例如:获取在线人数可通过connection组件提供的getStaticsticInfo方法实现,在app.js中增加定时器获取当前在线数据。
$ vim game-server/app.js
//应用配置连接服务器
app.configure('production|development', 'connector', function(){
app.set('connectorConfig',
{
connector : pomelo.connectors.hybridconnector,
heartbeat : 3,
useDict : true,
useProtobuf : true
});
setInterval(()=>{
const stats = app.components.__connection__.getStatisticsInfo();
console.log("connection statistics info:", stats);
}, 5000);
});
监测维护pomelo-admin
pomelo-admin提供对游戏各个服务器的数据进行实时监测和汇报,比如CPU、内存、连接数等数据。可自定义游戏逻辑数据的监测,比如当前有多少用户在副本场景中,当前有多少用户在进行A任务,当前有哪些用户的账号状态错误等。
虽然可采用查询数据库和添加logger日志来统计和监测游戏逻辑数据,但却不能做到实时。比如场景A最大用户容量为200,当超过200个用户时需热扩展服务器,此时若通过人工查询可能已经为时已晚,实时监测可以非常迅速的通知运维人员当前数据库状态。
对于日常繁琐的查询除了使用数据库脚本外有可通过实时监测来获取数据。同时伴随的坏处是会消耗部分服务器性能,因此需要在各种条件之间平衡利弊后使用。
pomelo-admin是pomelo自带的组件无需安装,pomelo自身已经实现的监控只需在app.js启动脚本中配置添加即可。
可通过查看package-lock.json配置文件判断是否已经安装pomelo-admin组件
$ cat web-server/package-lock.json
开启系统默认的监控
$ vim game-server/app.js
//应用全局配置
app.configure("production|development", function(){
//开启系统监控 Linux环境有效
app.enable("systemMonitor");
});
开启系统默认监控后
if(app.enabled('systemMonitor')) {
if(os.platform() !== Constants.PLATFORM.WIN) {
app.registerAdmin(admin.modules.systemInfo);
app.registerAdmin(admin.modules.nodeInfo);
}
app.registerAdmin(admin.modules.monitorLog, {path: pathUtil.getLogPath(app.getBase())});
app.registerAdmin(admin.modules.scripts, {app:app, path: pathUtil.getScriptPath(app.getBase())});
if(os.platform() !== Constants.PLATFORM.WIN) {
app.registerAdmin(admin.modules.profiler);
}
}
自定义监控模块
$ game-server/apps/monitor/online.js
//自定义监控模块
let Module = function(opts){
console.log("online monitor constructor");
opts = opts||{};
//当前监控模块所监测的服务器实例
this.app = opts.app;
//获取数据的方式
// pomelo-admin提供两种方式一种是pull拉取,一种是push推送
// pull拉取表示master服务器会主动从各个游戏服务器上拉取所需的监控数据
// push推送表示游戏服务器向master服务器推送监控数据
this.type = opts.type || "pull";
//每次push或pull的时间间隔
this.interval = opts.interval || 5;
};
// 监控模块标识
// 用于唯一标识监控模块,非常重要。
// 如果要向该模块获取和发送数据都需要依靠这个ID作为参数
// 如果需要让外部程序获取该模块的监控数据也必须依靠此参数
Module.moduleId = "online";
// 采用pull拉取 当接收到master主服务器拉通知时回调
// 采用push推送 每次到达interval间隔时间时回调
Module.prototype.monitorHandler = function(agent, msg){
console.log("online monitor handler");
//获取连接组件服务
const connectionService = this.app.components.__connection__;
if(!connectionService){
console.log("not support connection: %j", agent.id);
return;
}
//代理通知连接统计信息
const info = connectionService.getStatisticsInfo();
//通知admin的消息给master服务器
agent.notify(Module.moduleId, info);
};
// 采用pull拉取 每次到达pull拉取时间间隔时会被调用
// 采用push推送 当接收到游戏服务器push推送数据回调
Module.prototype.masterHandler = function(agent, msg){
console.log("online master handler", msg, Module.moduleId);
//若无消息则通知所有的monitor监视器去获取数据
if(!msg){
//通知指定类型的监听器获取获取数据
const type = "connector";
const list = agent.typeMap[type];
if(!list || list.length===0){
agent.notifyByType(type, Module.moduleId);
}else{
//通知所有监视器去获取数据
agent.notifyAll(Module.moduleId);
}
return;
}
//从monitor监视器中收集数据
let data = agent.get(Module.moduleId);
if(!data){
data = {};
agent.set(Module.moduleId, data);
}
data[msg.serverId] = msg;
};
//当第三方程序调用时 获取监控数据接口时回调
Module.prototype.clientHandler = function(agent, msg, cb){
console.log("online client handler");
if(!!cb && typeof cb==="function"){
const param = agent.get(Module.moduleId) || {};
//处理客户端请求直接返回数据并缓存到master服务器
cb(null, param);
}
};
//导出模块
module.exports.moduleId = Module.moduleId;
module.exports = function(opts){
return new Module(opts);
};
在app.js
中配置自定义监控模块
$ vim game-server/app.js
//应用全局配置 针对所有服务器
app.configure("production|development", function(){
//开启系统监控 Linux环境有效
app.enable("systemMonitor");
//配置自定义监控:运行自定义统计脚本收集服务器运行数据,为服务器注册自定义监控模块。
if(typeof app.registerAdmin === "function"){
//将监控在线用户模块注册给所有服务器
app.registerAdmin("online", require("./app/monitor/online"), {app:app});
}
});
若出现错误unknown module
需检查moduleId是否为空或undefined的情况
[2019-11-30 16:55:05.649] [ERROR] pomelo-admin - [ConsoleService] unknown module: undefined.
[2019-11-30 16:55:05.649] [ERROR] pomelo-admin - [MonitorAgent] notify should not have a callback.
运行后会出现一个错误信息,是否是因为统计在线运行时connector服务器还未初始化造成的。
[2019-11-30 18:23:24.452] [ERROR] pomelo-admin - [MasterAgent] fail to notifyByType for unknown server type:connector