一次python服务的性能优化经历

问题背景:

​ 在我们的业务中,有一些推荐的场景会需要走到集团研究院的算法推荐服务,对一些用户进行个性化的课件推荐或者作者推荐,这个业务场景已经很久了,但是一直有一个很难解决的问题困扰着我们,就是我们调用研究院的接口经常性的出现偶发性的接口超时,频率还比较高。

企业微信截图_7d6fdf5b-99f2-4516-85f0-ec638584492f

image-20230309224020119

初步排查过程:

一开始以为是研究院的推荐服务有性能问题,因为不了解推荐服务的实现逻辑,觉得算法推荐要基于大量的数据进行计算再生成结果,会不会是推荐服务里面超时了,但是和研究院的同事沟通后,他们的服务整体上的耗时有1秒的,但是一整天只有197个,完全对不上。

image-20230309092956102

最后找运维确定了下整个网络链路,如下,感谢公司运维大佬的指点和分析。

image-20230309141059985 因为业务侧的服务都在公有云上,然后算法侧基于软硬件成本等原因,整体的服务都在内网的服务器上,中间通过公有网络访问,中间也没有拉专线,所以整体的网络耗时非常的不稳定,另外由于公有云现在都在杭州,内网的服务都在广州,因为跨地域的问题,本身的网络耗时也是会有一定的影响。

初步解决方案:

因此和运维大佬讨论后有两种解决方案:

  1. 公有云和私有云之间拉一条专线,解决网络不稳定的问题
  2. 推荐服务上云,不存在跨云调用。

针对两种解决方案,我们做了如下的沟通和讨论:

  1. 拉专线的好处就是网络耗时会稳定很多,但是缺点就是成本会比较大,如果只是解决这个问题,就要一条专线会有些浪费,其次就是专线只能只能解决稳定性,但是跨地域的问题还是依旧存在

  2. 方案2和研究院的同事沟通后,如果整体上云,不太现实,一则是他们的改动太大,另外就是对我们公司来说云上的进行算法计算的成本相对于内网会高很多。

在这样的背景下,原本是想计划申请一条专线解决的,但是再次和研究院的同事深入沟通后,发现其实整体的算法推荐逻辑是 “预先的离线计算推荐结果 + 实时结果查询”,也就是存算分离的,也就是我们实时查询时只是查询结果,并不进行计算,而且他们的结果都是存在redis中的,并且算法离线计算每天只计算一次。

image-20230309164058906

因此我们想到一个改造方案,能不能只将推荐服务上云,算法推荐的结果想办法同步到云上去就行。

redis数据上云的方案:

  1. 运维开发公有云redis的访问,内网的离线计算服务可以直接写入公有云的redis,改造非常简单,只需要离线计算和推荐服务修改redis地址即可。
  2. 开发redis数据同步服务,通过一层带鉴权和网关限制的http接口开放内网的redis有限的(固定key格式)数据访问接口,将数据同步到公有云的redis

方案1的话需要开发公有云的redis访问,和运维同学沟通过后,基于安全性和公司内部规则的约定(云上的redis禁止外网开发),方案1放弃。方案二我们分析过,因为离线计算一次后,数据当天内不在进行变更,同时数据量很小只有几十MB,因此我们选择了做一个简单的数据同步方案进行,整体的成本也很低。若下图所示

image-20230309191831445

初步优化效果:

我们将用户的请求从一个要经过公网的链路,转换为内网的redis查询,不再有网络的不稳定和延时的影响,整体的性能有了大幅改善。

平均耗时基本已经在0.00Xms级别返回了,就真的是纯redis的耗时。

image-20230309191621272

再次排查过程:

问题现象:

但是不管是我们的告警,还是再一步分析发现还是会出现很多超过一秒的超时请求,特别是在早上高峰期的时候,虽然平均耗时很低,整体的超时请求数量不多,但是还是会有影响,也不科学,因为理论上都走了内网,该接口的操作也仅仅是查询ES, 不应该有这么多的超时,其次也怀疑过是服务器负载的问题,也尝试了扩容服务器节点,发现效果不佳。

image-20230309191624891

image-20230309172433273

排查思路1:

因为请求推荐服务会需要过一层nginx,会不会是nginx 有问题导致的请求延迟,所以我们需要验证下,我们绕过nginx,直接访问本机来测试,本机会不会出现也会有延迟超过一秒的情况, 在本机通过ab压测和抓包发现,确实有超过0.5S,甚至是1s的请求出现

image-20230309195501316

那就是证明了确实代码本身确实存在问题,在压测的情况下,确实会出现超时的情况,这个也就能够说明,为什么在早上高峰期的时候才会出现。

排查思路2:

通过上面的测试和分析,我们现在就到了怎么排查出代码本身存在的问题,因为研究院算法工程部用的技术栈都是python,推荐服务也是python写的,本人是java技术栈的,本身对python不慎了解,初步看了下代码,发现也是仅仅是redis的查询处理,而且也用到了python的redis连接池(专门去研究了下python中的 StrictRedis, 发现 StrictRedis 如果不用连接池,其实默认也出创建连接池的

image-20230309200435667

这块就有点诡异了,想不明白,为什么简简单单的redis查询,会有出现超时的情况,有些黔驴技穷了,这个时候没办法了,只能用上绝招火焰图了,不管是java还是python,都是有堆栈了,我们都是可以通过火焰图去抓取下火焰图,看看火焰图上有没有什么线索。

尝试学习了下python火焰图的抓取工具,没想到python还有自带的火焰图的工具 py-spy,采用了 py-spy record -o profile.svg --p pid,非常方便,没想到抓取出来还真发现了线索。

image-20230309201209357

问题点
  1. 从火焰图上看,redis建连占用的cpu非常多
  2. 日志的打印占用的cpu很多

问题2 比较好解决,我们只要把打印最多的日志找到禁止打印就行,但是问题1就很奇怪了,为什么用到了连接池,但是在火焰图上看还是在依旧创建连接。我们抓包验证下,果然发现每次请求访问redis都在新建连接。

image-20230309202405789

image-20230309222831075

那就是代码本身肯定有问题了重新查看代码, 从代码逻辑上看,StrictRedis是在__ init __方法中初始化的, 连接池是没有问题的,本地单元测试过,那么如果有问题的话那就是 init 方法每次都执行,简单验证debug下竟然果然如此。

image-20230309220151038

再来仔细分析了下 __ init __ 方法,发现这个方法并不是全局的,而是对每个请求初始化了,因此其实每次请求就要都执行 init方法,然后我们 init方法中又进行了redis的连接池初始化操作,那就很能说的通为什么每次请求都是新建redis 连接了

image-20230309222603926

修改方案:

修改的方式也就很简单了,只需要将代码中的redis连接池的初始化换成全局的就行,如下

image-20230309223108442

优化后的结果从抓包和连接数上看也是符合预期了

image-20230309223530246

二次优化效果:

整体的耗时相比较改善前有一些下降,虽然是0.00Xs,但是超时的请求再也没有出现过

image-20230309224147802

image-20230309224700427

总结:

这次的优化经历整体上不算太难,但是因为整个优化涉及到里多业务的整体方案设计,不熟悉的技术栈的问题排查,所以觉得有一定的分享价值,另外个人觉得性能优化是一个系列性的问题,需要考验的点有很多,有整体的方案,有细节的分析,有工具的使用,但是更多的是对每个小点都去深究,不放过,死磕到底的态度,慢慢的会的会越来越多,经验也会越来越深!!!

---------------------------END---------------------------

题外话

当下这个大数据时代不掌握一门编程语言怎么跟的上时代呢?当下最火的编程语言Python前景一片光明!如果你也想跟上时代提升自己那么请看一下.

在这里插入图片描述

感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。


👉优快云大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img
img

二、Python必备开发工具

工具都帮大家整理好了,安装就可直接上手!img

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、Python视频合集

观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

img

五、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

六、面试宝典

在这里插入图片描述

在这里插入图片描述

简历模板在这里插入图片描述

👉优快云大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

若有侵权,请联系删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值