Like Share Discussion Bookmark Smile

J.J. Huang   2020-02-14   Node.js   瀏覽次數:

Node.js | 監控並透過Tomcat Manager重啟服務

前言

此解決方法絕對不是最好或最正確的,純粹就是利用Node.js寫點爬蟲小工具來做處理。
如有更好的方法也請多多賜教!謝謝。

而且這問題我還跑到Node.js 中文論壇裡面去發問,在還沒人回應的狀況,自己就解了。論壇文章

問題說明

因公司內部Tomcat application有時會與ActiveMQ斷開,造成服務無法正常取得queues進行處理。

註:至於與ActiveMQ斷開的Exception,已經進行分析並處理了。

監控思維

主要使用puppeteercheerio模組製作爬蟲:

  • 爬取ActiveMQ Manage Queues頁面的Consumers數量進行監控。

  • 如發生異常。

  • 爬取Tomcat Manager頁面分析,並針對需要Reload的服務按鈕,加上Class,便於執行Click的動作。

  • 如有發生重啟。

  • 使用Line Bot發送訊息警示相關群組進行了解並觀察。

特別說明:

  • 為什麼不用request模組,針對Tomcat Manager的按鈕URL進行求請就好?

    • 因為有使用CSRF進行驗證,每次新的requestCSRF_NONCE都不一樣;所以使用puppeteer模擬瀏覽器操作。
      1
      /manager/html/reload?path=/&org.apache.catalina.filters.CSRF_NONCE=8F55096A1FEC8ADDA677B75A78A4DD7E
  • 為什麼要在Tomcat Manager上面新增Class

    • 因為是針對特定服務進行重啟。
  • 為什麼不改Tomcat Managerhtml就好?

    • 因為Tomcat Manager的頁面是Java裡面去Build出來的。
    • 我真的有去改Tomcat src並且重新產.jar去運行,是可行的!只是太不實際了。

程式碼

該程式碼是小弟撰寫的,網路似乎沒有該類型的爬蟲腳本,請支持原創,謝謝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
const puppeteer = require('puppeteer');
const request = require("request");
const cheerio = require("cheerio");
const querystring = require('querystring');

const activeMQ_URL = 'http://admin:admin@127.0.0.1:8161/admin/queues.jsp'; //ActiveMQ URL
const queuesName = 'XXXXXX'; // ActiveMQ Queue Name
const queuesConsumersNum = 2; // ActiveMQ qurue consumer check number

const tomcatManageURL = 'https://admin:admin@127.0.0.1/manager'; // Tomcat manager URL
const tomcatApplicationName = 'XXXXX'; // Tomcat application name

const checkApplication = function() {
request({
url: activeMQ_URL,
method: "GET"
}, function(error, response, body) {
if (error || !body) {
return;
}

const $ = cheerio.load(body);
const result = [];
const table_tr = $("#queues tbody tr");
for (let i = 1; i < table_tr.length; i++) {
const table_td = table_tr.eq(i).find('td');
if ($(table_td[0]).text().indexOf(queuesName) != -1) {
if ($(table_td[2]).text() < queuesConsumersNum) {
sendLineNotify(tomcatApplicationName + '服務異常自動重啟開始');
reloadApplication();
} else {
console.log('Nothing to do')
console.log('End Check ' + tomcatApplicationName + ' service status.');
}
}
}
});
};


const reloadApplication = function() {
(async () => {
console.log('Start Reload ' + tomcatApplicationName + ' Application.');
const browser = await puppeteer.launch();
const page = await browser.newPage();
let status = true;
await page.goto(tomcatManageURL);

await page.evaluate(x => {
let elements = document.getElementsByClassName('inline');
for (var element of elements)
if (element.action.indexOf('/' + x) != -1 && element.action.indexOf('stop') != -1) {
element.children[0].children[0].classList.add(x + '_Stop');
}
}, tomcatApplicationName);

try {
await page.click('.' + tomcatApplicationName + '_Stop');
} catch (e) {
// sendLineNotify(tomcatApplicationName + '服務停止失敗');
console.log('No Stop btn');
}

await page.evaluate(x => {
let elements = document.getElementsByClassName('inline');
for (var element of elements)
if (element.action.indexOf('/' + x) != -1 && element.action.indexOf('start') != -1) {
element.children[0].children[0].classList.add(x + '_Start');
}
}, tomcatApplicationName);

try {
await page.click('.' + tomcatApplicationName + '_Start');
} catch (e) {
// sendLineNotify(tomcatApplicationName + '服務啟動失敗');
status = false;
console.log('No Start btn');
}
if(status){
sendLineNotify(tomcatApplicationName + '服務異常自動重啟成功');
} else {
sendLineNotify(tomcatApplicationName + '服務異常自動重啟失敗');
}

console.log('End Reload ' + tomcatApplicationName + ' Application.');
await browser.close();
console.log('End Check ' + tomcatApplicationName + ' service status.');
})();
};

const sendLineNotify = function(msg) {
var form = {
message: msg,
};

var formData = querystring.stringify(form);
var contentLength = formData.length;

request({
headers: {
'Authorization': 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // Line Notify Token
'Content-Type': 'application/x-www-form-urlencoded'
},
uri: 'https://notify-api.line.me/api/notify',
body: formData,
method: 'POST'
}, function(err, res, body) {
console.log(tomcatApplicationName + '重啟Line通知狀態:' + body);
});
};

// Main
console.log('Start Check ' + tomcatApplicationName + ' service status');
checkApplication();