项目场景:
项目场景:使用公司封装的fastdfs工具包上传图片
问题描述
使用公司封装的fastdfs工具包上传文件时,调用的方法并没有对fastdfs client的方法做什么大改动。在并发量不是很大的情况下,有时会报出此错误,频率不高,并且上传图片也成功了。
具体错误信息如下:
2023-02-24 13:17:04.272 [TID:N/A] [pool-4-thread-4] ERROR c.g.t.f.d.conn.DefaultConnection -close connection error
java.net.SocketException: Broken pipe (Write failed)
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
at java.net.SocketOutputStream.write(SocketOutputStream.java:143)
at com.github.tobato.fastdfs.domain.conn.DefaultConnection.close(DefaultConnection.java:73)
at com.github.tobato.fastdfs.domain.conn.PooledConnectionFactory.destroyObject(PooledConnectionFactory.java:96)
at com.github.tobato.fastdfs.domain.conn.PooledConnectionFactory.destroyObject(PooledConnectionFactory.java:22)
at org.apache.commons.pool2.KeyedPooledObjectFactory.destroyObject(KeyedPooledObjectFactory.java:133)
at org.apache.commons.pool2.impl.GenericKeyedObjectPool.destroy(GenericKeyedObjectPool.java:1128)
at org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:403)
at org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:271)
at com.github.tobato.fastdfs.domain.conn.FdfsConnectionManager.getConnection(FdfsConnectionManager.java:148)
at com.github.tobato.fastdfs.domain.conn.TrackerConnectionManager.executeFdfsTrackerCmd(TrackerConnectionManager.java:72)
at com.github.tobato.fastdfs.service.DefaultTrackerClient.getStoreStorage(DefaultTrackerClient.java:32)
at com.github.tobato.fastdfs.service.DefaultFastFileStorageClient.getStorageNode(DefaultFastFileStorageClient.java:167)
at com.github.tobato.fastdfs.service.DefaultFastFileStorageClient.uploadFile(DefaultFastFileStorageClient.java:110)
at com.github.tobato.fastdfs.service.DefaultFastFileStorageClient.uploadFile(DefaultFastFileStorageClient.java:68)
at com.tianyi.platform.sdk.fastdfs.module.service.impl.FastdfsServiceImpl.uploadFile(FastdfsServiceImpl.java:54)
at com.tianyi.service.video.process.modules.service.VideoProcessPreviewImageService.processPreviewImage(VideoProcessPreviewImageService.java:70)
at com.tianyi.service.video.process.modules.receiver.VideoProcessReceiver.lambda$doProcessVideo$2(VideoProcessReceiver.java:156)
at java.util.concurrent.CompletableFuture.uniAccept(CompletableFuture.java:670)
at java.util.concurrent.CompletableFuture$UniAccept.tryFire(CompletableFuture.java:646)
at java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:456)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:758)
原因分析:
造成这个问题的原因是:在使用上传至fastdfs中使用了common-pool2的对象池,会有驱逐线程定时销毁之前缓存的连接,而这个连接有可能已经断开,所以关闭的时候会报这个错。但是代码中捕获了这个错误,并且在finally代码块中强制关闭了连接,
解决方案:
我尝试在代码中进行拦截
是这个异常的我就打印一条日志,甚至不打印日志
// 上传预览图到fastdfs
try {
// 返回值示例:group1/M04/F9/FD/wKhvFWOQPy2AXqBxAAAhXwgB5is954.jpg
spritePath = fastdfsService.uploadFile(imagePath);
} catch (FileNotFoundException e) {
log.error("文件未找到,上传预览图失败:" + spritePath + e);
return false;
//5.使用Exception 没有捕获到,于是我我想是不是报出的是个错误而不是异常,于是使用了Throwable ,结果还是没有捕获到
} catch (Throwable t) {
//} catch (Exception e) {
//1.首先我想直接捕获此异常但是idea提示不会产生此异常,建议删除,所以我又尝试使用Exception捕获后进行比较,不是的抛出,是的就处理掉不打印信息
//} catch (SocketException e) {
String exception = e.toString();
//4.我在此处加了一个日志输出,发现错误还是报出了,但是此条日志并没有打印是没有捕获到?
log.info("exception= " + exception);
//2.使用instanceof idea就提示错误,这里没有搞懂 为啥不让这么比较
//if (e instanceof SocketException) {
//3.我又尝试这样处理,比较抛出的异常是否为此异常,发现也失败了
if (exception .contains("SocketException")) {
log.error("fastDFS断开连接错误,不影响正常业务,无需在意");
} else {
throw e;
}
}
在日志配置文件中关闭日志打印
因为只是pool清除被断开的connection,记录的日志而已,FastDFS server端默认断开处于IDLE状态60s的connection;不影响正常业务,所以这个问题无需考虑。
所以我参考:https://github.com/tobato/fastdfs_client/issues/230,在log配置文件中加入如下配置,让此错误日志不在打印
<!--不显示ERROR c.g.tobato.fastdfs.domain.conn.DefaultConnection - close connection error 错误日志,
参照:https://github.com/tobato/fastdfs_client/issues/230-->
<logger name="com.github.tobato.fastdfs.domain.conn" level="OFF" additive="false"></logger>