https://juejin.cn/post/7208708762265616421

问题背景:

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

初步排查过程:

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

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

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

初步解决方案:

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

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

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

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

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

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

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

redis数据上云的方案:

  1. 运维开发公有云redis的访问,内网的离线计算服务可以直接写入公有云的redis,改造非常简单,只需要离线计算和推荐服务修改redis地址即可。
  2. 开发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,非常方便,没想到抓取出来还真发现了线索。

问题点

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

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

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

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

修改方案:

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

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

二次优化效果:

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

总结:

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

[转帖]一次python服务的性能优化经历的更多相关文章

  1. Java服务端性能优化

    <Java程序性能优化>说性能优化包含五个层次:设计调优.代码调优.JVM调优.数据库调优.操作系统调优. 常用的几个代码优化方案: 使用单例 对于IO处理.数据库连接.配置文件解析加载等 ...

  2. [daily][optimize] 一个小python程序的性能优化 (python类型转换函数引申的性能优化)

    前天,20161012,到望京面试.第四个职位,终于进了二面.好么,结果人力安排完了面试时间竟然没有通知我,也没有收到短信邀请.如果没有短信邀请门口的保安大哥是不让我进去大厦的.然后,我在11号接到了 ...

  3. python可变交换性能优化

    离许多新的压力python性能优化见交换两个变量值可以使用 a,b = b,a 这样能够提高性能 >>> from timeit import Timer >>> ...

  4. 大规模服务网格性能优化 | Aeraki xDS 按需加载

    作者 钟华,腾讯云专家工程师,Istio project member.contributor,专注于容器和服务网格,在容器化和服务网格生产落地方面具有丰富经验,目前负责 Tencent Cloud ...

  5. 人人都能掌握的Java服务端性能优化方案

    作为一个Java后端开发,我们写出的大部分代码都决定着用户的使用体验.如果我们的后端代码性能不好,那么用户在访问我们的网站时就要浪费一些时间等待服务器的响应.这就可能导致用户投诉甚至用户的流失. 关于 ...

  6. 一次EF批量插入多表数据的性能优化经历

    距离上次的博客已经有15个多月了,感慨有些事情还是需要坚持,一旦停下来很有可能就会停很久或者从此再也不会坚持.但我个人一直还坚持认为属于技术狂热份子,且喜欢精益求精的那种.最近遇到两个和数据迁移相关的 ...

  7. Python 3.9 性能优化:更快的 list()、dict() 和 range() 等内置类型

    Python 的 3.9.0 版本正在开发中,计划在 2020-10-05 发布 final 版本. 官方在 changelog 中披露了很多细节,其中有一项"vectorcall" ...

  8. python django ORM 性能优化 select_related & prefetch_related

    q = models.UserInfo.objects.all() select * from userinfo select * from userinfo inner join usertype ...

  9. Python代码性能优化技巧

    摘要:代码优化能够让程序运行更快,可以提高程序的执行效率等,对于一名软件开发人员来说,如何优化代码,从哪里入手进行优化?这些都是他们十分关心的问题.本文着重讲了如何优化Python代码,看完一定会让你 ...

  10. Python 代码性能优化技巧(转)

    原文:Python 代码性能优化技巧 Python 代码优化常见技巧 代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化. ...

随机推荐

  1. 2021平(jia)凡(ban)的一年

    0x00 刚刚把<平凡的世界>电视剧看完.也不知道什么原因,又去刷了一遍, 可能是有那么一段时间比较迷茫.加班加到怀疑人生了吧. 记得当年第一次看这本小说还是17年,好像是为了借一本什么书 ...

  2. 关于汽车OTA,这篇科普文能告诉你

    随着汽车中软件发挥的作用越来越重要,软件定义汽车已经是行业内的共识.汽车行业的发展极有可能最终像手机产业一样,基础硬件差异会越来越小,关键在于汽车给用户的体验的多样性,以及汽车产品在不同场景下满足用户 ...

  3. 一文读懂GaussDB(openGauss) 的六大关键技术特性

    摘要:更为深入地介绍了GaussDB(openGauss)的关键特性.成功案例. GaussDB(openGauss)是深度融合华为在数据库领域多年的经验,结合企业级场景需求,推出的新一代企业级分布式 ...

  4. GaussDB(DWS)发生数据倾斜不要慌,一文教你轻松获取表倾斜率

    摘要:GaussDB(DWS)是MPP并行架构,若表的数据存在倾斜情况,会引起一系列性能问题,影响用户体验,严重时可能会引起系统故障.因此能快速获取倾斜的表并整改是GaussDB(DWS)运维管理人员 ...

  5. AI如何提升10倍筛药效率?6月18日华为云携手中科院上海药物所揭开谜底

    摘要:6月18日,华为云TechWave全球技术峰会(人工智能&数据)围绕人工智能.大数据.数据库.华为云Stack等热点话题,携手来自全球的IT精英.技术大咖.先锋企业.合作伙伴共话前沿技术 ...

  6. CWE 视图层级关系解析:节点关系查询

    本文分享自华为云社区<CWE视图层级关系的解析 之 CWE节点关系的查询>,作者: Uncle_Tom. 1. CWE 转换成 SQLite 表 依据<CWE视图层级关系的解析 之 ...

  7. 聊聊Hive数据血缘——从Atlas没有列级血缘的Bug讲起

    前几天,Datahub提供了最新的字段级别数据血缘功能,很多朋友迫不及待想对比一下Datahub的字段级血缘与Atlas的区别. 这个时候问题来了,在Atlas收集Hive血缘的时候,由于部分版本问题 ...

  8. 玩转Python:在Python中处理表格数据,几个非常流行且功能强大的库

    在Python中处理表格数据,有几个非常流行且功能强大的库.以下是一些最常用的库及其示例代码: 1. Pandas Pandas是一个开放源代码的.BSD许可的库,为Python编程语言提供高性能.易 ...

  9. GO语言之环境搭建和基本命令

    目录 go语言基础 下载go编译器 go目录简介 gopath简介 环境变量配置 GOPATH PATH go语言项目结构 IDE下载与配置 安装goland goland里添加goroot和gopa ...

  10. ME21N 采购订单批导

    1业务场景 事务代码:ME21N创建采购订单 可以通过BAPI_PO_CREATE1批量创建 2代码实现 1.抬头 2.行项目 3.增强 抬头增强字段放在BAPI_TE_MEPOHEADER结构中的C ...