使用线程池和BlockingQueue重新构造I / O密集型Java Web服务

时间:2019-01-14 10:13:28

标签: java multithreading architecture threadpool sftp

我创建的并且当前在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个拉链。与当前的实现。

还将实现用于s​​ftp连接的连接池(当前没有连接池,我意识到这是必须的)。同样适用于2个建议的工作

1)从远程和

拉动zip

2)在本地处理zip

我将使用线程池(根据教程Parallel and Asynchronous Programming ,如果该服务是I / O密集型线程,甚至可以达到内核数量的10倍。则需要进行偏离基准测试。但是从概念上讲,这对于头开始)。

这种重组有意义吗?还有什么可以做的?

1 个答案:

答案 0 :(得分:1)

我将根据活动类型定义许多线程池执行程序:

  • 一个Runtime.getRuntime().availableProcessors()大小的CPU密集型工作
  • 一个用于磁盘I / O绑定的作业,它较小(1..3)。 HDD在顺序模式下表现最佳。对于SSD,您可以尝试增加池的大小,但是在任何情况下,在执行并行磁盘I / O时都要使用大量缓冲(1MB +),
  • 一个主要用于网络I / O绑定的作业(4..20,取决于网络带宽和传输距离)。

然后根据任务的性质将流程分为多个子任务。完成后,结束每个任务会将其结果移交给相应池中的新任务。

我还要实现一个backpressure mechanism,以免队列过大(默认情况下,ThreadPoolExecutor会愉快地排队无限数量的作业),并时刻注意堆和磁盘空间使用情况。磁盘(HDD)通常是最大的瓶颈,请尝试在内存中执行更多操作。