【问题标题】:Re-architecturing I/O intensive Java web service using thread pools and BlockingQueue使用线程池和 BlockingQueue 重新架构 I/O 密集型 Java Web 服务
【发布时间】:2019-01-16 14:34:08
【问题描述】:

我创建的并且目前在 PROD 中运行的 Java 项目是 I/O 密集型的。我想重构它以优化性能——不是我被要求这样做,但我觉得仍有改进的余地。所以在为时已晚之前处理它。很少有步骤可以并行化并更好地利用多个内核。

什么服务?

它是一个网络服务,它简单地摄取一个文件并通过网络将它们 sftp-ies 到远程 sftp 服务器(通过互联网而不是公司内部网)。有 2 个 sftp 站点。因此,服务通过请求本身发送的元数据来决定向哪个服务器进行 sftp。它还有 2 个定期运行的作业,这些作业在这 2 个 sftp 站点上以 5 分钟的定时延迟进行轮询,并拉取 zip 文件(如果有)。

做什么工作: 作业将所有可用的 zip 一个一个拉到本地文件夹。然后开始处理每个 zip(通过循环 zips 集合)。首先它提取 zip,然后获取 1 个 pdf 文件并发送到公司网络内的另一个 web 服务(比如服务 1)。然后它获取一个 xml 文件,对其进行解析并从中提取某些数据,然后将该数据提供给另一个服务(例如服务 2)。

我打算做什么? 一项工作要做的工作量太大了。 我计划将其拆分 -> 作业只会将 zip 拉入本地文件夹并将名称推送到 BlockingQueue 中,这将启动另一个作业并由它完成处理,即提取 zip 可以与从远程 sftp 服务器拉取 zip 并行处理。现在我的查询是,将 zip 从远程拉到本地和在本地处理 zip 实际上都是 I/O 操作,但是 因为首先是网络上的 I/O 和另一个本地文件 I/O,我认为使用的数据通道/总线是不同的. 因此,如果我将它们并行化,它将提高性能。 我需要这样做,因为在未来,拉链的数量会增加,例如 1000 个拉链,这非常慢与当前的实施。

还将为 sftp 连接实现连接池(目前没有,我意识到这是必须的)。也适用于 2 个提议的工作

1)从远程拉拉链和

2) 在本地处理 zip

我将使用线程池(根据教程Parallel and Asynchronous Programming ,如果服务是 I/O 密集型服务,线程数甚至可以达到核心的 10 倍。需要进行离线基准测试。但从概念上讲,这对正面来说是有好处的开始)。

这种重组有意义吗?还能做什么?

【问题讨论】:

    标签: java multithreading architecture threadpool sftp


    【解决方案1】:

    我会根据活动类型定义多个线程池执行器:

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

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

    我还将实现backpressure mechanism 以不让队列变得太大(默认情况下ThreadPoolExecutor 将愉快地排队无限数量的作业)并留意堆和磁盘空间的使用情况。磁盘 (HDD) 通常是最大的瓶颈,尝试在内存中做更多的事情。

    【讨论】:

      猜你喜欢
      • 2014-07-20
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      • 1970-01-01
      • 2016-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多