应项目需求,需要将上传至Fastdfs的图片,搭建一个图片素材库(类似于百度图片)。但是在项目构建初期,数据量不是很大,也并没有设想到要做这一块的功能,图片上传fastdfs后,也就没有将图片宽高,大小,存下来。在需求下发下来后,着手考虑如何针对场景在现有基础上做一些补充或者叫修复。首先需要新增三个字段,width,height,size。然后对库中已有的千万图片数据,做数据修复。
开始构想,做一个定时处理任务跑批,一次获取1w条数据,然后在此次任务中,将获取到的1w条数据分片,一个分片中1000条数据,然后分10个线程并发处理。处理完后,一次性更新入库(大数据库,1w条数据还是可以支持的)。或者一个分片中100条数据,分100个线程。针对线程数这块,特地查到windows服务器下最多可支持好几千甚至更多个线程,当然这些也跟CPU,操作系统等有关系,但对于我们跑批的这一点线程,还是没问题的。
任务流程图期间遇到些问题,操作FastDfs的是使用了一个封装好的工具包org.csource.fastdfs-client-java 版本5.0.4,调用了其封装好的下载接口,StorageClient.download_file1(file_id);但是报错,主要错误如下: java.io.IOException: recv cmd: 10 is not correct, expect cmd: 100
fastdfs storageClient 被多线程抢占使用经查,发现,FastDfs 在多线程环境下上传,下载图片的时候,同时使用一个StorageClient操作文件,会报这个错误,网络建议有两种解决方案:
1. 对StorageClient对象加锁
2. 每次下载或上传文件时,重新new一个StorageClient
第一种方案的话,鉴于多线程处理方式下,对象加锁,那显然不合适,
第二种方案,每一次上传,下载时都去开辟一个链接,几千万的数据量,频繁的开关,是否会给线上的图片服务器造成压力,是未知的,保险起见,换了一种方式:
通过HttpURLConnection 读取流的方式下载,这种方式,显然是避开了频繁创建StorageClient,并且,通过HttpURLConnection请求Fastdfs的ngnix代理路径,也会适当的降低单一Storage访问压力。项目比较赶,所以,暂时先用该方式修复,至于Fastdfs频繁创建StorageClient是否会有效率或者其他影响,需要深入了解一下。
期间还遇到了一些图片下载解析的问题,这个问题,是JDK由于版本迭代产生的一些隐式异常,是在ImageIO.read() 还有 像此处的java.awt.image.ColorConvertOp.filter() 的一些显式异常。
这个异常暂时先忽略掉了,因为可能是由于一些历史的jpeg图片导致,后期再看如何修复,可能会需要使用到类似于ImageMagic的图片处理工具等等了。
虽然弄完了,程序一切正常,但是,还是不够快,10000数据量差不多10分钟,那些秒级百万数据处理到底是怎么样做到的呢,行吧,自己需要学的还有很多了。
最后,还是将数据分成了多个时间段,在检索上进行分片,然后部署了多个处理任务,并行处理。
学无止尽,在每一次处理解决问题中,才能感受到成长。
网友评论