关于python进程在linxu运行时接受MQ消息阻塞一段时候后在进行业务交易时会在固定代码卡住固定时间问题

1、背景:我们的系统本身逻辑已经十分成熟,在给另一家公司生产环境部署时,回归验证时发生了这个问题。

2、问题描述:我们的主要业务处理应用是由python代码写的,多个进程,进程之间通过mq消息队列传递消息。当代码处于等待mq的消息时,进程会处于阻塞状态。我们其中的一个进程在阻塞了超过二十多分钟后,接受到mq的消息后继续执行时,会在固定的数据库操作中卡住15至16分钟,卡完后会抛出数据库异常ORA-03113: 通信通道的文件结尾,后续由于我们封装的执行数据库操作的函数在检测到规定内的异常时会尝试重新建立数据库连接,后续就不会在卡住。卡住一次后的二十分钟左右内的交易不会再次卡住,之后便会再次卡住。

3、问题分析:经过打印日志排查,确定了卡主的地方是在执行数据库操作时,并且由于卡主的时间比较固定,分析是Oracle数据库的一个空闲连接超过一定时间后便会自动清理连接的设置导致的。

由于我们的python代码并未用到数据库连接池,无法进行心跳检测连接是否还可用。当应用起来之后只会初始化一次数据库连接,后续一直用同一个,当等待mq超过一定时间后,数据库服务端单方面将连接清理,但我们的代码对此是感知不到的,由此会发生系统流程卡住一定时间的现象,而且是偶现的。并且我们排除了卡住是由于系统资源不足导致的进程阻塞。

解决方案1:在每次交易时新建数据库连接。

结论1:这种方案确实有一点效果,但是当我这样做后,发现代码还是会卡,但这次代码是卡在了读取excel的地方,而且现象和刚开始的问题是一样的。这个现象是十分矛盾的,问题现象是和数据库连接相关的现象,但代码实际卡住的地方并未进行数据库操作,我们陷入了迷茫。对此,为了进一步排查是哪里卡住了,怀疑可能是句柄泄露导致的,我们修复了句柄泄露问题(不管用)。让现场运维安装了个strace工具,该工具可以打印出来监听的进程id所调用的操作系统提供的具体函数,然后在进行交易前执行该命令,发现卡住在这个函数read(句柄ID,),但我们发现这个句柄ID并不是读取excel相关的句柄ID。openat(句柄ID,”文件名“)。也不是recvfrom()函数建立的句柄ID,而是打开共享内存的某个文件/dev/shm/xxx。但这无法得知该句柄是关于什么的。但发现卡住之后立即就执行了write()函数,文件是Oracle客户端的某个地方的一个错误日志。打开日志文件后发现了一些错误信息。对此,我们可以确定,卡住的原因并不是由于读取excel文件,还是有由于数据连接。

对此我们将代码修改成了plan b

解决方案2:在主函数中加一个线程,每个五分钟执行一个select 1 from dual,让数据库服务端不在自动清理该数据库连接,进程还是只用一个数据库连接。

结论2:可行,相当于模拟了连接池的心跳检测,但是消耗的性能更多点。

当发现问题并不是代码层面的问题,使用strace命令看到进程具体在执行什么,具体卡住在哪里,以及卡住之后干了什么是比较好用的。因为我们使用方案1取跑的时候,他在卡住后不会抛出异常,后续就正常跑了,发生了啥、为啥卡住是看不出来的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fake-WTX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值