ELK专题:使用Elastic APM对Python项目实施性能监控
前言
在运维的技术栈里面,说到监控系统,大多数人可能首先想到的对后台服务器的CPU、内存、网络流量、磁盘IO等性能指标监控起来。要是再深入一点,可能会再做一个日志监控,把各个事务的日志统计起来,可以跟踪各个事务的时间和数量的分布等等。
那假如,我们想更深入一层,想要知道各个API在处理事务的过程中在每个步骤上都花了多少时间呢?比方说,有一个接口GET /user_info/<user_id>
,服务器在处理这个接口的时候需要从数据库上使用user_id
查询用户的昵称,同时请求其他API得到玩家的排行榜信息。我们自然可以使用日志打点的方式把这些步骤都记录下来,再通过ELK的日志监控去完成,但这样无疑会增加大量的开发成本,而且很有可能需要反复打磨才能获得一个满足各个场景的通用标准。
而今天要说的Elastic APM(application performance monitoring)就是专门针对这种场景的通用解决方案。
实现原理
Elastic APM的技术栈由四个组件组成:APM agent、APM Server、Elasticsearch、Kibana。
APM agent: 植入到业务应用的代码中,采集应用运行期间的性能数据,各个主流的开发框架都有现成的APM库可以直接使用。
APM Server: 所有应用的性能数据最后都会汇聚到APM Server中,可以在APM Server按需进行数据转换、校验或者过滤后再输出到Elasticsearch。
Elasticsearch(ES):和日志监控一样,APM Server采集回来的性能数据最后会以文档的形式存放到ES的索引中,同时ES会提供强大的存储和查询功能。
Kibana: 提供数据可视化功能,在最新的版本中还可以提供ELK Stack集群的管理功能。
总体而言,Elastic APM的实现原理和本专题之前讨论的ELK日志分析系统类似,只是数据源的采集方式不同。
测试环境搭建
在之前的实践中,在笔者的实验环境已经有一套现成的ES和Kibana,今天我们重点放在APM的搭建。
版本信息
根据官方的兼容矩阵,本实验环境选用的组件版本如下:
参考:
https://www.elastic.co/support/matrix#matrix_compatibility
https://www.elastic.co/guide/en/apm/get-started/current/agent-server-compatibility.html
https://www.elastic.co/guide/en/apm/agent/python/6.x/supported-technologies.html
组件 | IP地址 | 版本 |
---|---|---|
Kibana | 192.168.0.213 | 7.13.4 |
ES | 192.168.0.212 | 7.13.4 |
APM Server | 192.168.0.214 | 7.15.2 |
APM Agent | 192.168.0.129 | 6.x |
Python | 192.168.0.129 | 3.9 |
Flask | 192.168.0.129 | 1.1 |
APM Server 安装
笔者使用的是Ubuntu 20.04系统,官方文档或者Kibana的页面里面都有详细的指引,部署过程如下:
1 | curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-7.15.2-amd64.deb |
更多详细安装步骤可以参考:https://www.elastic.co/guide/en/apm/server/7.15/installing.html
APM Agent 安装
在本测试环境中,使用Python Flask搭建一个demo。在开始测试代码之前,需要先安装如下Python库:
参考文档:https://www.elastic.co/guide/en/apm/agent/python/6.x/flask-support.html
1 | pip install "elastic-apm[flask]" |
Server与Agent联调
在APM Server使用的测试配置文件apm-test.yaml
内容如下:
1 | apm-server: |
使用命令apm-server -c /root/apm-test.yaml
启动APM Server服务,屏幕输出如下:
1 | # apm-server -c /root/apm-test.yaml |
Python测试代码:
1 | from flask import Flask |
启动上面的flask代码后,当flask应用接收到请求后,APM Server会收到应用上报的性能数据,示例如下:
1 | { |
到这里,我们已经完成了APM Server和APM Agent的联调了。
实战演练
示例代码
下面的示例代码,会模拟一个现实API的工作场景:
- 服务启动后,功能演示如下:
1
2$ curl http://192.168.0.129:5000
i hava a uuid: beeca785-0022-4313-a2d4-0b26154e10af! I have been seen 1210 times. - 当接到请求时,查询并返回Redis中的数据(一个随机uuid)
- 在特定的场景下(用了一个随机数模拟),需要向另一个API请求数据,最后再存储到数据库中
- 通过redis计算页面的访问次数并显示
1 | from flask import Flask |
APM Server 输出到ES
为了更好地实现性能数据的存储和可视化,我们还需要借助ES和Kibana,笔者在之前的文章中已经完成了Kibana和ES的联调,这里就不多赘述。在本测试环境中,APM Server使用的配置文件内容如下:
1 | apm-server: |
API测试
使用ab工具,对测试API进行60秒压力测试,并发连接数10,测试结果如下:
1 | $ ab -c 10 -t 60 'http://192.168.0.129:5000/' |
在上面的Python代码中通过随机数去控制概率,会有一半的请求需要通过httpbin的接口获得UUID,所以最后返回时间的中位数是953ms。
在Kibana上的可视化
服务概况
我们可以在Kibana页面的”APM -> Service Name -> Overview”中查看业务的概况:
▲ Overview页面中可以直观地看到以服务器节点或者API路径为维度的延时、访问量的变化。
Metrics
▲ 也可以查看服务进程的CPU和内存使用情况。
Transactions
这是笔者最常用的一个功能, 查看特定API路径的运行情况,本文的demo只有一个GET /
:
▲ 在trace sample栏目可以看到APM Agent的采样,在timeline会显示该样本在处理这个请求时候每一个细分步骤和花费的时间。
▲ 这是返回时间958ms的一个样本,我们可以看到有954ms都花在了请求httpbin上。
What’s Next
笔者目前在一个手游项目上担任运维工程师,在项目筹备阶段就先后完善了系统和日志的监控,再到后来通过服务拨测功能也覆盖了部分关键游戏场景的业务监控。在前一段时间,为了在压测或者是日常运营的时候能更有效地对各个API接口进行优化,才引入了本文的介绍到的APM工具。
而当初在给开发团队推荐介绍Elastic APM的时候,也是从类似这样的demo开始的,当然在会议室里面那个demo是结合项目的实际API做的,功能和场景也会更丰富。
尽管已经说了很多,但搭建一个demo往往只是开始,到后面的调研、使用试点服务在测试环境反复打磨乃至上线到生产环境,期间也经历了更多深入的研究。比如说:使用现成的云产品还是自己搭建、各个模块之间的认证方式、APM Agent带来的性能损耗、对不同代码语言的改造方案、集群容量、APM Agent采集回来的数据类型、ES的索引模板、Kibana可视化方案等,都需要反复斟酌。
和本系列的文章类似,本文旨在提供一个思路,希望能给读者带去一点参考经验。