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

来源:互联网 发布:带网络机顶盒的电视机 编辑:程序博客网 时间:2024/05/22 13:14

        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.jsMonitorAgent.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);};//实际上就是调用subscribevar 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
原创粉丝点击