21 - Traces - 观察应用程序的效能瓶颈 (5/6) - 透过 APM Agents 收集并传送後端服务运作的记录

Traces - 观察应用程序的效能瓶颈 系列文章


本篇学习重点

  • APM Agents 要解决的问题是什麽?
  • APM Agents 提供什麽功能?
  • 如何使用 APM Agents 的简介
  • 使用 APM Agents 要注意的事项。

APM Agents 要解决的问题

Elastic APM Agents 的任务主要有两件事:

  • 协助『应用程序』或『服务』收集 Performance (效能) 相关的 Metrics,传送给 APM Server。
  • 当 『应用程序』或『服务』 发生 Error (错误) 时,收集 Error Logs,传送给 APM Server。

要做到以上的两件事,代表我们需要程序运作时,收集这两种的资讯,以下分别针对这两种情境来说明一般的做法。

传统收集 Performance Metrics 的问题

要分析某段程序运作效能时,最简单与古老的做法,就是在程序开始时,先记录当下的时间,在程序结束之後,记录结束的时间,也因为这种需求太普遍,各种语言当中的 Framework 或 Library 也都有支援这种计算 time elapsed 的工具,不过当记录这些 Performance Metrics 时,常会有以下的问题:

  • 『只有有埋 time elapsed 的地方,才收集得到数据』,但是要埋的地方可能有非常多,一开始不会都埋好,实务上常常会变成『发生问题时,才改 code 来埋 log、重新出 build、deploy、想办法让问题再次发生时,取得 log 』,这样会变成是背动的状况,甚至遇到不容易 reproduce (重制) 的例外状况时,也会很不容易收集到能协助判断及解决问题的资讯。
  • 收集到的资讯不足,在不同的情境下,会需要收集的资讯会不同,例如 Database 存取时的执行速度太慢,这时要能进一步盘查原因,可能会需要执行当下的 SQL statement 并且包含执行时带入的参数,也可能会需要知道是哪一个请求,才产生出这个 DB 的 query,资讯不足时要花更多的时间才能推测与盘查。

传统收集 Error 的问题

使用例如 try catch 等 Error handling 的方法,并且在错误发生时写 Logs,而这样的做法常会遇到:

  • Logs 没有结构化的格式,都只纯文字的方式在解读,有时要找寻相关的 Logs 时,只能用 grap 的方式去筛选,但复杂的条件要处理会很花时间。
  • 没有抓到的错误,被丢出时,记录到的资讯也不足,可能只有 stack trace,但是缺少能更进一步判断的商业资讯,例如使用者 ID、订单编号…等。
  • 收到的 Error,不容易与前、後发生的处理所产生的 Logs 串连在一起,在分析问题的原因时,不容易掌握整体处理流程发生状况的全貌。

APM Agents 的功能介绍

Elastic APM Agent 在协助收集 Performance Metrics 时,提供几种的方式:

Framework Integration (框架整合)

也可以称为 Build-in Instrumentation (内建检测),不论是哪种程序语言,在开发的时候常会使用各种 Framework,并且在 Framework 透过已经建立好的一些机制,例如:HTTP 请求的处理、Database 的存取,Logging 的机制、Scheduling (排程) 的功能…等。

APM Agents 在各种语言的支援上,都有尽量整合最热门的一些 Framework,让使用者简单的设定後就能直接使用,自动依照 Framework 的功能,收集相关的资讯,并且以结构化的方式,将收集到的数据的格式定义在 Elastic Common Schema 之中。

Instrumentation (检测)

在没有使用支援的 Framework 的时候,APM Agents 也有提供 Instrument (检测) 资料收集的工具,让使用者能很简单的将自己程序中要观察的某个处理行为,能包装成为 TransactionSpan,并且透过已经定义好的架构与提供的 Utility,能轻易的收集 Performance 相关的 Metrics 并且加上要额外记录的资讯,并且由 APM 帮我们将这收集到的事件,与其他前後的事件连结在一起。

Background Collection (背景收集)

APM Agents 在运作时,会在背景定期的收集系统的 Metrics,能够配合我们所收集的 TransactionSpan 的资讯,来协助掌握某个要观察的时间点,系统整体的状况。

APM Agents 支援的语言

目前有支援的语言,後端相关的如下:

  • Golang
  • Java
  • .Net
  • Node.js
  • PHP
  • Python
  • Ruby

前端相关的有两个

  • iOS
  • RUM (Real Time Monitoring) Javascript

APM Agents 使用方式简介

以下使用 Golang 为例:

  1. 安装 Elastic APM 套件
go get -u go.elastic.co/apm
  1. 使用在 Build-in framework 或 Library,例如 Gin Web Framework
import (
	"go.elastic.co/apm/module/apmgin"
)

func main() {
	engine := gin.New()
	engine.Use(apmgin.Middleware(engine))
	...
}
  1. 透过 Environment Variable 定义相关的设定
  • ELASTIC_APM_SERVER_URL:APM Server 的位置
  • ELASTIC_APM_SERVICE_NAME:目前的服务名称,这个会是之後在 APM UI 中用来识别服务的重要设定。
  • ELASTIC_APM_ENVIRONMENT:目前的 Environment,这也是在 Kibana APM UI 中筛选的主要功能之一。
  • ELASTIC_APM_GLOBAL_LABELS:有一些自订的 Labes 是属於全域型的,也就是在这个服务里全都要加上的,可以定在这里。
  • ...其它可参考 官方文件 - APM Go Agents - Configuration
  1. 指定自定义的 Instrument

建立自己定义的 Transaction

tx := apm.DefaultTracer.StartTransaction("GET /api/v1", "request")
defer tx.End()
...
tx.Result = "HTTP 2xx"
tx.Context.SetLabel("region", "us-east-1")

Transaction 当中加上 Span

span, ctx := apm.StartSpan(ctx, "SELECT FROM foo", "db.mysql.query")
defer span.End()

由於每一种语言实作的方式都会有些不同,每一种 Framework 的行为有不同时,支援的方式也会有所差异,以上只是最简短介绍 APM Agents 的使用方式,让大家有个感觉,详细的使用方式,请参考 官方文件 - APM Agents [1] 每个语言的版本。

使用 APM Agents 时要注意的事项

对於原本服务的影响?

APM Agents 在运作时,一定会占用到原本服务需使用的系统资源,这些处理会使用到:

  • CPU
  • Memory
  • 频宽

另外再从两个部份来分析:

  • Latency (延迟):APM Agents 收集资讯对於原本服务的 latency 影响程度非常的小,一般只有个位数的微秒 (microseconds),所以单纯是考量 Latency 的部份的话,埋的量不是非常多的话,其实不会有太大的影响。
  • Background tasks (背景处理):APM 在收集到 Instrument 资讯之後,会需要序列化 (serialize) 以及压缩 (gzipping) 的处理,这部份会占用到 CPU 的运算,如果服务本身是使用 CPU 为主的服务 (CPU bound),这部份会影响到原本的性能,但如果不是 CPU bound 的话,影响会较少。

另外 APM Server 如果无法正常接受 APM Agents 所传送的资料时,APM Agents 最终会选择放弃传送,设计上也是以不影响原本服务执行为主。

特别注意:先前专案的团队实际在使用 PHP 版本的 APM Agents 时,在压测时有明确的因为加上 APM Agents 後,原本服务的 QPS 下降将近一半,猜测和 PHP 的实作版本没有实作 async call 可能有关,若有使用 PHP 版本的话会需要特别留意。

Sample Rate (取样率)

既然使用 APM Agents 收集 Instruments 数据时,一定会占用到系统的资源,也就是多少都会影响到原本服务的效能,这时候 Sample Rate (取样率) 就是一个很重要的设定,不过这个值没有一定的标准,但是在量级非常大的系统之中,1 ~ 3% 的取样率一般已经足够有一定的代表性,也就是若是有问题发生时,一般都会能取得到样本,当然这个设定值还是会依照使用的情境与硬体的规格需进行压测及调整。

减少 APM Agents 处理的资料量

  • 如果某些资料没有必要都要收集,例如 capture_headercapture_body ,这个在 Sample Rate 较高、量级较大的环境之中,应该考虑关掉 capture_body ,这个会於效能会有明显的影响。
  • 如果一个 Transaction 中包含了过多个 Span,这也会让整包处理的量非常的大,例如有写了个跑非常多次的回圈,里面产生非常多的 span,这种情况应该设定好 transaction_max_span 来避免这种意外发生。
  • 另外 APM Agents 会将收集到的 Instruments 资料分批的往 Elasticsearch 传送,这个每次处理的量也会占用到系统的效能,如果记忆体占用太多,应该要尝试调整传送的间隔 api_request_time 、或是每批的大小 api_request_size

参考资料

  1. 官方文件 - APM Agents

查看最新 Elasticsearch 或是 Elastic Stack 教育训练资讯: https://training.onedoggo.com
欢迎追踪我的 FB 粉丝页: 乔叔 - Elastic Stack 技术交流
不论是技术分享的文章、公开线上分享、或是实体课程资讯,都会在粉丝页通知大家哦!


<<:  React Hooks - useState

>>:  【Day 23】深度学习实作 --- "Hello world"

[Day 25] Edge Impulse + BLE Sense实现手势动作辨识(下)

=== 书接上回 [Day 24] Edge Impulse + BLE Sense实现手势动作辨识...

DAY 28 - 殭屍女孩 (1)

大家好~ 我是五岁~ 今天要来画可爱的殭屍女孩~ 风格类似是中国殭屍,她外观上有两个巨大的手手可以跟...

把Nano板run起来

先说,我是用mac双系统的win10,本来想在mac os做,但是下载下来的说明书里有个自己的驱动程...

找LeetCode上简单的题目来撑过30天啦(DAY20)

这题写凌晨2、3点,本来要用c的,最後用JAVA,然後睡觉前送出去Time Limit Exceed...

D-09 资料库存取 ? Dapper

怎麽处理资料库沟通 相信这点是每个程序开发工程师关注的点,在dotnetcore中可以选择Entit...