[转帖]一次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 原则,实现程序的重构.优化. ...
随机推荐
- 数据库的两个好帮手:pagehack和pg_xlogdump
摘要:pagehack和pg_xlogdump可以帮助我们在数据库故障定位中,解析各种文件的页面头和xlog日志. 随着技术的演进,数据也发生了巨大的变化,数据规模越来愈大.数据种类呈现多样性,数据处 ...
- Python中Round函数:怎么解释?怎么用?
摘要:在本文中,介绍了什么是round函数以及如何从python内核中实现它.同时,还介绍舍入函数的一些缺点,以及如何纠正它们,如何在数据科学中广泛使用的库中发挥作用. Python中的舍入函数,返回 ...
- 带你彻底搞懂高性能网络模式Reactor 和 Proactor
摘要:无论是 Reactor,还是 Proactor,都是一种基于「事件分发」的网络编程模式,区别在于 Reactor 模式是基于「待完成」的 I/O 事件,而 Proactor 模式则是基于 ...
- OpenHarmony移植案例:如何适配服务启动引导部件bootstrap_lite
摘要:本文介绍了startup子系统之bootstrap_lite服务启动引导部件的移植适配案例及原理. 本文分享自华为云社区<OpenHarmony移植案例与原理 - startup子系统之b ...
- 没想到,学棋五年的我竟然输给了昇腾CANN!
摘要:整整两天,上百场对弈,TA竟然未尝一败,真是让人拍案叫绝. 近日,一位神秘"人物"亮相华为昇腾CANN技术开放日现场,引得众人簇拥,吸粉无数.从现场AI棋艺大战的画面中我们可 ...
- Solon 开发进阶,二、体外扩展机制
Solon 开发进阶 一.插件扩展机制 二.体外扩展机制 三.常用配置说明 四.启动参数说明 五.全局异常订阅 Solon 的一个特色:体外扩展机制,用于解决 fatjar 模式部署时的扩展需求.比如 ...
- 鸿蒙HarmonyOS实战-ArkTS语言(基本语法)
一.ArkTS语言基本语法 1.简介 HarmonyOS的ArkTS语言是一种基于TypeScript开发的语言,它专为HarmonyOS系统开发而设计.ArkTS语言结合了JavaScript的灵活 ...
- 【计算机网络】soap和rest简单比较整理
https://www.bilibili.com/video/BV1ht411U7fC/?spm_id_from=333.337.search-card.all.click&vd_source ...
- 【网络爬虫学习】Python 爬虫初步
本系列基于 C语言中文网的 Python爬虫教程(从入门到精通)来进行学习的, 部分转载的文章内容仅作学习使用! 前言 网络爬虫又称网络蜘蛛.网络机器人,它是一种按照一定的规则自动浏览.检索网页信息的 ...
- Linux mknod命令详解
Linux一切皆文件,系统与设备通信之前,要建立一个存放在/dev目录下的设备文件,默认情况下就已经生成了很多设备文件,有时候自己手动新建一些设备文件,这就会用到mknod. 语法格式:mknod[选 ...