频道组件
具体文件是:pomelo/lib/common/components/channel.js
组件加载后写入app中 app.channelService === app.components.__channel__
可以设置频道(channel),把用户放入频道不同进程的玩家可以添加到相同的频道下
支持广播全部玩家,发送给指定的玩家,广播同一频道下的玩家
在发送消息时会根据用户连接的serverId进行普通调用或者RPC调用:
var sendMessage = function(serverId) {
return (function() {
if(serverId === app.serverId) {
self.channelRemote[method](route, msg, opts, genCB());
} else {
app.rpcInvoke(serverId, {namespace: namespace, service: service,
method: method, args: [route, msg, opts]}, genCB(serverId));
}
}());
};
RPC字典组件
具体文件是:pomelo/lib/common/components/dictionary.js
组件加载后写入app中 app.components.__dictionary__
实际上是把rpc调用的字串进行简化。
默认会读取app/servers/xx/handler/下的所有js模块并生成一个rpc的数组
例如:[serverName.handlerName.methodName, …],然后数组排序(这样保证所有进程字典一致性)
然后根据排序把rpc的字串转为下标(数字)的形势。
如果服务器设置使用字典后,那么消息流中会用数字把对应的rpc字串替换掉。减少消息的冗余
支持在config/dictionary.json配置额外的rpc
protobuf组件
具体文件是:pomelo/lib/common/components/protobuf.js
组件加载后写入app中 app.components.__protobuf__
采用的是pomelo-protobuf
配置文件:
config/serverProtos.json
config/clientProtos.json
提供了序列化、反序列化、protos文件修改动态重载功能
客户端连接管理session
具体文件是:
pomelo/lib/common/components/session.js
pomelo/lib/common/components/backendSession.js
组件加载后写入app中:
app.sessionService == app.components.__session__
app.backendSessionService == app.localSessionService' == app.components.__backendSession__
对于每一条client和server的连接都会维护有一份session
在pomelo中有3种session,分别是session frontendSession backendSession
官方wiki
消息发送组件
具体文件是:pomelo/lib/common/components/pushScheduler.js
组件加载后写入app中:app.components.__pushScheduler__
对广播进行过滤以及发送,可以自定义全局的处理函数,也可以针对频道定义过滤
发消息接口:
PushScheduler.prototype.schedule = function(reqId, route, msg, recvs, opts, cb) {
var self = this;
if(self.isSelectable) {
if(typeof self.selector === 'function') {
self.selector(reqId, route, msg, recvs, opts, function(id) {
if(self.scheduler[id] && typeof self.scheduler[id].schedule === 'function') {
self.scheduler[id].schedule(reqId, route, msg, recvs, opts, cb);
} else {
logger.error('invalid pushScheduler id, id: %j', id);
}
});
} else {
logger.error('the selector for pushScheduler is not a function, selector: %j', self.selector);
}
} else {
if (typeof self.scheduler.schedule === 'function') {
self.scheduler.schedule(reqId, route, msg, recvs, opts, cb);
} else {
logger.error('the scheduler does not have a schedule function, scheduler: %j', self.scheduler);
}
}
};
可以看到支持外部传入selector,以外部啊传入scheduler模块。
默认的话,scheduler采用的是 ./pushSchedulers/direct.js
var doBroadcast = function(self, msg, opts) {
var channelService = self.app.get('channelService');
var sessionService = self.app.get('sessionService');
if(opts.binded) {
sessionService.forEachBindedSession(function(session) {
if(channelService.broadcastFilter &&
!channelService.broadcastFilter(session, msg, opts.filterParam)) {
return;
}
sessionService.sendMessageByUid(session.uid, msg);
});
} else {
sessionService.forEachSession(function(session) {
if(channelService.broadcastFilter &&
!channelService.broadcastFilter(session, msg, opts.filterParam)) {
return;
}
sessionService.sendMessage(session.id, msg);
});
}
};
在这里可以看到,广播消息是,会进行一次频道过滤,然后再把消息发送给客户端。
而这个频道过滤是在频道组件
中的
实际是创建频道组建时外部传入的过滤器。