记一次线上BUG - pdf转图片

11 篇文章 0 订阅

先吐槽一下

最近接手一个项目,前任代码非常烂,如果骂人等于杀人,那么他不知道死了多少回了。
1、项目代码是从以前几个项目中拼凑来的,本身就很烂,没有全局处理器,包含很多以前的无用代码,勉强能用。
2、mybatis动态SQL全部字符串拼接,不能防sql注入攻击。
3、批量插入和更新数据库用for循环。
4、随意使用数据库事务,该加事务时不加,不该加时乱加,controller层写大量业务逻辑和操作数据库代码。
5、前端不能防csrf、xss攻击。
6、前端代码只是功能的堆砌,以报错bug掩盖其他bug,在现代浏览器中勉强能用。
7、接口参数没有安全校验。
8、如果接口必输项为空,则直接返回成功,没有日志记录。
9、一个简单的业务,提供很多接口,由客户端一个一个的按顺序调起,没有注释。
10、接口响应数据格式不统一,没有兜底响应数据,有些异常响应数据丢失字段。
11、使用全局属性封装数据,不考虑线程安全问题。
12、随意加锁,降低服务吞吐量。
13、捕获异常不处理,吃异常信息,日志多为e.printStackTrace();和System.out.println。
14、有些异常日志只输出e.getMessage(),不打印堆栈信息。
15、工具方法百度搜索直接粘在项目里用,一点也不改动。

bug感性描述

前几天客户反馈,上传pdf文件时,个别文件提示上传失败,有的多试几次就成功了,有的一直没成功,没成功的数据也入库了,但是查不到详细信息。

定位bug

于是安排一波,申请查看生产日志。终于在日志找到了一行:Coordinate out of bounds!(正对应第14条吐槽)。
这是什么鬼?赶紧看源码,发现,controller的一个方法里写了1000多行,还执行多次更新SQL,异常日志里只输出了e.getMessage()。
查生产数据库,发现pdf转图片后的SQL在表中没有记录,文件系统中也没找到转后的图片,初步判断是pdf转图片时报错了。

复现bug

向客户要了上传失败的文件,在本地测试,都上传功能了,在开发环境window系统和linux系统测试也都成功了。最怕这事,唉,头大!
百度查找该bug相关信息,一个一个验证都不是想要的信息。
有说是第三方包的bug,查看代码里的jar包,是fontbox-2.0.1.jar、pdfbox-2.0.6.jar,版本不一致,确实存在问题。生产环境的系统是Neokylin,网上找不到更多的信息了。
好在准生产环境也是Neokylin系统,申请在准生产环境试试,哈哈bug复现了。
怎么修复呢?升级jar包?于是改用了fontbox-2.0.12.jar、pdfbox-2.0.12.jar,重启项目后,上传发生失败的文件,哎,在期待中成功了,一切是那么的理想当然。
秉着谨慎的态度,又上传了一遍,呃,失败了?!证明升级jar包的方式并无什么卵用。

猜想

如果是Neokylin系统的bug,哎呀,不能往这方面想。
重启项目后第一次成功了,后面再试就一直是失败,一定是缓存导致的。
跟踪代码进底层看看,呃,跟到了jdk的native方法也没看出什么来。

源代码

BufferedImage image = renderer.renderImageWithDPI(i, 80);
ImageIO.write(image, type, new File(path));

解决方案

死马当活马医吧,改一改代码

BufferedImage image = renderer.renderImageWithDPI(i, 72.0f);
image.flush();
ImageIO.write(image, type, new File(path));

没错,只加了一行image.flush();因为实在黔驴技穷了。
为防止再次失败,又准备了pdfbox-2.0.1.jar备用(不太靠谱的降级方案),毕竟申请一次准生产环境操作权限很麻烦。
当我小心翼翼地上传多次失败的文件后,满怀期待的终于都成功了,备用的pdfbox-2.0.1.jar也没用上。

后记

只因为少了一行image.flush();就在特定的服务器上,特定的文件上,特定的时间点发生了让人难以捉摸的bug。从网上抄来的代码一定要验证可用性,一定要优化,生成BufferedImage,一定要flush。
最后也懒得骂人了,骂多了折寿。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值