[转帖]一次python服务的性能优化经历
https://juejin.cn/post/7208708762265616421
问题背景:
在我们的业务中,有一些推荐的场景会需要走到集团研究院的算法推荐服务,对一些用户进行个性化的课件推荐或者作者推荐,这个业务场景已经很久了,但是一直有一个很难解决的问题困扰着我们,就是我们调用研究院的接口经常性的出现偶发性的接口超时,频率还比较高。
初步排查过程:
一开始以为是研究院的推荐服务有性能问题,因为不了解推荐服务的实现逻辑,觉得算法推荐要基于大量的数据进行计算再生成结果,会不会是推荐服务里面超时了,但是和研究院的同事沟通后,他们的服务整体上的耗时有1秒的,但是一整天只有197个,完全对不上。
最后找运维确定了下整个网络链路,如下,感谢公司运维大佬的指点和分析。
因为业务侧的服务都在公有云上,然后算法侧基于软硬件成本等原因,整体的服务都在内网的服务器上,中间通过公有网络访问,中间也没有拉专线,所以整体的网络耗时非常的不稳定,另外由于公有云现在都在杭州,内网的服务都在广州,因为跨地域的问题,本身的网络耗时也是会有一定的影响。
初步解决方案:
因此和运维大佬讨论后有两种解决方案:
- 公有云和私有云之间拉一条专线,解决网络不稳定的问题
- 推荐服务上云,不存在跨云调用。
针对两种解决方案,我们做了如下的沟通和讨论:
拉专线的好处就是网络耗时会稳定很多,但是缺点就是成本会比较大,如果只是解决这个问题,就要一条专线会有些浪费,其次就是专线只能只能解决稳定性,但是跨地域的问题还是依旧存在
方案2和研究院的同事沟通后,如果整体上云,不太现实,一则是他们的改动太大,另外就是对我们公司来说云上的进行算法计算的成本相对于内网会高很多。
在这样的背景下,原本是想计划申请一条专线解决的,但是再次和研究院的同事深入沟通后,发现其实整体的算法推荐逻辑是 "预先的离线计算推荐结果 + 实时结果查询",也就是存算分离的,也就是我们实时查询时只是查询结果,并不进行计算,而且他们的结果都是存在redis中的,并且算法离线计算每天只计算一次。
因此我们想到一个改造方案,能不能只将推荐服务上云,算法推荐的结果想办法同步到云上去就行。
redis数据上云的方案:
- 运维开发公有云redis的访问,内网的离线计算服务可以直接写入公有云的redis,改造非常简单,只需要离线计算和推荐服务修改redis地址即可。
- 开发redis数据同步服务,通过一层带鉴权和网关限制的http接口开放内网的redis有限的(固定key格式)数据访问接口,将数据同步到公有云的redis
方案1的话需要开发公有云的redis访问,和运维同学沟通过后,基于安全性和公司内部规则的约定(云上的redis禁止外网开发),方案1放弃。方案二我们分析过,因为离线计算一次后,数据当天内不在进行变更,同时数据量很小只有几十MB,因此我们选择了做一个简单的数据同步方案进行,整体的成本也很低。若下图所示
初步优化效果:
我们将用户的请求从一个要经过公网的链路,转换为内网的redis查询,不再有网络的不稳定和延时的影响,整体的性能有了大幅改善。
平均耗时基本已经在0.00Xms级别返回了,就真的是纯redis的耗时。
再次排查过程:
问题现象:
但是不管是我们的告警,还是再一步分析发现还是会出现很多超过一秒的超时请求,特别是在早上高峰期的时候,虽然平均耗时很低,整体的超时请求数量不多,但是还是会有影响,也不科学,因为理论上都走了内网,该接口的操作也仅仅是查询ES, 不应该有这么多的超时,其次也怀疑过是服务器负载的问题,也尝试了扩容服务器节点,发现效果不佳。
排查思路1:
因为请求推荐服务会需要过一层nginx,会不会是nginx 有问题导致的请求延迟,所以我们需要验证下,我们绕过nginx,直接访问本机来测试,本机会不会出现也会有延迟超过一秒的情况, 在本机通过ab压测和抓包发现,确实有超过0.5S,甚至是1s的请求出现
那就是证明了确实代码本身确实存在问题,在压测的情况下,确实会出现超时的情况,这个也就能够说明,为什么在早上高峰期的时候才会出现。
排查思路2:
通过上面的测试和分析,我们现在就到了怎么排查出代码本身存在的问题,因为研究院算法工程部用的技术栈都是python,推荐服务也是python写的,本人是java技术栈的,本身对python不慎了解,初步看了下代码,发现也是仅仅是redis的查询处理,而且也用到了python的redis连接池(专门去研究了下python中的 StrictRedis, 发现 StrictRedis 如果不用连接池,其实默认也出创建连接池的)
这块就有点诡异了,想不明白,为什么简简单单的redis查询,会有出现超时的情况,有些黔驴技穷了,这个时候没办法了,只能用上绝招火焰图了,不管是java还是python,都是有堆栈了,我们都是可以通过火焰图去抓取下火焰图,看看火焰图上有没有什么线索。
尝试学习了下python火焰图的抓取工具,没想到python还有自带的火焰图的工具 py-spy,采用了 py-spy record -o profile.svg --p pid,非常方便,没想到抓取出来还真发现了线索。
问题点
- 从火焰图上看,redis建连占用的cpu非常多
- 日志的打印占用的cpu很多
问题2 比较好解决,我们只要把打印最多的日志找到禁止打印就行,但是问题1就很奇怪了,为什么用到了连接池,但是在火焰图上看还是在依旧创建连接。我们抓包验证下,果然发现每次请求访问redis都在新建连接。
那就是代码本身肯定有问题了重新查看代码, 从代码逻辑上看,StrictRedis是在__ init __方法中初始化的, 连接池是没有问题的,本地单元测试过,那么如果有问题的话那就是 init 方法每次都执行,简单验证debug下竟然果然如此。
再来仔细分析了下 __ init __ 方法,发现这个方法并不是全局的,而是对每个请求初始化了,因此其实每次请求就要都执行 init方法,然后我们 init方法中又进行了redis的连接池初始化操作,那就很能说的通为什么每次请求都是新建redis 连接了
修改方案:
修改的方式也就很简单了,只需要将代码中的redis连接池的初始化换成全局的就行,如下
优化后的结果从抓包和连接数上看也是符合预期了
二次优化效果:
整体的耗时相比较改善前有一些下降,虽然是0.00Xs,但是超时的请求再也没有出现过
总结:
这次的优化经历整体上不算太难,但是因为整个优化涉及到里多业务的整体方案设计,不熟悉的技术栈的问题排查,所以觉得有一定的分享价值,另外个人觉得性能优化是一个系列性的问题,需要考验的点有很多,有整体的方案,有细节的分析,有工具的使用,但是更多的是对每个小点都去深究,不放过,死磕到底的态度,慢慢的会的会越来越多,经验也会越来越深!!!
[转帖]一次python服务的性能优化经历的更多相关文章
- Java服务端性能优化
<Java程序性能优化>说性能优化包含五个层次:设计调优.代码调优.JVM调优.数据库调优.操作系统调优. 常用的几个代码优化方案: 使用单例 对于IO处理.数据库连接.配置文件解析加载等 ...
- [daily][optimize] 一个小python程序的性能优化 (python类型转换函数引申的性能优化)
前天,20161012,到望京面试.第四个职位,终于进了二面.好么,结果人力安排完了面试时间竟然没有通知我,也没有收到短信邀请.如果没有短信邀请门口的保安大哥是不让我进去大厦的.然后,我在11号接到了 ...
- python可变交换性能优化
离许多新的压力python性能优化见交换两个变量值可以使用 a,b = b,a 这样能够提高性能 >>> from timeit import Timer >>> ...
- 大规模服务网格性能优化 | Aeraki xDS 按需加载
作者 钟华,腾讯云专家工程师,Istio project member.contributor,专注于容器和服务网格,在容器化和服务网格生产落地方面具有丰富经验,目前负责 Tencent Cloud ...
- 人人都能掌握的Java服务端性能优化方案
作为一个Java后端开发,我们写出的大部分代码都决定着用户的使用体验.如果我们的后端代码性能不好,那么用户在访问我们的网站时就要浪费一些时间等待服务器的响应.这就可能导致用户投诉甚至用户的流失. 关于 ...
- 一次EF批量插入多表数据的性能优化经历
距离上次的博客已经有15个多月了,感慨有些事情还是需要坚持,一旦停下来很有可能就会停很久或者从此再也不会坚持.但我个人一直还坚持认为属于技术狂热份子,且喜欢精益求精的那种.最近遇到两个和数据迁移相关的 ...
- Python 3.9 性能优化:更快的 list()、dict() 和 range() 等内置类型
Python 的 3.9.0 版本正在开发中,计划在 2020-10-05 发布 final 版本. 官方在 changelog 中披露了很多细节,其中有一项"vectorcall" ...
- python django ORM 性能优化 select_related & prefetch_related
q = models.UserInfo.objects.all() select * from userinfo select * from userinfo inner join usertype ...
- Python代码性能优化技巧
摘要:代码优化能够让程序运行更快,可以提高程序的执行效率等,对于一名软件开发人员来说,如何优化代码,从哪里入手进行优化?这些都是他们十分关心的问题.本文着重讲了如何优化Python代码,看完一定会让你 ...
- Python 代码性能优化技巧(转)
原文:Python 代码性能优化技巧 Python 代码优化常见技巧 代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化. ...
随机推荐
- 30亿参数,华为云发布全球最大预训练模型,开启工业化AI开发新模式
摘要: 4月25日,华为云发布盘古系列超大规模预训练模型,包括30亿参数的全球最大视觉(CV)预训练模型,以及与循环智能.鹏城实验室联合开发的千亿参数.40TB训练数据的全球最大中文语言(NLP)预训 ...
- 跟我学AI建模:分子动力学仿真模拟之DeepMD-kit框架
摘要:分子动力学仿真模拟的重点就在于如何建立模型描述分子间的相互作用. 本文分享自华为云社区<AI建模-分子动力学仿真>,作者: 木子_007 . 一.背景 分子动力学的仿真模拟广泛应用于 ...
- 带你全方面了解字节 A/B 实验的文化与工具
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 A/B 测试是在相同的环境下,通过随机的抽样把对照组和控制组进行区分,并分别实行新旧两种策略,结合一定的统计方法来 ...
- 查看Windows系统 重启时间
查看Windows系统 重启时间 CMD 命令 systeminfo 事件查看器 筛选:1074 6005: 开机时间.6006:关机时间
- JMeter 源码解读 - HashTree
背景: 在 JMeter 中,HashTree 是一种用于组织和管理测试计划元素的数据结构.它是一个基于 LinkedHashMap 的特殊实现,提供了一种层次结构的方式来存储和表示测试计划的各个组件 ...
- Java Kafka 消费积压监控
Java Kafka 消费积压监控 后端代码: Monitor.java代码: package com.suncreate.kafkaConsumerMonitor.service; import c ...
- BZOJ 3450 - Tyvj1952 Easy (期望DP)
描述 某一天 WJMZBMR 在打 osu~~~ 但是他太弱逼了,有些地方完全靠运气:( 我们来简化一下这个游戏的规则: 有 \(n(n\le 300000)\) 次点击要做,成功了就是 o,失败了就 ...
- 数字孪生 3D 风电场,智慧风电之陆上风电
前言 "十四五"期间,在传统产业数字化升级和绿色改造领域.绿色低碳城镇化和现代城市建设领域.绿色低碳消费领域,和可再生能源或电力系统建设等领域,总投资可以达到近 45 万亿,平均每 ...
- 写了个移动端可滑动(惯性滑动&回弹)Vue导航栏组件 ly-tab
https://www.imooc.com/article/23768?block_id=tuijian_wz https://blog.csdn.net/weixin_44614772/articl ...
- [Qt开发/毕业设计/求职项目]局域网环境下远程文件发送部署系统-服务端、客户端双端的讲解
写在前面 本文旨在做一个简单的代码讲解,我会给出源码,然后整个代码的讲解都在源码的基础上进行. 代码可能会随着更新而进行修改,但是整体框架变化不会太大. 整个文章内容不会太多,算是我自己的一个复盘,整 ...