首先介紹下背景:咱們公司的產品,會直接部署在甲方,由於甲方比較多,且他們包含個性化需求較多,因此,每一個甲方能夠理解爲咱們產品的一條git分支。 因爲甲方的機器環境、網絡環境各不相同,時常出現一些運行時的問題,因而,我設計了這套簡易的智能監控系統,用來實時監測各個甲方接口狀況。css
該套方案衍生的適用範圍以下:前端
單擊節點能夠再次模擬該次節點,在瀏覽器中顯出出參。java
雙擊某個節點能夠複製該節點出參。mysql
由於咱們產品已經完成了先後端分離(前幾篇文章有介紹),因此,咱們重點監控接口。git
個人方案是:sql
這裏由於每一個公司的各個接口,入參、出參加密方式不通,並且身份認證也是不相同,咱們會在獨立寫一個方法來實現加解密,因此,我只介紹未加密、已解密的參數;關於出參下文以{"code":"200","data":null,"message"::"success"}爲例,身份認證我以簡單token進行講解本文。docker
某個獲取新聞列表接口:數據庫
http://*.com/v1/news?token=2c789e34dc81d79feba6a005ad63902b
複製代碼
解密後的出參:json
{"code":"200","data":[{"id":"1","title":"這是一條假新聞","url":"http://"},{"id":"2","title":"這是一條假新聞","url":"http://"}],"message"::"success"}
複製代碼
相對url:後端
v1/news
複製代碼
請求類型:
get
複製代碼
body主體:
token={token}
複製代碼
corn表達式:
0 0/3 * * * ?(每隔3分鐘執行一次)
複製代碼
host(必填)
http://a.com
複製代碼
參數(list)
token 2c789e34dc81d79feba6a005ad63902b
複製代碼
host(必填)
http://b.com
複製代碼
參數(list)
token 4297f44b13955235245b2497399d7a93
複製代碼
好比在新聞獲取接口綁定A、B環境,則每隔3分鐘請求一輪接口。
A環境host+相對url=
http://a.com/v1/news
複製代碼
請求類型:
get
複製代碼
body主體:
token=2c789e34dc81d79feba6a005ad63902b
複製代碼
B環境host+相對url=
http://b.com/v1/news
複製代碼
請求類型:
get
複製代碼
body主體:
token=4297f44b13955235245b2497399d7a93
複製代碼
咱們框架自己並不會關心有幾個參數,只會遍歷接口中帶佔位符的,把佔位符中字段替換爲環境裏的參數list中變量。 好比一個body爲token=2c789e34dc81d79feba6a005ad63902b&type=1&mobile=2
則添加接口時,body填入:
token={token}&type={type}&mobile={mobile} 其中佔位符能夠隨便起名字
複製代碼
配置環境時參數(list)以下:
k | v |
---|---|
token | 2c789e34dc81d79feba6a005ad63902b |
type | 1 |
mobile | 2 |
參數和佔位符裏的對應,和url其餘變量不相關。
對於不一樣的狀態碼,咱們有不一樣的顏色,對應本身產品中錯誤碼選擇合適顏色便可,錯誤等級越高,顏色越顯眼。
包含兩種不一樣的緯度,能夠直接點擊進入,查看A環境全部接口的監控狀況,或者查看接口1全部環境的監控狀況。
環境編輯界面:
任務編輯界面:
既然是週期性監控,天然少不了使用cron表達式,咱們又是java項目,因此採用了quartz框架。
public class QuartzSchedule {
private static SchedulerFactory sf = new StdSchedulerFactory();
private static Scheduler sched;
final static String groupName = "task";
public static void init() throws IOException, SchedulerException {
//查詢全部須要執行的任務和項目列表
// 使用類加載器,加載mybatis的配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 構造sqlSession工廠
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
MprojectTaskDao mprojectTaskDao = sqlSession.getMapper(MprojectTaskDao.class);
sched = sf.getScheduler();
//只查詢全部在m_project_include表裏面的任務
List<MprojectTask> mprojectTaskList = mprojectTaskDao.findList();
for (MprojectTask mprojectTask : mprojectTaskList) {
startJob(mprojectTask);
}
}
public static void stopTask(MprojectTask mprojectTask) {
TriggerKey triggerKey = TriggerKey.triggerKey(mprojectTask.getId(), groupName);
try {
sched.pauseTrigger(triggerKey);// 中止觸發器
sched.unscheduleJob(triggerKey);// 移除觸發器
sched.deleteJob(JobKey.jobKey(mprojectTask.getId(), groupName));// 刪除任務
} catch (Exception e) {
e.printStackTrace();
}
}
/*
中止和暫停都可使用
*/
public static void startTask(MprojectTask mprojectTask) {
//不管是否關閉,先關閉任務再開啓。
stopTask(mprojectTask);
startJob(mprojectTask);
}
private static void startJob(MprojectTask mprojectTask) {
try {
JobDetail jobDetail = JobBuilder.newJob(TaskQuzrtzJob.class).withIdentity(mprojectTask.getId(), groupName).build();
// 觸發器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 觸發器名,觸發器組
triggerBuilder.withIdentity(mprojectTask.getId(), groupName);
triggerBuilder.startNow();
// 觸發器時間設定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(mprojectTask.getCron()));
// 建立Trigger對象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 調度容器設置JobDetail和Trigger
sched.scheduleJob(jobDetail, trigger);
// 啓動
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
複製代碼
public class TaskQuzrtzJob implements Job {
public TaskQuzrtzJob() throws IOException {
}
//JobExecutionContext context傳遞參數值
public void execute(JobExecutionContext context) {
//經過context獲得該任務的全部環境
//遍歷全部環境
//拼湊出請求地址
//使用封裝的框架加密發送請求
//得出出參解密後的結果
//與上次進行比對,不相同則標記,入節點表
//入記錄表
}
}
複製代碼
由於咱們這個監控每一個接口(任務)有多個環境,假設100個接口100個環境,每3分鐘監控一次,則天天記錄量爲
100 * 100 * 20 * 24=4800 000條記錄,這個記錄比較驚人,因此咱們分了兩張表,一張表只記錄記錄,另一張表記錄變動,展現節點的時候只查詢變動表,可解決性能上的問題。
前端採用css來畫圓和顏色
round {
border-radius: 50%;
text-align: center;
width: 25px;
height: 25px;
line-height: 25px;
}
.on {
border: 1px solid #7CBA23;
}
複製代碼
線條使用line畫線
line {
border-bottom: 1px solid gainsboro;
height: 2px;
width: 20px;
}
複製代碼
總體採用angular js渲染列表
咱們使用mysql數據庫,mybatis框架鏈接。
咱們會對每一個接口和狀態碼進行關聯,異常時,發送郵件,測試人員覈實問題後反饋給開發,開發解決後,錄入解決方案,以便下次查詢。
這個平臺已經試行1個多月了,整體知足咱們的需求,以往,咱們跑測試腳本,每每不能實時監測服務器健康狀態,如今,任何一個環境有問題,咱們都實時,而且能夠統計出某個環境從什麼時間到什麼時間接口處於異常。
這套平臺,功能很少,但極大的簡化了咱們的對環境穩定性的評估,也收集了大量的數據信息便於後期統計分析。 其次,該方案稍做改造,可運用於多種監測場景中。
將來,我會融入一些智能化的分析,好比下文是某次郵件提醒的內容:
(智能監控) 發現《A客戶私有環境》中 【獲取新聞列表】 接口異常,異常代碼爲102; 出參爲{"data":null,"message":"成功","state":102}
歷史解決方案有:
該環境接口在5分鐘前是正常的,出參爲{"data":null,"message":"暫無數據","state":200}
發現有另外2個其它環境異常,分別爲XXX、YYY環境。但異常狀態和該校不類似,排除接口war包bug的緣由。
因爲《XXX環境》其餘接口在5分鐘內某次監控均爲異常,因此(智能監控) 已自主調用容器自愈模塊,目前已恢復服務,本次收集數據耗時5分鐘,分析問題耗時100毫秒,自愈耗時60秒,該環境中斷服務時間爲6分鐘,本月中斷服務總時長爲15分鐘,高可用性爲98.33%。
over