pomelo源码解析之组件解析(三)

频道组件

具体文件是: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);
    });
  }
};

在这里可以看到,广播消息是,会进行一次频道过滤,然后再把消息发送给客户端。
而这个频道过滤是在频道组件中的
实际是创建频道组建时外部传入的过滤器。

猜你喜欢

转载自blog.csdn.net/qq_37543025/article/details/85939373