用PyPy加速Python代码
事情背景
我们业务服务使用了Metric+Graphite+Grafana这套业务指标收集系统,Graphite 可以实时收集、存储、显示时间序列类型的数据(time series data)。它主要有三个部分构成:
- graphite webapp —— 基于 Django 的网页应用程序。
- carbon —— 基于 Twisted 的进程,用来接收数据;
- whisper —— 专门存储时间序列类型数据的小型数据库;
线上业务众多数据收集量很大,采用了分布式的收集方案即前端carbon-relay按业务前缀转发到后端的容器和物理机carbon服务上,部署在容器的服务指标使用carbon-aggregator做聚合收集,部署在物理机的服务指标使用carbon-cache做收集。通过grafana配置graphite-web(这个graphite-web去连接后端多个carbon的graphite-web)来生成服务指标面板,根据业务需求配置图表展示和指标异常预警。
graphite-web去连接后端多个carbon的graphite-web这边经常出现下面的这种连接异常,出现问题时候graphite-web的Django进程使用CPU达到100%(单核跑满),grafana侧读取graphite数据为空从而触发很多的无效报警,给业务同学带来不好的体验。

排查优化
grafana配置的graphite-web源要访问后端全部carbon节点的graphite-web,先提升graphite-web访问本地whisper的速度,这块参考官方文档中的CARBONLINK_HOSTS配置,直接访问本地CACHE_QUERY_PORT,如下:
CARBONLINK_HOSTS = ['127.0.0.1:port']
graphite-web源访问后端全部carbon节点的graphite-web这条链路进行优化,查看网友的实践方案
参考:Graphite的百万Metrics实践之路 存储使用SSD、carbon-aggregator做聚合这些都已经实现,使用全套go方案重新的架构https://github.com/grobian/改起来也不现实,作者提到一个使用PyPy代替Python的方案,看起来可行。
PyPy 的官网https://speed.pypy.org ,看介绍比cpython还快

参考:用 PyPy 让你的 Python 代码运行得更快!本地mac上验证PyPy比Python快了35倍

mac上的Python是3.10版本,线上机器用的是Python2.7的版本,测试也有10倍的提升

安装PyPy
替换graphite机器(centos7.9)默认的Python
1、安装pypy
bunzip2 pypy2.7-v7.3.17-linux64.tar.bz2
tar -xvf pypy2.7-v7.3.17-linux64.tar
cp -r pypy2.7-v7.3.17-linux64 /usr/local/
2、安装依赖的库
yum install gcc-c++ libstdc++-devel lapack-devel lapack -y
/usr/local/pypy2.7-v7.3.17-linux64/bin/pypy -m ensurepip
/usr/local/pypy2.7-v7.3.17-linux64/bin/pypy -m pip install --upgrade pip
/usr/local/pypy2.7-v7.3.17-linux64/bin/pip install tagging parse cairocffi django==1.7.0 twisted==15.5.0 whisper numpy wheel
/usr/local/pypy2.7-v7.3.17-linux64/bin/pip install scipy
/usr/local/pypy2.7-v7.3.17-linux64/bin/pip install django-tagging
3、替换Python
ln -s /usr/local/pypy2.7-v7.3.17-linux64/bin/pypy python2
这样带来一个问题,yum就没有办法用了,需要修复一下yum依赖的Python配置
1.vim /usr/bin/yum
将#!/usr/bin/python改成#!/usr/bin/python2.7(默认python版本)
2.vim /usr/libexec/urlgrabber-ext-down
将#!/usr/bin/python改成#!/usr/bin/python2.7(默认python版本)
前面文章中提到PyPy 只适用于长时间运行的程序,刚好这个graphite-web就属于这类应用,替换后graphite-web的Django进程使用CPU维持在20%上下,网络连接也比之前减少了很多。


写在最后
使用PyPy替换Python带来的性能提升可以暂时满足我们的需求,持续运行了一个多月未再出现之前的异常情况,后续再出现架构瓶颈的话需要考虑其他的方案。