我创建的并且当前在PROD中运行的Java项目是I / O密集型的。我想对其进行重构以优化性能-并非要求我这样做,但我认为仍有改进的余地。因此,在为时已晚之前进行处理。很少有步骤可以并行化,并且可以更好地利用多个内核。
做什么服务?
这是一个Web服务,它简单地摄取一个文件,然后通过网络sftp-ies将它们通过sftp-ies传输到远程sftp服务器(通过Internet而非公司Intranet)。有2个sftp站点。因此,服务通过请求本身发送的元数据来决定将服务器发送到哪个服务器。它还有2个定期运行的作业,它们在这2个sftp站点上按5分钟的定时延迟进行轮询,并提取zip文件(如果有)。
做什么工作: 作业将所有可用的zip压缩一一拉到本地文件夹。然后开始处理每个zip(通过遍历zip集合)。首先,它提取zip,然后获取1个pdf文件,然后发送到公司网络内的另一个网络服务(例如服务 1 )。然后,它获取一个xml文件,对其进行解析并从中提取某些数据,然后将该数据提供给另一服务(例如,服务 2 )。
我打算做什么? 一项工作要做的工作太多。 我打算将其拆分-> Job将仅将zip压缩到本地文件夹中并将名称推送到BlockingQueue中,这将触发另一个作业,并且处理将由它完成,即提取zip可以与从远程sftp服务器提取zip并行处理。现在,我的疑问是将zip从远程拉到本地和在本地处理zip实际上是I / O操作,但因为首先是通过网络的I / O和另一个本地文件I / O,所以我认为使用的数据通道/总线是不同的 因此,如果我将它们并行化,将会提高性能。我需要这样做,因为在将来,拉链的数量将增加,比如说一次只能抓取1000个拉链。与当前的实现。
还将实现用于sftp连接的连接池(当前没有连接池,我意识到这是必须的)。同样适用于2个建议的工作
1)从远程和
拉动zip2)在本地处理zip
我将使用线程池(根据教程Parallel and Asynchronous Programming ,如果该服务是I / O密集型线程,甚至可以达到内核数量的10倍。则需要进行偏离基准测试。但是从概念上讲,这对于头开始)。
这种重组有意义吗?还有什么可以做的?
答案 0 :(得分:1)
我将根据活动类型定义许多线程池执行程序:
Runtime.getRuntime().availableProcessors()
大小的CPU密集型工作然后根据任务的性质将流程分为多个子任务。完成后,结束每个任务会将其结果移交给相应池中的新任务。
我还要实现一个backpressure mechanism,以免队列过大(默认情况下,ThreadPoolExecutor
会愉快地排队无限数量的作业),并时刻注意堆和磁盘空间使用情况。磁盘(HDD)通常是最大的瓶颈,请尝试在内存中执行更多操作。