在2021年4月份,Elastic刚刚入围了Gartner的APM魔力象限。如Elastic同时新晋入围的,还有阿里云:
在这个魔力象限中,我们看到,还有另外一家国内厂商听云。 在关于的长处介绍中,我们看到这样的一段描述:
开源技术:Tingyun使用现代的开源技术(例如Kafka和Elasticsearch)构建了许多组件和功能。这降低了客户成本。
其中提到了其解决方案也使用到了Elasticsearch。其实不只是听云,日志分析技术做为APM整体技术中非常重要的一个部分,大量的APM厂商其实背后也是使用到了Elasticsearch,包括头部的Dynatrace, Datadog等解决方案背后也有使用到Elasticsearch作为多种不同数据结构的背后存储数据库。可以说,在这个市场中,Elastic作为Elasticsearch背后的商业公司亲自入场参与游戏,即是资本选择的必然,也是客户需求驱动的结果。通过以下Elastic APM的演进图我们可以看到,Elastic的APM解决方案并非一蹴而就,而是经过数年的演进,才能够被符合Gartner魔力象限的考核标准,获得客户的青睐的:
这里,我们希望通过一系列的文章,能够帮助到大家更好的理解Elastic APM这样一个广义的从全观察性的角度去描述应用性能的解决方案。本文将结合APM技术的分类和实现方式,从整体上介绍Elastic APM。
互联网应用的应用交付链
在了解Elastic APM之前,我们首先需要了解一下典型的互联网或移动互联网应用的整个应用交付链。
上面这张示意图给出的就是一种典型的互联网应用的应用交付链,在这个应用交付链最左端是部署在机房或云服务商上的相对可控的区域,例如负载均衡、Web服务、应用服务器、数据库、消息总线、IDC基础设施(存储,计算,网络)等等。越往右就是离应用的最终用户越近的部分,会涉及到机房或云服务的链路,第三方的服务(例如云服务、CDN、推送、地图等等),用户设备接入的本地运营商、移动运营商、用户访问应用使用的不同终端设备,浏览器等等。
所有图上标注了炸弹的位置,都是整个应用交付链里容易出现性能问题和降低用户体验的问题点,例如浏览器或设备的不兼容、2G/3G/4G网络基站的拥塞、各地无良运营商的劫持、CDN节点的故障、第三方API接口的限流策略、骨干网运营商的线路维护、以及服务端的代码、服务、资源等问题。所有这些问题都是APM需要关注的问题,理论上,从左到右,对运维和研发人员来说,总体的可控度是递减的,而APM的引入就是希望能提高运维和研发人员对这些问题的可控度、降低MTTR。
因此APM需要关注或者说需要采集数据的位置也就是图上的这些炸弹的位置,而不同位置的数据采集就带来了APM技术的不同分类。
APM技术分类和实现
从APM监测部署的位置(或者叫做数据采集位置)来分,基本上可以分成客户端和服务端两大类技术。分别针对最终用户侧和应用服务侧的APM技术。我们通常说的端到端的应用性能管理,指的就是从这两端来实现的APM技术组合。
客户端APM技术
从客户端角度的APM技术分类上来看,又可以分为主动式的APM客户端监测技术和被动式的监测技术两大类:
主动式的客户端监测技术
主动式的客户端监测技术称为Synthetic Monitoring:Synthetic,从字面的意思翻译是人工合成的,也就是说这种监测技术的数据采集不是真实用户产生而是人工模拟出来的,通过脚本程序模拟真实用户的访问行为来对应用进行主动式的访问来采集数据,也就是通常说的拨测。这种监测方式需要部署一定数量的监测节点,通过定时调度的计划来主动访问应用来采集数据。
Elastic APM解决方案中,在7.11版本中提供Sythetic Agent的体验版:
其工作原理如下:
Sythetic Agent目前主要基于JavaScript和 Playwright来进行合成测试的脚本编写。其中, Playwright 是Microsoft开发的浏览器测试库。它可靠且快速,并具有可自动等待页面元素准备就绪的现代API。我们可以参考官网文档学习Elastic Sythetic Agent。
以下示例,我们使用Elastic Sythetic Agent监控腾讯云ES的首页,以及模拟进行系列用户下单动作,来监控在站点上执行的操作和请求的用户体验指标:
主动式监测由于监测节点可控度非常高,理论上你可以利用这些监测点做任何的数据采集,因此此类技术的适用场景包括做应用性能特别是可用性的监测,做对比测试(例如IDC/CDN/云服务商的对比和选型),竞品对标,压力测试等。
由于主动式监测使用的是模拟的样本数据,需要有足够多的样本才能模拟出真实用户的性能体验,否则会存在较大的样本偏差,导致错误的结论。所以,如果要部署大量的监测节点的话,成本还是比较高的,因此目前此类监测很少有自己部署的,大部分使用的都是一些厂商提供的第三方监测服务。这里,推荐大家使用腾讯云的Serverless服务,或者TKE容器服务,以轻量化的方式部署Elastic Sythetic Agent。
被动式客户端APM监测技术
被动式客户端APM监测技术称为RUM:即真实用户的监测,利用的是真实的用户对应用的访问来采集性能数据。RUM有一个天然的优势就是基本上没有样本偏差,当全流量采集数据的时候,采集到的数据就是你的用户的真实体验数据。目前客户端的RUM技术会覆盖两部分的典型应用:WebApp和NativeApp,这里面当然也包括现在比较流行的HybridApp。
从客户端采集真实用户的性能数据基本上用的就是埋点这一条途径了,对于WebApp,通过页面上插入JS,利用现代浏览器提供的NavigationTiming和ResourceTiming接口来采集性能数据。
Elastic APM的真实用户监测由APM Real User Monitoring (RUM) agent提供支撑,Elastic RUM agent除了使用Navigation Timing,Resource Timing之外,也使用Paint Timing和User Timing 来捕获每次用户点击您的页面之一时的用户体验指标。此数据存储在Elasticsearch中,可以在其中使用Kibana对其进行可视化。
关于RUM,Google的一项最新举措是Core Web Vitals,它引入了一组新指标,可以通过量化现实世界中的用户体验来更好地对好站点和坏站点进行分类。这是通过查看三个关键指标来完成的:加载性能,视觉稳定性和交互性
Elastic RUM采用了Google Core Web Vitals:
大型内容渲染(LCP)
加载性能。LCP是页面的主要内容可能已加载的时间戳。对用户而言,这是您网站的感知加载速度。为了提供良好的用户体验,Google建议您的LCP少于2.5秒。 [ 4 ]
首次输入延迟(FID)
负载响应能力。FID衡量的是从用户第一次与页面进行交互(例如单击)到页面可以响应这些交互之间的时间。为了提供良好的用户体验,Google建议FID小于100毫秒。 [ 5 ]
累积布局移位(CLS)
视觉稳定性。内容是否由于异步资源加载或动态内容添加而四处移动?CLS测量了这些令人沮丧的意外布局位移。为了提供良好的用户体验,Google建议CLS得分小于.1
。 [ 6 ]
从2021年5月开始,Google将开始使用Core Web Vitals作为其排名算法的一部分,并将为网站提供机会,使其无需使用AMP即可排名为“热门新闻” 。
对于WebApp和HybirdApp,均可采用Elastic RUM来进行监控,包含各种统计类的信息:
以及错误明细:
而对NativeApp的RUM监控就没有什么标准的接口可以用了,如果想自己做的话一般依赖于研发人员手工埋码,或者在开发App的时候使用一套统一的框架来进行埋码和采集。
目前APM行业里通常的做法是提供一套可以自动埋码和采集数据的SDK来自动完成监控代码的注入工作。通过这种方式可以做到开发人员只需要修改少量代码甚至一行代码都无需修改就可以集成RUM的数据采集功能到App中。这里使用到的自动代码注入技术与服务端监控的代码注入机制类似。
在Android上,如果使用Java,可以使用Elastic的APM Java agent,可通过- javaagent
,或直接jvm attach的方式进行自动埋点。也可通过手动加载库方式,自定义埋点:
// Hook into a callback provided by the framework that is called on incoming requests
public Response onIncomingRequest(Request request) throws Exception {
// creates a transaction representing the server-side handling of the request
Transaction transaction = ElasticApm.startTransactionWithRemoteParent(request::getHeader, request::getHeaders);
try (final Scope scope = transaction.activate()) {
String name = "a useful name like ClassName#methodName where the request is handled";
transaction.setName(name);
transaction.setType(Transaction.TYPE_REQUEST);
return request.handle();
} catch (Exception e) {
transaction.captureException(e);
throw e;
} finally {
transaction.end();
}
}
通过库的方式进行埋点的逻辑和上面代码大同小异。
客户端RUM一个非常重要的技术难点就是对客户端资源的消耗的控制。包括计算资源(CPU,内存)以及网络资源(流量)。对计算资源的消耗最终可能影响应用本身的性能,如果控制不好会变成为了做性能监测反而引入新的性能问题。
因此对性能数据的采集上一般会对不存在性能问题的样本数据在客户端上降低采样比例或者是只采集简单的汇总数据,而只对超过性能阈值和异常的数据进行详细的数据采集。同样在客户端进行一部分的数据汇总和合并,(例如短时间内,客户端发生同一种网络故障是往往是重复出现的,可以合并以后再上报),在不同网络环境下使用不同的数据上报策略,这些都可以极大地降低对网络流量的消耗。
Elastic APM通过提供tail-based Sampling方式来满足以上需求,只要请求的链路追踪数据中任何节点出现重要数据特征(错慢请求),这个请求的所有链路数据都采集(由分布式微服务的各个节点上产生),否则将可以被policy设置为丢弃。这种采样方式在一些场景特别有效,比如错慢全采,大客户全采,而其他非重要数据仅提供聚合报告。
服务器端APM技术
再来看看服务端的APM技术。目前比较常用的服务端APM技术大概可以分为以下四种:
无探针技术:无需安装探针,通过系统或服务自身提供的状态接口来进行组件的性能和状态的监控,例如通过SNMP等协议实现的监控,这种监测技术大家应该比较熟悉了,例如常见的Promethues,Cacti,Zabbix等工具都属于这一类型的监控技术。无探针技术目前是作为APM中的辅助技术来提供第四个维度的应用组件性能和状态数据的。
在Elastic APM的解决方案当中,我们通过metricbeat等各种数据摄入组件,将其他指标工具产生的数据进行重新规范化,汇聚于Elasticsearch,形成可联合分析的数据:
日志分析技术:日志分析能做的事情非常多,其中一部分就是APM,实际上日志分析是APM中非常重要的一种补充。通过采集系统、组件和应用的日志并进行实时的分析来进行性能评估和问题的定位。Elastic的核心Elastic Stack就是该领域最热门的底层软件设施,
而在Elastic APM的解决方案当中,更是直接提供了日志与分布式追踪(trace)数据的整合,可以统一在Kibana上完成上下文的切换和关联分析
NPM技术:此类技术使用的是网络协议包监听和分析的技术来实现的应用性能管理,实际上是属于NPM(NetworkPerformanceManagement)领域的产品,用在APM领域的时候通常叫做aaNPM(ApplicationAwareNetworkPerformanceManagement,应用感知网络性能管理)。NPM的厂商比较多了,也有一些开源的产品例如ntop(http://www.ntop.org/)大家有兴趣可以了解一下。aaNPM可以采集足够详细的应用网络性能方面的数据,但是无法提供代码级别的性能数据。
在Elastic APM的解决方案当中,我们通过packetbeat捕获应用程序服务器之间的网络流量,解码应用程序层协议(HTTP,MySQL,Redis等),将请求与响应相关联,并记录每个事务中我们感兴趣的字段。
应用内探针技术:这个应该是目前APM行业里比较流行的技术,使用的是运行在应用内部(应用服务器上)的探针,由于探针与用户的代码在一起运行在应用内部,因此可以采集到非常详细的性能指标数据和业务指标数据,包括应用的响应时间,代码模块的执行时间,应用调用其他服务组件或API接口的响应时间,代码对系统资源的消耗等。
此外,运行在应用内部的探针还可以对代码的调用栈和应用之间的调用链进行跟踪,可以提供非常完整的业务调用栈性能数据和追踪数据。
相比其他三种技术,应用内探针使用的是侵入式的探测技术,具有非常明显的优点就是调用栈的跟踪和代码的定位,但是也带来了对应用的性能和稳定性产生影响的风险。不过目前好的探针技术基本都可以做到在极低的性能和稳定性影响风险的情况下采集到足够详细的应用性能数据了。
Elastic APM针对应用内探针技术,提供了时下所有热门语言的探针:
- APM Go Agent [1.x] — other versions
- APM Java Agent [1.x] — other versions
- APM .NET Agent [1.9] — other versions
- APM Node.js Agent [3.x] — other versions
- APM PHP Agent [1.x] — other versions
- APM Python Agent [6.x] — other versions
- APM Ruby Agent [4.x] — other versions
- APM Real User Monitoring JavaScript Agent [5.x] — other versions
以简易的方式完成对应用的埋点监测:
列了这么多APM的技术大家可以看到,没有一项技术是可以完全取代另外一项的,不同的APM技术适用于不同的应用场景。这里给出了一张APM技术使用场景对照表:
位置 | 方式 | 技术 | Elastic APM技术覆盖 | 侵入 | 全样本 | 真实用户 | 最终用户体验 | 竞品对标 | 网络问题定位 | 基础架构监控 | 后端服务监控 | 业务监控 | 代码级定位 | 分布式追踪 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
客户端 | 主动 | 主动拨测 | Synthetic Agent | ✅ | ✅ | ✅ | ✅ | ✅ | ||||||
被动 | RUM | RUM Agent | ✅ | ✅ | ✅ | ✅ | ✅ | |||||||
服务端 | 主动 | 无探针技术 | Metricbeat | ✅ | ✅ | ✅ | ||||||||
被动 | 日志分析 | Filebeat & Logstash | ✅ | ✅ | ||||||||||
NPM | Packect beat | ✅ | ✅ | ✅ | ✅ | ✅ | ||||||||
应用内探针 | APM Agents | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
可以看到,最常需要的技术已经在Elastic APM解决方案当中被相对完整的覆盖了。
因为,随着越来越复杂的应用架构和应用场景,越来越需要将不同的APM技术组合在一起使用,对端到端的性能数据进行相关性分析,才能快速准确地定位性能问题点。Gartner也是在2015年第一次将APM魔力象限的名称从Application Performance Monitoring改成了Application Performance Monitoring Suites。强调APM厂商应该以套件的方式为用户提供完整的解决方案。
其中的逻辑是显而易见的,由于客户端APM和服务端APM探针部署的位置差异导致各自只能看到完整调用链中一部分的性能数据和现象,因此只有把两端的数据关联在一起分析才能更精确的定位问题。同样的在服务端的应用中,完成一个业务/事务的处理往往需要在不同的应用系统、组件和服务之间相互调用和传递数据,只有将各应用和组件之间的性能数据通过业务的调用链关联起来才有可能对性能问题进行快速有效的追踪和定位。这就是APM分析中的跨应用分析和追踪技术,这项技术的实现就很大程度上依赖于应用内探针技术。
通过应用内探针技术,在对应用进行自动埋码进行性能数据采集的同时,还可以对应用的响应信息和应用对外的服务调用请求进行适当的修改,加入用来追踪的数据(例如在HTTP请求头里加入追踪的会话ID等等),而在客户端和其他应用组件内部的探针就可以对这些追踪数据做相应的处理,并且在数据采集的时候对每个请求做关联了。
通过分布式追踪技术,在客户端就可以迅速了解一个请求慢是由于服务端的接口响应慢还是网络延时高导致的,而在服务端的接口数据里,又可以详细地钻取到最终导致应用的复杂调用链响应慢情况下特定的服务组件或代码。