最近這段時間在強化日志系統(tǒng)自身的穩(wěn)定性和可靠性,一個穩(wěn)定可靠的系統(tǒng)離不開監(jiān)控,我們這里談及的監(jiān)控除了服務是否存活還有這些組件的核心metrics采集與抓取,為此我們將這些任務做成了定時任務來執(zhí)行。由于大致的思路以及設計已經(jīng)成型,所以今天來分享一下日志系統(tǒng)在定時任務這塊的選型與設計。
從我之前分享的文章中不難看出我們?nèi)罩鞠到y(tǒng)的各個組件的選型:
這也是很多互聯(lián)網(wǎng)日志解決方案的通用選型。但是,我們在調研這些組件自身提供的監(jiān)控方案以及他們支持的第三方監(jiān)控工具時,卻得到了不一致的結果:
從上面的結果來看,自身具備的監(jiān)控能力以及跟第三方的監(jiān)控系統(tǒng)的集成能力參差不齊。這顯然不符合我們的期望,我們的幾個關注點:
總結一下,如上的這些組件在被監(jiān)控能力上雖然各有差異,不過還是有一些共同點,那就是對于:
這兩種協(xié)議的metrics請求,各個組件都至少支持其中的一個。
其實,監(jiān)控統(tǒng)一化這一點不難做到,我們可以選擇當前主流的開源監(jiān)控工具Zabbix(對于JMX的metrics獲取,Zabbix自身已經(jīng)提供了原生支持:Java Gateway)。但是對于個性化的監(jiān)控,比如特定metrics的提取與展示,需要對Zabbix進行定制。出于各種原因,我們暫時沒有采用基于Zabbix的定制方案。
因為Zabbix 提供了JMX收集的原生支持,而且它自身又是開源軟件,所以我們的JMX metrics收集是基于Zabbix Java Gateway進行定制的。
簡單了解一下Zabbix Java Gateway,Zabbix是在2.0之后對JMX提供了原生支持。它的架構非常簡單,如下圖所示:
工作原理:
Zabbix server想知道一臺主機上的特定的JMX值時,它向Zabbix Java gateway詢問,而Zabbix Java gateway使用“JMXmanagementAPI”去查詢特定的應用程序,而前提是應用程序這端在開啟時需要-Dcom.sun.management.jmxremote
參數(shù)來開啟JMX查詢就行了。
Zabbix server有一個特殊的進程用來連接Javagateway叫StartJavaPollers.Java gateway是一個獨立運行的java daemon程序,類似于一個proxy來解耦Zabbix和那些提供JMX metrics的component。
我們主要利用了java gateway獲取JMX的代碼(JMXItemChecker.java類),然后將獲取到的metrics轉存到我們的數(shù)據(jù)庫里,以供在日志系統(tǒng)的管控臺進行展示。因為我們沒有采用整套機制,所以無關的細節(jié)就不再多談。
http metrics主要用來對ElasticSearch進行監(jiān)控(因為它不支持JMX),我們使用HttpClient來發(fā)送請求,然后同樣將獲取到的信息存儲到我們的數(shù)據(jù)庫里。
quartz是一個開源的、功能強大的主流定時任務執(zhí)行框架。我們簡單提一下它的幾個核心概念:
當然quartz框架還有很多其他概念,但就這篇文章而言,這里我們只談上面這些就夠了。
上面談到了我們選擇的開源定時任務框架quatrz,單有一個框架還不夠,我們還需要對任務進行規(guī)劃、分類以及如何去管理、分發(fā)這些任務進行設計。
我們暫且將定時任務分為兩種:
這里,對于metrics的收集是我們引入定時任務的主要需求,因此我們將以它為主線來介紹我們的定時任務執(zhí)行引擎。
基于上面介紹的quartz的幾個概念,以及我們需要達到的通用化任務執(zhí)行的目的,我們需要思考如何來讓這個定時任務執(zhí)行引擎變動更自動化,提高它的擴展性,這就牽扯到定時任務執(zhí)行需要的元數(shù)據(jù)管理。
我們設計了一個層次化的組織結構,他們從上到下依次是:
category
對job進行廣義上的劃分,比如我們上面提到的offlineCalc,metricsPoller等。在Quartz里,Job有分組(group)的概念,我們也以此作為job分組的依據(jù)。
type
定義了任務的類型,它歸屬于category
。type
不只起到組織job
的作用,某種程度上它應對著一個job class,也就是某一組遵循相同處理邏輯的job
的歸類。比如,我們上面提到的,針對JMX 以及 http metrics的poller。
job
對應于quartz中的Job,這里需要權衡好它的粒度。拿JMX metrics poller這種類型的job舉例,如果只需要抓取某個component的metrics,那么一個job的粒度就可以是對一個metrics的一次獲取。但如果你需要對多個component的很多metrics進行提取,那么你job的粒度就不能這么細,可能你一個job必須要負責一個component中的所有metrics的提取。這取決于你的任務量,以及合理控制一個定時任務框架中的job數(shù)。
job metadata
存儲job
在運行時必須的元數(shù)據(jù)。上面提到job
是一類相同業(yè)務邏輯的一個抽象執(zhí)行單元。但他們并非完全一樣,不一樣的地方就區(qū)別在他們的執(zhí)行時需要的元數(shù)據(jù)。job
跟metadata
的對應關系是一對多的關系。比如我們上面提到的JMX metrics poller,它存儲了一個job
需要提取的metrics的object attribute的集合。
job trigger
對應于quartz中的Trigger
。job
跟trigger
的對應關系是一對一。
上面的這些數(shù)據(jù)都提供了在管控臺進行配置管理的功能。
為了提升定時任務執(zhí)行引擎的可擴展性以及自管理性。我們選擇用Zookeeper
來存儲如上的整個job的拓撲以及元數(shù)據(jù)信息。
Zookeeper除了是很好的元數(shù)據(jù)管理工具,還是很主流的分布式協(xié)同工具。它的Event機制,使得我們對Job生命周期的自動化管理成為可能。我們通過對各個ZNode的children ZNode進行監(jiān)聽,來動態(tài)感知Job的變化,感知到節(jié)點的變化之后,我們就可以動態(tài)創(chuàng)建或者刪除某個job。
本篇內(nèi)容我們以對日志系統(tǒng)的各個component的metrics的監(jiān)控為切實需求,談論了我們在主流的定時任務執(zhí)行框架quartz上進行的任務設計使得它更具擴展性,同時將其跟Zookeeper結合使得任務的管理具備自動化的能力。