pomelo服务器群消息变更的获知

        Pomelo中是master服务器首先启动,然后在启动其他服务器的。那么当一个服务器启动时,它是如何获知此时整个服务器集群整体信息的?当服务器启动之后,后续服务器的添加或删除的信息是如何传递给该服务器的呢?

        首先,当master服务器启动时,会创建masterAgent

Pomelo-admin中的consoleService.js中:

var ConsoleService = function(opts) {
	EventEmitter.call(this);
	this.port = opts.port;
	this.env = opts.env;
	this.values = {};
	this.master = opts.master;

	this.modules = {};
	this.commands = {
		'list': listCommand,
		'enable': enableCommand,
		'disable': disableCommand
	};

	if (this.master) {
		this.authUser = opts.authUser || utils.defaultAuthUser;
		this.authServer = opts.authServer || utils.defaultAuthServerMaster;
		this.agent = new MasterAgent(this, opts);
	} else {
		this.type = opts.type;
		this.id = opts.id;
		this.host = opts.host;
		this.authServer = opts.authServer || utils.defaultAuthServerMonitor;
		this.agent = new MonitorAgent({
			consoleService: this,
			id: this.id,
			type: this.type,
			info: opts.info
		});
	}
};

masterAgent管理了所有和monitorAgent的连接。Master服务器会监听所有的master端口。同时会启动waterdog模块(masterwatcher.jswatchdog.js)

其他非master服务器启动时,会创建monitorConsoleService,并启动MonitorAgent且调用其connect函数,在连接成功之后会发送register消息。

masterAgent收到register消息时,会调用doAuthServer,验证成功。之后会给MonitorAgent客户端发送register成功的消息,同时也触发了masterAgentregister事件。

MasterAgent.js

var doAuthServer = function(msg, socket, self, cb) {
  var authServer = self.consoleService.authServer;
  var env = self.consoleService.env;
  authServer(msg, env, function(status) {
    if (status !== 'ok') {
      socket.emit('register', {
        code: protocol.PRO_FAIL,
        msg: 'server auth failed'
      });
      cb(new Error('server auth failed'));
      return;
    }

    var record = addConnection(self, msg.id, msg.serverType, msg.pid, msg.info, socket);

    socket.emit('register', {
      code: protocol.PRO_OK,
      msg: 'ok'
    });
    msg.info.pid = msg.pid;
    self.emit('register', msg.info);
    cb(null);
  });
};

consoleService

exportEvent(self, self.agent, 'register');

var exportEvent = function(outer, inner, event) {
	inner.on(event, function() {
		var args = Array.prototype.slice.call(arguments, 0);
		args.unshift(event);
		outer.emit.apply(outer, args);
	});
};// outer是MasterConsoleService  inner是masterAgent event是register
最终触发了MasterConsoleService的register事件:

而在masterwatcher.js中 ,代码对register进行了register事件监听:

this.service.on('register', onServerAdd.bind(null,this));

var onServerAdd = function(module, record) {
  logger.debug('masterwatcher receive add server event, with server: %j', record);
  if(!record || record.type === 'client' || !record.serverType) {
    return;
  }
  module.watchdog.addServer(record);//调用watchdog去添加服务器
};

最终还是调用了watchdog.jsnotify方法,向那些向master订阅过的monitor发送有新成员加入的消息。

MonitorAgent收到register成功,设置标志位,并且触发当初ConsoleServicestart函数传入的回调函数,这时候,会启动模块__watchdog__(monitorwatcher.js),非中心服务器,会调用subscribeRequest(this,this.service.agent, this.id, cb);向中心服务器获取已经注册的服务器服务器列表。即向mastermonitor发送subscribe请求以monitor消息的形式。

Monitorwatcher.js

var subscribeRequest = function(self, agent, id, cb) {
  var msg = {action: 'subscribe', id: id};
  agent.request(Constants.KEYWORDS.MASTER_WATCHER, msg, function(err, servers) {
    if(err) {
      logger.error('subscribeRequest request to master with error: %j', err.stack);
      utils.invokeCallback(cb, err);
    }
    var res = [];
    for(var id in servers) {
      res.push(servers[id]);
    }
    addServers(self, res);
    utils.invokeCallback(cb);
  });
};
  self.app.addServers(servers);
};

MasterAgent收到subscribe请求后,调用masterwatchermasterHandler方法即__watchdog__masterHandler函数进行处理订阅信息,把客户端加入订阅列表中,当有新的服务器加入的时候,会进行通知。并把当前所有服务器列表,传入回调函数,通过socket.emit('monitor', resp)函数,把所有服务器,通知给订阅服务器。

Monitorwatcher.js

var subscribeRequest = function(self, agent, id, cb) {
  var msg = {action: 'subscribe', id: id};
  agent.request(Constants.KEYWORDS.MASTER_WATCHER, msg, function(err, servers) {
    if(err) {
      logger.error('subscribeRequest request to master with error: %j', err.stack);
      utils.invokeCallback(cb, err);
    }
    var res = [];
    for(var id in servers) {
      res.push(servers[id]);
    }
    addServers(self, res);
    utils.invokeCallback(cb);
  });
};

Monitoragent.js
MonitorAgent.prototype.request = function(moduleId, msg, cb) {
  if (this.state !== ST_REGISTERED) {
    logger.error('agent can not request now, state:' + this.state);
    return;
  }
  var reqId = this.reqId++;
  this.callbacks[reqId] = cb;
  this.socket.emit('monitor', protocol.composeRequest(reqId, moduleId, msg));
};

服务器这边使用masterHandler进行处理:

MasterAgent.js
    socket.on('monitor', function(msg) {
      if (!registered) {
        // not register yet, ignore any message
        // kick connections
        socket.disconnect();
        return;
      }

      if (type === TYPE_CLIENT) {
        logger.error('invalid message to monitor, but current connect type is client.');
        return;
      }

      msg = protocol.parse(msg);
      if (msg.respId) {
        // a response from monitor
        var cb = self.callbacks[msg.respId];
        if (!cb) {
          logger.warn('unknown resp id:' + msg.respId);
          return;
        }
        delete self.callbacks[msg.respId];
        utils.invokeCallback(cb, msg.error, msg.body);
        return;
      }

      // a request or a notify from monitor
      self.consoleService.execute(msg.moduleId, 'masterHandler', msg.body, function(err, res) {
        if (protocol.isRequest(msg)) {
          var resp = protocol.composeResponse(msg, err, res);
          if (resp) {
            socket.emit('monitor', resp);
          }
        } else {
          //notify should not have a callback
          logger.warn('notify should not have a callback.');
        }
      });
  }); // end of on 'monitor'
  


Module.prototype.masterHandler = function(agent, msg, cb) {
  if(!msg) {
    logger.warn('masterwatcher receive empty message.');
    return;
  }
  var func = masterMethods[msg.action];
  if(!func) {
    logger.info('masterwatcher unknown action: %j', msg.action);
    return;
  }
  func(this, agent, msg, cb);
};

//实际上就是调用subscribe
var subscribe = function(module, agent, msg, cb) {
  if(!msg) {
    utils.invokeCallback(cb, new Error('masterwatcher subscribe empty message.'));
    return;
  }

  module.watchdog.subscribe(msg.id);
  utils.invokeCallback(cb, null, module.watchdog.query());
};

MonitorAgent收到monitor消息处理代码如下:

 this.socket.on('monitor', function(msg) {
    if (self.state !== ST_REGISTERED) {
      return;
    }

    msg = protocol.parse(msg);

    if (msg.command) {
      // a command from master
      self.consoleService.command(msg.command, msg.moduleId, msg.body, function(err, res) {
        //notify should not have a callback
      });
    } else {
      if (msg.respId) {
        // a response from monitor
        var cb = self.callbacks[msg.respId];
        if (!cb) {
          logger.warn('unknown resp id:' + msg.respId);
          return;
        }
        delete self.callbacks[msg.respId];
        utils.invokeCallback(cb, msg.error, msg.body);
        return;
      }

      // request from master
      self.consoleService.execute(msg.moduleId, 'monitorHandler', msg.body, function(err, res) {
        if (protocol.isRequest(msg)) {
          var resp = protocol.composeResponse(msg, err, res);
          if (resp) {
            self.socket.emit('monitor', resp);
          }
        } else {
          //notify should not have a callback
          logger.error('notify should not have a callback.');
        }
      });
    }
  });
就是调用:
Module.prototype.monitorHandler = function(agent, msg, cb) {
  if(!msg || !msg.action) {
    return;
  }
  var func = monitorMethods[msg.action];
  if(!func) {
    logger.info('monitorwatcher unknown action: %j', msg.action);
    return;
  }
  func(this, agent, msg, cb);
};
也就是
var subscribeRequest = function(self, agent, id, cb) {
  var msg = {action: 'subscribe', id: id};
  agent.request(Constants.KEYWORDS.MASTER_WATCHER, msg, function(err, servers) {
    if(err) {
      logger.error('subscribeRequest request to master with error: %j', err.stack);
      utils.invokeCallback(cb, err);
    }
    var res = [];
    for(var id in servers) {
      res.push(servers[id]);
    }
    addServers(self, res);
    utils.invokeCallback(cb);
  });
};

MonitorAgent收到monitor消息的时候,根据respidcallbacks中获取回调函数,即当初请求订阅时候传入的回调函数,在subscribeRequest中,回调函数调用addServers,通过appaddServers函数,把获取的服务器列表存入serverTypeMaps中,同时app会发送ADD_SERVERS消息,在组件proxy中会触发addServers函数,生成对每个服务器远程调用的代理。生成代理的时候,要求服务器要配置端口port,否则无法调用rpc

 

这里面,官方的wikimaster方和monitor方 双方都有watchdog模块。仔细看看源码发现:master方的watchdog模块是由masterWatcher.js和watcherdog.js两个文件实现,而monitor则是由monitorWatcher.js实现,它没有watcherdog.js文件。

        最后用张图来总结上述过程:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值