监控告警系统始终遵循:和业务系统整合,采集业务系统数据,然后上报,进行数据处理,然后在界面展示的过程。Cat作为点评开源的项目,起源于ebay的Cal,由吴其敏和尤勇开发。这个项目在2011年就开源了,从代码的提交记录看,但依然不妨碍它作为一个优秀的监控工具。下面的内容基于V3.0.0进行说明。
一、cat的相关架构
从整体的架构可以看到,首先会构建消息树的上下文,基于threadLocal实现,放入到MessageQueue,而其数据结构是ArrayBlockingQueue。然后进行发送到Server,然后会经过相关的分析器analyzer进行处理,然后呈现在界面上。这个过程其实是一个埋点,采集数据,获取数据后,进行处理,然后呈现到界面的过程。
二、在业务系统中整合Cat的方式
1.首先在java的resource里面加上META-INF文件夹,然后新增app.properties文件,比如:app.name=springboot-cat
2.在业务中整合cat
public void testNormal() { Transaction t = Cat.getProducer().newTransaction("URL", "MyPage"); try { // do your business here t.addData("k1", "v1"); t.addData("k2", "v2"); t.addData("k3", "v3"); Thread.sleep(30); t.setStatus(Message.SUCCESS); } catch (Exception e) { t.setStatus(e); } finally { t.complete(); } }
三、整合的思路
可以看到会首先创建一个新的Transaction,重要的方法是t.complete(),记录事件,此时会将信息放入到队列中,最终可以看到会走到
public void add(Message message) { if (m_stack.isEmpty()) { MessageTree tree = m_tree.copy(); //设置消息树 tree.setMessage(message); //进行刷新操作 flush(tree, true); } else { //否则说明当前的事务为父级,添加事务child Transaction parent = m_stack.peek(); addTransactionChild(message, parent); } }
调用刷新接口进行数据入队列到m_atomicQueue或者m_queue,但是m_atomicQueue会最终将数据入队到m_queue。
m_queue.offer(tree)
可以看到队列的数据结构为ArrayBlockingQueue。
入了队列,必然就需要进行出队列,因此可以猜想到会执行poll()操作:
MessageTree tree = queue.poll()
入了队列,经过分析处理器,会进入相关的处理器AbstractMessageAnalyzer中analyze方法。相关的分析器如下:
四、分析器又是什么时候执行的呢
1) PeriodTask
一条线是可以看到执行器执行的过程是在PeriodTask中执行的,因此可以从PeriodTask中找到一些线索:
可以看到其基于RealtimeConsumer会随其初始化方法进行启动。
2)MessageReceiver.init()
另一条入队的路线可以看到是基于enqueue的
五、consumer的源头
可以看到在cat的源码中,cat-home的代码启动后,可以看到messageReceiver.init()这个方法会执行,而其属于setup方法,那必然需要在启动的时候需要启动它,此时才可以执行task,然后完成分析器的业务分析相关操作。
为什么这么说:如果下载了frameworks和foundition代码的话,可以看到这个init方法的源头在frameworks的HttpServlet接口,我们知道DispatcherServlet就是继承了这个方法实现的扩展。而在这里我们可以找到execute(ModuleContext ctx)和setup(ModuleContext ctx)可想而知就会随着服务的启动而执行。
源头代码:
public abstract class AbstractContainerServlet extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { super.init(config); try { if (m_container == null) { m_container = ContainerLoader.getDefaultContainer(); } m_logger = m_container.getLogger(); initComponents(config); } catch (Exception e) { if (m_logger != null) { m_logger.error("Servlet initializing failed. " + e, e); } else { System.out.println("Servlet initializing failed. " + e); e.printStackTrace(System.out); } throw new ServletException("Servlet initializing failed. " + e, e); } } }
这个方法是Servlet留给我们扩展的,这里可以看到会初始化一些组件,此时会调用((AbstractModule)module).setup(ctx)。而这个正是我们想要找的方法,此时会启动netty服务。可以看到里面添加了一个解码和一个编码到pipeline中。
在cat-home里面同时我们可以看到execute(ModuleContext ctx):
这个方法会启动报表重新加载task、task消费、启动告警、执行检查点操作
重新加载的task:
task消费:进行task处理
六、启动告警
告警的相关渠道
短信、微信、邮件、短信
七、执行检查点操作
EventAnalyzer 事件分析器 ProblemAnalyzer 问题分析器 BusinessAnalyzer 业务分析器 TransactionAnalyzer 事务分析器 StateAnalyzer 状态分析器 StorageAnalyzer 存储分析器 TopAnalyzer top分析器 HeartbeatAnalyzer 心跳分析器 CrossAnalyzer 交叉分析器 DumpAnalyzer dump分析器 DependencyAnalyzer 依赖分析器 MatrixAnalyzer matrix分析器