postman触发任务处理,长时间未响应时,自动retry,导致SFTP连接意外中断

背景

今天写了一个数据处理任务,用于后端定时触发。并为这个定时任务提供了一个触发接口,用于手动触发。
这个任务的处理逻辑,大概是从SFTP上拉取文件,并对文件进行解析。任务写完后,在测试时,数据量较少,并未发现问题。

现象

今天在正式环境手动触发任务时,由于处理时间较长,大概在30分钟左右。开始时,任务处理正常。处理了一段时间后,任务持续报异常,后台日志持续飘红。跟踪日志发现,SFTP连接被意外中断,导致任务处理失败。即使程序自动重新创建连接,仍然会被意外中断。

重试多次,现象可以复现,且均是出现在任务执行一段时间之后。

通过在任务处理的入口处增加日志,发现了问题原因。一段时间之后,后端收到了第二次任务处理的请求。第二次任务处理时,对第一次还未执行完成的任务造成了影响。

但是又有了两个问题:

  1. 第二次触发的请求是哪里来的?我用postman只触发了一次请求,且这次请求的结果还未返回。
  2. 为什么第二次的任务处理会关闭第一次的任务连接。

猜想

  1. 第二次请求
    通过观察,猜想,第二次请求是postman触发的。因请求长时间未得到响应,所以postman自动触发了一次重试。于是,我再次使用postman触发任务,并取消postman的等待响应。10分钟之后,后端未收到二次请求,且第一次任务正常执行完成。由此可知,postman在一段时间内未得到响应,将触发重试。
  2. 关闭连接
    通过查看代码发现,SFTP的连接工具类,使用的是单例模式,且共享一个连接。于是第二个任务在调用关闭处理时,第一次任务的连接也被关闭了。于是后端出现了连接意外关闭的错误。

解决方案

  1. 针对postman自动重试,如果不经常使用,可以考虑在触发任务后,手动停止postman的响应等待。但如果接口调用频繁的话,需要做特殊处理。此处提供几个思路。
  • 将任务处理包装成线程任务。在接口触发时,创建一个线程任务,另起线程执行,同时返回接口响应。对于这种方式,需要考虑接口的并发处理。
  • 使用内存锁,任务触发时,获取内存锁,如果获取到则触发任务执行,否则直接返回。该方式,可以阻断postman的自动重试。但同时也会阻止手动的重复执行,有利有弊。
  1. 针对连接异常关闭
    如果是单线程模式,则无需过多处理。
    对于并发模式,则可以考虑避免使用单例模式的连接管理。考虑将SFTP的连接进行池化管理。采用连接池,可以避免不同任务中的连接影响。

2022/11/23 更新
这个问题,后来做了一些优化,同步一下,仅供参考:

  1. 如果接口只希望单线程处理,则增加内存锁,防止并发,如上文中所说。
  2. 如果接口希望可以支持多线程并发处理,则需要对接口做相应改造。改造方案如下:
    • SFTP 连接进行池化处理(最优解法)
      池化处理的SFTP连接,避免在业务代码中进行SFTP连接和关闭处理,从而一劳永逸的支持代码的并发处理。
    • SFTP 连接关闭时,进行判断后关闭
      如果不进行池化处理,则可以采用在连接关闭时,判断是否还有未完成的处理线程,如果有,则不关闭的。让最后处理完的线程关闭连接。此种方式,能简单修复,但应对并发处理时,显得不够优雅。且在高并发场景下,依然存在问题。
    • 使用线程变量 ThreadLocal
      使用现成变量,让每个线程都去建立一个连接,而不是多个线程复用连接。这种方式存在风险,如果线程开启数量超过了SFTP允许的连接数,可能导致连接失败。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值