2016年对于网易杭州研究院(以下简称“杭研”)而言是重要的 – 成立十周年之际,杭研正式推出了网易云。“十年•杭研技术秀”系列文章,由杭研研发团队倾情奉献,为您展示杭研那些有用、有趣的技术实践经验,涵盖云计算、大前端、信息安全、运维、QA、大数据、人工智能等领域,涉及前沿的分布式、容器、深度学习等技术。正是这些宝贵的实践经验,造就了今天高品质的网易云产品。本文的分享来自杭研运维团队,结合网易杭研的实践解析了现代化的企业级监控体系的构建。
本文分为上下篇,上篇内容包括:
CMDB体系的建立
基于模型的监控体系
监控数据存储,可视化和数据处理
服务器和网络设备监控
下篇内容包括:
应用性能监控以及业务监控
统一Agent
流式监控以及终端设备监控
分布式跟踪系统以及日志分析
统一应用配置中心与应用管控
企业级监控未来的发展趋势
五、应用性能监控以及业务监控
上面的系统监控,实现了服务器以及网络设备等基本指标的监控,同时通过用户自定义采集器可实现一些其他系统级的监控,比如DB、缓存等其他组件的监控。但是对于应用内部的无法用脚本采集的监控就无法实现了。比如Java内部方法的调用情况,应用执行SQL的效率等等。应用程序的监控体系与系统监控的区别主要在采集方式上,监控项报警等其他体系可以跟系统监控一样。目前业界对于应用监控的采集都采用相关开发语言的探针来实现,这种方式的优点是对应用侵入比较小,用户后期实施比较容易。
1、数据采集探针
Java在1.5版本之后 推出javaagent技术,支持运行期更改程序字节码。Java启动参数增加 -javaagent:参数,让虚拟机启动之后优先进入用户自定的premain函数,在premain函数内,用户可以加入自定义transformer,当类被加载的时候transformer可以对代码进行改动,加入拦截逻辑,实现监控数据采集。这种方式的优点是对应用的侵入比较小,对于已经存在的应用,上监控就比较容易。另外其他的语言也有相应的探针机制实现低侵入的监控数据的采集。
2、采集汇总数据的思路
监控数据采集是通过监控项定义的周期定时采集的。每当业务调用发生的时候,比如URL调用、SQL执行等,通过拦截器对内部的计数器进行累加,采集周期到的时候,实现数据采集,并且reset计数器。相比日志,采样等其他的方式,这种方式的优点有:对应用性能影响比较小,因为主要是内存操作;对监控服务器的冲击比较小,因为固定周期采集产生的监控数据的量是一定的;能够采集总量的信息,对于业务监控的统一采集比较重要。
3、中间件采集的扩充
Java应用采集的时候除了采集基本的JVM参数,重要的是要支持对于一些中间件的调用的采集,比如MySQL关系数据库、Redis/Memcached缓存、Dubbo调用、HBase调用、httpclient调用,以及网易内部的NOS、NDIR、NKV等各种中间件。javaagent支持升级,升级之后可以不断增加新的中间件的拦截。用户通过查看中间件的监控数据可以判断依赖的中间件是否出问题,进而诊断应用的问题。下面是一些视图的示例:
JVM GC视图
应用异常监控
SQL监控
Redis监控
4、应用拓扑
当各种中间件采集完成之后,当前应用对于中间件的依赖关系就有了,调用的数值也有了。如果将应用与中间件的依赖关系展示在一个拓扑图上,并且对于出问题的组件标红,那么用户一方面可以很好地掌握应用对中间件以及第三方服务的依赖关系,另一方面也能直观地看到应用出现问题的根源所在。通过对Dubbo等分布式系统的拓展,可以逐步定位问题的根源。由于javaagent是逐步升级的,拓扑图的需要支持配置的方式实现扩展。
5、profile功能的实现
通过URL监控,我们可以定位一个URL的执行的效率,当URL调用比较慢的时候,我们需要知道一个URL的调用的总体性能消耗情况。比如一个URL会执行SQL语句,调用缓存,调用外部Dubbo服务,我们需要知道哪个调用是最多最耗时的,这就需要profile的功能。由于依赖的服务可能也会依赖其他服务,所以profile的数据应该是树状的。为了实现profile功能,首先需要javaagent支持树状结构数据的采集,另外服务器端存储也需要支持树状结构的存储。
6、用户自定义的业务监控
上面的监控指标都是一些标准的中间件指标,但是对于一些用户特性化的业务指标就无法通过通用的方式来实现,比如对于下单量的监控。为了实现用户自定义的监控,可以提供SDK来实现,用户通过使用SDK,自编程方式在客户端先做聚合,发送到服务器再由服务器进行集群聚合。然后可以用平台的视图引擎实现数据可视化。
六、统一Agent
系统监控的脚本需要服务器上安装的Agent来执行,由C和C++编写完成,Agent会一直运行在服务器上,除了定期执行监控脚本之外,Agent应该支持更多功能,理论上讲一台服务器上统一安装一个Agent来统一执行相关任务,实现对服务器的高效管控。现在总结Agent需要实现的功能包含:
与服务器端保持心跳。服务器进入CMDB系统就具有网络连通性,后续通过Agent的连通性来判断主机的存活状态。在失去联通性之后再加上其他的判断条件,可以判断一台主机是否宕机,网络是否出问题。
自升级和配置同步。当有新版本的Agent发布,可以实现自动升级,这样可以大大减少运维成本,同时Agent需要识别网络拓扑,为后续其他运维功能提供支持。
实现监控功能。从配置中心获取监控项,周期执行监控脚本,上报监控数据。另外对于外部探测的监控,需要承担Super Agent角色,执行探测脚本,实现VIP、网络监控等监控等功能。
支持Agent的API调用。这样服务器端就可以通过API实现对客户端的控制,比如执行相关脚本实现部署任务等。Agent 支持API,大大拓展了Agent的功能范围,给系统以更大的想想空间。
支持日志采集和传输。很多企业对于日志的采集传输往往采用独立的Agent来实现,这样做一方面造成运维成本的增加,另外也降低的系统的集成度,降低可用性。另外独立的Agent也可能会造成系统资源的浪费,比如某一些产品Agent采用Java编写,那么运行的时候占用资源多,而且fullgc容易对系统产生冲击。
与其他系统集成,支持插件化体系。随着企业的发展,往往需要在服务器上做的功能越来越多,一个可扩充的插件化体系就能够大大提升其他系统与Agent的集成,提升运维效率。
由此可见,统一的Agent,对于监控以及系统的运维效率提升至关重要。设计运维系统的时候需要优先考虑与统一Agent的集成。
七、流式监控以及终端设备监控
之前涉及到的监控主要特点是监控对象比较少,比如服务器的数量不会很多,另外以周期采集为主,一次采集的数据量不会很大。在某些场景下,这种监控方式并不能完全满足。比如无线设备的监控,前端js页面的监控,还有一些日志的监控等等。对于这种监控方式需要做到多维度、多指标的聚合监控,准实时等。这就需要一个引擎来对数据进行分析,适配等,我们称之为流式监控。之前杭研的NAPM重点采集一些已经定义好的性能指标,对于用户自定义的指标涉及比较少。流式监控通过统一的处理模型,不但可以实现通用指标的聚合,也可以实现自定义指标的处理,具有通用性。
1、消息建模
首先在CMDB系统定义无线或js的应用的名字,然后在监控系统定义消息的类型以及消息的字段,数据类型信息等。这样也就定义了终端上报的消息的格式。对于某一些隐含字段需要服务器端实时计算获取,比如消息发送的IP地址,消息所在的位置信息,消息所在的运营商等等,后续通过对这一些属性进行聚合,产出区域或者ISP报表。
2、消息处理模型
消息模型建立之后,终端按照消息建模的方式上报数据,服务器端处理模型需要做如下事项:
定义采集器和数据项,定义数据的存储方式,以及为添加监控项打好基础。
数据项的字段上设置消息处理的取值函数,用于对消息的值进行处理,比如截取消息内容的函数等等。
定义聚合方式,实现对消息的聚合运算,比如sum、avg、max、min等。
3、 统一的监控项,报警,状态处理方式
数据经过处理和聚合之后,形成与系统适配的消息格式,进行存储,同时可以设置报警表达式进行报警,处理状态转换等。
流式监控的方式解决了海量终端和海量监控数据的场景,也可以为无线应用,web js监控等提供服务器端的数据处理模型,与无线应用的采集器可以无缝集成,提升监控效率。
八、分布式跟踪系统以及日志分析
前面的应用监控都是周期采集汇总数据为主,而且数据之间的关联性比较小。一般而言一个企业的IT系统是比较复杂的,不只是依赖一些中间件,更会依赖一些其他的服务,而且一个服务也可能依赖其他服务。当系统出问题的时候,对于服务质量的跟踪就比较困难。在这种场景下,很多企业也已经进行了实践,通常的做法是在前端应用生成一个traceId,然后将traceId,透传到各个后台的服务,通过traceId对服务的质量进行跟踪。系统调用的数据通过日志打印到磁盘上,日志上报后,集中存储,处理,就形成了分布式的跟踪系统。在这过程有几个关键点:
1、traceId的生成
业界通常认为traceId是一个没有语义的字符串,但是事实上traceId是可以有一定的意义属性的,比如一个traceId是针对某个前端IP调用产生的,访问某个URL产生的,并且可能是某个用户访问的。所以给traceId赋予访问资源,访问用户等属性利于traceId的搜索与跟踪。
2、traceId的透传
如何将前端产生的traceId透传到后端,成为一个难题。很多企业通过开发自己的中间件,并且在中间件埋点的方式实现traceId的透传,这种方式的缺点是需要开发自己的中间件。另外一种方式是通过字节码增强方式在中间件植入拦截逻辑,并且将traceId嵌入中间件发送的请求中,实现透传。这种方式可以减少企业的开发成本,并减少对系统的侵入性,比前一种方式更为优越。
3、数据的采集传输
traceId透传之后,需要将中间的一些关键事件以日志的方式输出,关键事件可以是log的API调用,方法调用,中间件调用等。输出后由统一Agent上传到服务器端进行存储和处理。服务器端可以将相同的traceId的日志统一存储在一起,利于后续跟踪。
4、数据的查询
当需要定位业务问题的时候,可以通过资源,或者用户标示以及时间定位到traceId,通过traceId可以查询一系列的相关事件,就可以实现对某个具体资源访问的分布式跟踪。
5、统一的日志处理框架
上述涉及到了javaagent的日志传输和处理,但事实上用户的业务日志也是需要处理的。如果javaagent的分布式跟踪的日志和用户的日志可以统一处理,企业开发的成本就能够大大减少。用户的业务日志通过统一Agent上传到处理服务器,处理服务器可以根据需要将日志归档存储,建立索引,导入离线计算平台计算,或者导入流式系统进行实时计算。这样运维自动化集成程度就大大提高,用户的需求也可以得到很好的满足。
九、统一应用配置中心与应用管控
前面涉及的系统很好地满足了监控的需求,但是在某一些情况下光监控还不能完全满足需求,用户需要监控到系统问题之后能够有所动作,对当前应用实现管控。比如大促的时候线上应用压力比较大,感觉系统可能会出问题,期望将一些不重要的功能关闭,实现系统降级,保证线上核心下单流程的稳定。为了实现对应用的管控,我们需要一个统一的配置中心,将应用配置实时下发到应用内存。统一配置中心需要有如下关键点:
一个应用配置的管理界面实现KV配置项的增加删除修改。
提供API接口对配置信息进行更改。
提供编程的SDK给用户使用,实现配置推送。
定义应用与配置中心服务器的推送协议,用户可以针对不支持语言实现推送。
十、企业级监控未来的发展趋势
上文主要讲述了为满足企业级监控需求需要开发的系统。从长远的发展来看,企业级监控的发展趋势可以有两个并行的方向:
1、与其他系统的融合,就有更高效、全面的监控,这也符合未来超融合系统的趋势。
资产管理系统集成,实现对企业资源的全面监控。
与云平台集成,可以方便将一些虚拟设备自动加入CMDB系统,快速自动实现监控。
与安全相关的产品融合,通过统一Agent实现安全相关的管理控制。
与中间件的集成,中间件在交付用户使用之前必须是与监控系统可集成的,这样也可提升监控自动化程度。
2、监控系统自身的深入的发展趋势。
root cause溯源化。各种监控系统集成一体,通过监控系统能够快速定位问题的根源,减少故障时间。
趋势预测。通过监控数据预测未来发展的趋势,做到及时预防。
智能化。监控系统需要做到更智能,甚至具有学习能力,能够自动对故障进行治愈。
——叶锋
网易杭州研究院运维部