watchdog.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. var logger = require('pomelo-logger').getLogger('pomelo', __filename);
  2. var utils = require('../util/utils');
  3. var Constants = require('../util/constants');
  4. var countDownLatch = require('../util/countDownLatch');
  5. var EventEmitter = require('events').EventEmitter;
  6. var util = require('util');
  7. var Watchdog = function(app, service) {
  8. EventEmitter.call(this);
  9. this.app = app;
  10. this.service = service;
  11. this.isStarted = false;
  12. this.count = utils.size(app.getServersFromConfig());
  13. this.servers = {};
  14. this.listeners = {};
  15. };
  16. util.inherits(Watchdog, EventEmitter);
  17. module.exports = Watchdog;
  18. Watchdog.prototype.addServer = function(server) {
  19. if(!server) {
  20. return;
  21. }
  22. this.servers[server.id] = server;
  23. this.notify({action: 'addServer', server: server});
  24. };
  25. Watchdog.prototype.removeServer = function(id) {
  26. if(!id) {
  27. return;
  28. }
  29. this.unsubscribe(id);
  30. delete this.servers[id];
  31. this.notify({action: 'removeServer', id: id});
  32. };
  33. Watchdog.prototype.reconnectServer = function(server) {
  34. var self = this;
  35. if(!server) {
  36. return;
  37. }
  38. if(!this.servers[server.id]) {
  39. this.servers[server.id] = server;
  40. }
  41. //replace server in reconnect server
  42. this.notifyById(server.id, {action: 'replaceServer', servers: self.servers});
  43. // notify other server to add server
  44. this.notify({action: 'addServer', server: server});
  45. // add server in listener
  46. this.subscribe(server.id);
  47. };
  48. Watchdog.prototype.subscribe = function(id) {
  49. this.listeners[id] = 1;
  50. };
  51. Watchdog.prototype.unsubscribe = function(id) {
  52. delete this.listeners[id];
  53. };
  54. Watchdog.prototype.query = function() {
  55. return this.servers;
  56. };
  57. Watchdog.prototype.record = function(id) {
  58. if(!this.isStarted && --this.count < 0) {
  59. var usedTime = Date.now() - this.app.startTime;
  60. logger.warn('all servers startup in %s ms', usedTime);
  61. this.notify({action: 'startOver'});
  62. this.isStarted = true;
  63. }
  64. };
  65. Watchdog.prototype.notifyById = function(id, msg) {
  66. this.service.agent.request(id, Constants.KEYWORDS.MONITOR_WATCHER, msg, function(signal) {
  67. if(signal !== Constants.SIGNAL.OK) {
  68. logger.error('master watchdog fail to notify to monitor, id: %s, msg: %j', id, msg);
  69. } else {
  70. logger.debug('master watchdog notify to monitor success, id: %s, msg: %j', id, msg);
  71. }
  72. });
  73. };
  74. Watchdog.prototype.notify = function(msg) {
  75. var listeners = this.listeners;
  76. var success = true;
  77. var fails = [];
  78. var timeouts = [];
  79. var requests = {};
  80. var count = utils.size(listeners);
  81. if(count === 0) {
  82. logger.warn('master watchdog listeners is none, msg: %j', msg);
  83. return;
  84. }
  85. var latch = countDownLatch.createCountDownLatch(count, {timeout: Constants.TIME.TIME_WAIT_COUNTDOWN}, function(isTimeout) {
  86. if(!!isTimeout) {
  87. for(var key in requests) {
  88. if(!requests[key]) {
  89. timeouts.push(key);
  90. }
  91. }
  92. logger.error('master watchdog request timeout message: %j, timeouts: %j, fails: %j', msg, timeouts, fails);
  93. }
  94. if(!success) {
  95. logger.error('master watchdog request fail message: %j, fails: %j', msg, fails);
  96. }
  97. });
  98. var moduleRequest = function(self, id) {
  99. return (function() {
  100. self.service.agent.request(id, Constants.KEYWORDS.MONITOR_WATCHER, msg, function(signal) {
  101. if(signal !== Constants.SIGNAL.OK) {
  102. fails.push(id);
  103. success = false;
  104. }
  105. requests[id] = 1;
  106. latch.done();
  107. });
  108. })();
  109. };
  110. for(var id in listeners) {
  111. requests[id] = 0;
  112. moduleRequest(this, id);
  113. }
  114. };