我需要以多线程方式处理 6 亿条记录,每个请求需要 5-6 秒。在启动应用程序中,我需要创建 1000 个线程,但 tomcat 仅支持 200 个。最好的方法是什么?
4 回答
您可以完全控制 Tomcat 在/apache-tomcat/conf/server.xml中创建的线程数:
<connector connectiontimeout="20000"
maxthreads="1000"
port="8080"
protocol="HTTP/1.1"
redirectport="8443" />
您可以在线程的操作系统限制范围内执行此操作。在mac上是2000。
但我认为创建 1000 个线程不会对您有太大帮助。松散地说,您只能执行与机器上的内核一样多的并发线程。
因此,使用 4 核机器处理 6 亿条记录需要大约 24 年的时间。使用 32 个内核,您可以将其降低到个位数的年数。
我会怎么做?我会研究像 Apache Beam 这样的东西,它可以在很多很多机器上并行化你的工作流程。看看https://cloud.google.com/dataflow/。您可以创建任务来申请 1000 台 4 核机器。谷歌会为你旋转它们并把它们拆掉。这项工作大约需要 9 天。信封背面计算表明,获得您的答案将花费您大约 8,640 美元
如果你想保持高效,你很可能不想使用 1000 个线程,除非你的机器有 1000 个 CPU。如果您的任务受 CPU 限制,那么工作线程的数量应该接近 CPU 计数,否则您将在CPU 调度上浪费周期。
由于您的问题缺乏任何技术细节,我建议关闭它。写一个新的解释你的问题的基础:
- 您如何接收请求?通过 HTTP?局域网还是广域网?是否可以将其更改为其他内容,例如因为请求数据是从外部数据库生成的。
- 您如何处理请求?是 CPU 密集型计算还是您向其他系统发出扇出请求以丰富数据。
- 您如何保存处理结果?
- 你打算如何处理失败?如果一个请求处理失败,您是否计划重复 6 亿个请求?
在这 5-6 秒内会发生什么?它是使用 CPU 进行计算,还是将数据发送到其他地方并等待它返回?
在第二种情况下,您不需要启动 1000 个线程来并行执行 1000 个查询,但如果另一个后端支持,您可以使用 @Async。您将只有一小部分输入和输出线程。
您可以为此使用 Spring WebFlux。然而,WebFlux 不使用 tomcat,而是基于 Netty 构建的自定义 HTTP 服务器,参见例如https://www.baeldung.com/spring-webflux。
这只有在您可以以反应方式执行每个步骤时才有效。在您的情况下,使用响应式 WebClient 进行 SOAP 调用以在不阻塞的情况下发送数据,并在 SOAP 响应上订阅第二个非阻塞进程以将数据上传到谷歌云。
如果必须使用 Spring,您可以查看Spring Cloud Data Flow而不是 Apache Beam。
如果您只想通过使用 Tomcat 和 Spring Boot 来实现这一点,您必须扩大实例的数量。扩大规模将提供更多核心,但可能不是最好的方法。
另外我建议将 Tomcat 与 NIO 一起使用,这将提高性能。