pomelo组就之server组件分析

在前面的一篇文章中知道了connector组件的作用,而且知道了,connector接收到数据之后,会调用server组件的handle方法来处理这些数据,那么这篇文章我们就来看看server组件究竟是怎么进行工作的吧。。。

首先我们来看看server组件的包装器的定义:

/**
 * Component for server starup.
 */
var Server = require('../server/server');

/**
 * Component factory function
 *
 * @param {Object} app  current application context
 * @return {Object}     component instance
 */
module.exports = function(app) {
  return new Component(app);
};

/**
 * Server component class
 *
 * @param {Object} app  current application context
 */
var Component = function(app) {
  this.server = Server.create(app);  //用于创建真正的server组件
};

Component.prototype.name = '__server__';

/**
 * Component lifecycle callback
 *
 * @param {Function} cb
 * @return {Void}
 */
Component.prototype.start = function(cb) {   //启动
  this.server.start();
  process.nextTick(cb);
};

/**
 * Component lifecycle function
 *
 * @param {Boolean}  force whether stop the component immediately
 * @param {Function}  cb
 * @return {Void}
 */
Component.prototype.stop = function(force, cb) {
  this.server.stop();
  process.nextTick(cb);
};

/**
 * Proxy server.handle
 */
Component.prototype.handle = function(msg, session, cb) {  //调用server的hanlder来处理接收到的数据,用cb来处理返回的数据
  this.server.handle(msg, session, cb);
};
这里无非就是对内部的server进行了一个代理,尤其是handle方法,直接就是调用的内部server的handle方法进行处 理的,好吧,那么我们接下来来看看这个内部的server究竟是怎么定义的吧,首先来看看它的构造函数:
module.exports.create = function(app) {
  return new Server(app);
};
//这个可以看成是server的构造函数吧
var Server = function (app) {
  this.app = app;
  this.filterService = null;
  this.handlerService = null;
  this.state = ST_INITED;
};

var pro = Server.prototype;
这里应该是没有什么重要的信息,无非就是设置了一些属性,其实干货比较多的过程在于start部分,来看看先:
pro.start = function() {
  if(this.state > ST_INITED) {
    return;
  }

  this.filterService = initFilter(this.app);  //初始化filter函数
  this.handlerService = initHandler(this.app);  //初始化handler
  this.state = ST_STARTED;
};
这里代码通过名字就知道要干一些什么事情了,初始化了filter,然后还初始化了handler,这里就是暂时不看filter部分的内容吧,来看看这个handler是怎么进行初始化的。。。
//创建handlerservice
var initHandler = function(app) {
  return new HandlerService(app, loadHandlers(app));
};
好吧,其实这里创建的是一个handlerservice,在创建它的同时,还要进行handler的load,来看看handler是怎么load的吧:
 //为当前的server加载它的handler
var loadHandlers = function(app) {
  var p = pathUtil.getHandlerPath(app.getBase(), app.getServerType());  //用于根据server的类型来加载相应的handler
  if(p) {
    return Loader.load(p, app);  //加载handler
  }
};
这个就是handler的load过程,这里就不细看了,我们已经知道pomelo可以自己定义服务器类型,例如我们例子中用的chat,那么当启动相应的服务器的时候,就会从相应的文件夹里面去载入文件,从而完成handler的load过程,其实这个样子看起来很像ruby on rails的方式。。。里面load的过程,其实就是一些读取文件夹,读文件等,就不细究了。。那么接下来来看看handlerservice是怎么定义的吧,先来看看它的构造函数:
var Service = function(app, handlers) {
  this.app = app;
  this.handlers = handlers || {};
};
很简单吧,无非就是保存一下app和handlers。。。


好了,那么接下来来看看server组件处理数据的流程吧,先来看最外面的server包装器它的handle方法:

Component.prototype.handle = function(msg, session, cb) {  //调用server的hanlder来处理接收到的数据,用cb来处理返回的数据
  this.server.handle(msg, session, cb);
};
没什么意思,不过这里需要说明的是,cb回调函数是在connector里面传过来的,handler处理完成后,可以调用cb将数据返回给客户端。。。。。以后会看到的。。

好了,接下来来深入内部看看吧:

 //调用handler来处理信息
pro.handle = function(msg, session, cb) {
  if(this.state !== ST_STARTED) {
    cb(new Error('server not started'));
    return;
  }

  var routeRecord = parseRoute(msg.route);  //用于解析route参数
  if(!routeRecord) {
    cb(new Error('meet unknown route message %j', msg.route));
    return;
  }

  if(this.app.getServerType() !== routeRecord.serverType) {  //判断route的路径是否是到当前的服务器
    doForward(this.app, msg, session, routeRecord, cb);  //如果类型不符的话,那么用符合的服务器来处理
  } else {
    doHandle(this, msg, session, routeRecord, cb);  //符合,那么用当前的handler来处理
  }
};
首先是解析发送过来的数据的route信息,包含了server的类型,所访问的handler的类型,方法的名字等等。。然后再判断当前服务器类型与要访问的服务器类型是否相同,如果不相同的话,那么需要进行远程调用,将这些参数传给合适的服务器进行处理,这里就不细看,以后会讲的,就先看看相同的情况下把,会调用当前服务器的handler进行处理:
//这里调用用户定义的handler来处理数据
var doHandle = function(server, msg, session, routeRecord, cb) {
  var originMsg = msg;
  msg = msg.body || {};
  msg.__route__ = originMsg.route;  //相当于是保存route数据

  var self = server;

  var handle = function(err, resp) {
    if(err) {
      // error from before filter
      handleError(self, err, msg, session, resp, function(err, resp) {
        response(self, err, msg, session, resp, cb);
      });
      return;
    }
//调用handler进行处理
    self.handlerService.handle(routeRecord, msg, session, function(err, resp) {
      if(err) {
        //error from handler
        handleError(self, err, msg, session, resp, function(err, resp) {
          response(self, err, msg, session, resp, cb);  
        });
        return;
      }

      response(self, err, msg, session, resp, cb);  //相当于是向客户端返回信息
    });
  };  //end of handle

  beforeFilter(server, msg, session, handle);
};

在调用之前,会先执行filter函数,在调用之后也要执行filter函数,这里其实是调用内部的handlerservice进行处理这些数据的,那么来看看handlerservice的handle方法吧:
Service.prototype.handle = function(routeRecord, msg, session, cb){
  // the request should be processed by current server
  var handler = getHandler(this.handlers, routeRecord);  //根据handdler的名字获取handler
  if(!handler) {
    logger.error('[handleManager]: fail to find handler for %j', msg.__route__);
    cb(new Error('fail to find handler for ' + msg.__route__));
    return;
  }
  var start = Date.now();

  handler[routeRecord.method](msg, session, function(err,resp){  //相当于是根据method的名字来执行相应的方法,传入的额函数就是handler里的next参数,用于将返回的数据发送给客户端
    var log = {
      route : msg.__route__,
      args : msg,
      time : utils.format(new Date(start)),
      timeUsed : new Date() - start
    };
    forward_logger.info(JSON.stringify(log));
    cb(err,resp);
  });
  return;
};
感觉这里已经很简单了吧,无非就是根据前面的一些route的信息,找到相应的方法,然后由其来处理,然后再将返回的信息发送给客户端。。。


好了,这里整个server组件的工作流程也就比较的清晰了,用一张图来总结吧:








(1)首先connector组件接收到数据

(2)调用server组件来处理数据,server组件根据route信息通过handleservice找到相应的handler以及对应的方法来处理

(3)再通过connector组件将返回的数据发送给客户端。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值