Actor 系统无响应:ThreadPoolExecutor 调度程序仅创建核心线程池,显然忽略最大线程池大小

2024-02-02

更新:我发现如果我设置ThreadPoolExecutor's核心池大小与最大池大小相同(29 个线程)。但是,如果我将核心池大小设置为 11,最大池大小设置为 29,那么 Actor 系统只会创建 11 个线程。我该如何配置ActorSystem / ThreadPoolExecutor继续创建线程以超过核心线程数并保持在最大线程数之内?我不想将核心线程计数设置为最大线程计数,因为我只需要额外的线程来取消作业(这应该是一个罕见的事件)。


我有一个针对 Oracle 数据库运行的批处理程序,使用 Java/Akka 类型的 actor 和以下 actor 来实现:

  1. BatchManager负责与 REST 控制器对话。它管理着一个Queue未初始化的批处理作业;当从队列中轮询未初始化的批处理作业时,它将变成JobManager演员并被处决。
  2. JobManager维护一个存储过程队列和一个池Workers;它初始化每个Worker使用存储过程,并且当Worker完成后,它将过程的结果发送到JobManager,以及JobManager发送另一个存储过程到Worker。当作业队列为空且所有作业均结束时,批处理终止Workers处于空闲状态,此时JobManager将其结果报告给BatchManager,关闭其工作人员(通过TypedActor.context().stop()),然后自行关闭。这JobManager has a Promise<Status> completion当作业成功完成时,或者当作业由于取消或致命异常而终止时,即完成。
  3. Worker执行存储过程。它创造了Oracle连接 https://docs.oracle.com/cd/E18283_01/appdev.112/e13995/oracle/jdbc/OracleConnection.html and a 可调用语句 https://docs.oracle.com/javase/7/docs/api/java/sql/CallableStatement.html用于执行存储过程,并注册一个onFailure回调与JobManager.completion to abort连接和cancel该声明。此回调不使用参与者系统的执行上下文,而是使用从创建的缓存执行器服务创建的执行上下文BatchManager.

我的配置是

{"akka" : { "actor" : { "default-dispatcher" : {
    "type" : "Dispatcher",
    "executor" : "default-executor",
    "throughput" : "1",
    "default-executor" : { "fallback" : "thread-pool-executor" }
    "thread-pool-executor" : {
        "keep-alive-time" : "60s",
        "core-pool-size-min" : coreActorCount,
        "core-pool-size-max" : coreActorCount,
        "max-pool-size-min" : maxActorCount,
        "max-pool-size-max" : maxActorCount,
        "task-queue-size" : "-1",
        "task-queue-type" : "linked",
        "allow-core-timeout" : "on"
}}}}}

目前worker的数量是在其他地方配置的workerCount = 8; coreActorCount is workerCount + 3 while maxActorCount is workerCount * 3 + 5。我正在配备两个核心和 8GB 内存的 Macbook Pro 10 上进行测试;生产服务器要大得多。我正在谈论的数据库位于速度极慢的 VPN 后面。我使用 Oracle 的 JavaSE 1.8 JVM 运行所有这些。本地服务器是 Tomcat 7。Oracle JDBC 驱动程序是版本 10.2(我也许能够说服当局使用更新版本)。所有方法要么返回void or Future<>并且应该是非阻塞的。

当一批成功终止时,就没有问题了——下一批立即开始,并有完整的工作人员。但是,如果我通过终止当前批次JobManager#completion.tryFailure(new CancellationException("Batch cancelled"))那么onFailure注册的回调Workers熄火,然后系统变得无响应。调试 printlns 指示新批次以八个正常运行的工作线程中的三个开始,并且BatchManager变得完全没有反应(我添加了一个Future<String> ping只返回一个命令Futures.successful("ping")并且这也会超时)。这onFailure回调在单独的线程池上执行,即使它们在参与者系统的线程池上,我也应该有足够高的max-pool-size为了容纳原来的JobManager, its Workers, its onFailure回调,以及第二个JobManager and is Workers。相反,我似乎在适应原来的JobManager和它的Workers, 新的JobManager以及不到一半的Workers,并且没有剩下任何东西BatchManager.我运行它的计算机资源不足,但看起来它应该能够运行十几个线程。

这是配置问题吗?这是由于 JVM 施加的限制和/或 Tomcat 施加的限制吗?这是由于我处理阻塞 IO 的方式有问题吗?可能还有其他几件事我可能做错了,这些只是我想到的。

Cancellable 语句的要点 https://gist.github.com/kcleereman/48d3bfaa4a6599160867哪里的CallableStatement and OracleConnection被取消

不变的要点 https://gist.github.com/kcleereman/f8f11d010f88df5b36ce where CancellableStatements被创建

JobManager 清理代码要点 https://gist.github.com/kcleereman/d729d47d80262961f1a6

配置转储 https://gist.github.com/kcleereman/ee28474af7b4bc2c1f9e通过获得System.out.println(mergedConfig.toString());


编辑:我相信我已经将问题范围缩小到参与者系统(它的配置或其与阻塞数据库调用的交互)。我消除了Worker演员并将他们的工作量转移到Runnables以固定大小执行ThreadPoolExecutor,其中每个JobManager创建自己的ThreadPoolExecutor并在批次完成时将其关闭(shutDown正常终止时,shutDownNow异常终止)。取消在实例化的缓存线程池上运行BatchManager。 Actor系统的调度程序仍然是ThreadPoolExecutor但只分配了六个线程。使用此替代设置,取消将按预期执行 - 当数据库连接中止时,工作线程终止,并且新的连接将终止。JobManager立即执行完整的工作线程。这向我表明这不是硬件/JVM/Tomcat 问题。


更新:我使用了线程转储Eclipse 的内存分析器 https://eclipse.org/mat/。我发现取消线程挂在CallableStatement.close(),所以我重新排序取消,以便OracleConnection.abort()之前CallableStatement.cancel()这解决了问题 - 取消全部(显然)正确执行。这Worker不过,线程继续坚持他们的声明 - 我怀疑我的 VPN 可能部分或全部归咎于此。

PerformanceAsync-akka.actor.default-dispatcher-19
  at java.net.SocketInputStream.socketRead0(Ljava/io/FileDescriptor;[BIII)I (Native Method)
  at java.net.SocketInputStream.read([BIII)I (SocketInputStream.java:150)
  at java.net.SocketInputStream.read([BII)I (SocketInputStream.java:121)
  at oracle.net.ns.Packet.receive()V (Unknown Source)
  at oracle.net.ns.DataPacket.receive()V (Unknown Source)
  at oracle.net.ns.NetInputStream.getNextPacket()V (Unknown Source)
  at oracle.net.ns.NetInputStream.read([BII)I (Unknown Source)
  at oracle.net.ns.NetInputStream.read([B)I (Unknown Source)
  at oracle.net.ns.NetInputStream.read()I (Unknown Source)
  at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1()S (T4CMAREngine.java:1109)
  at oracle.jdbc.driver.T4CMAREngine.unmarshalSB1()B (T4CMAREngine.java:1080)
  at oracle.jdbc.driver.T4C8Oall.receive()V (T4C8Oall.java:485)
  at oracle.jdbc.driver.T4CCallableStatement.doOall8(ZZZZ)V (T4CCallableStatement.java:218)
  at oracle.jdbc.driver.T4CCallableStatement.executeForRows(Z)V (T4CCallableStatement.java:971)
  at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout()V (OracleStatement.java:1192)
  at oracle.jdbc.driver.OraclePreparedStatement.executeInternal()I (OraclePreparedStatement.java:3415)
  at oracle.jdbc.driver.OraclePreparedStatement.execute()Z (OraclePreparedStatement.java:3521)
  at oracle.jdbc.driver.OracleCallableStatement.execute()Z (OracleCallableStatement.java:4612)
  at com.util.CPProcExecutor.execute(Loracle/jdbc/OracleConnection;Ljava/sql/CallableStatement;Lcom/controller/BaseJobRequest;)V (CPProcExecutor.java:57)

然而,即使在修复取消顺序之后,我仍然遇到演员系统没有创建足够线程的问题:我仍然只在新批次中获得八分之三的工作人员,并且随着取消的工作人员的增加而添加新的工作人员他们的网络连接超时。我总共有 11 个线程 - 我的核心池大小,29 个线程 - 我的最大池大小。显然,演员系统忽略了我的最大池大小参数,或者我没有正确配置最大池大小。


(免责声明:我不认识 Akka)

根据您下面的队列大小=-1的配置,我猜任务队列是无界的。

  "task-queue-size": "-1",
  "task-queue-type": "linked"

线程池执行器 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html除非工作队列已满并且无法排队,否则不会生成超出核心池大小的内容。仅当任务队列已满时,它才会开始生成最多 max 线程。

如果运行的线程少于 corePoolSize,Executor 总是 更喜欢添加新线程而不是排队。如果 corePoolSize 或 更多线程正在运行,执行器总是更喜欢排队 请求而不是添加新线程。如果请求不能被 排队,创建一个新线程,除非超过 maxPoolSize,在这种情况下,任务将被拒绝。

请检查是否可以修复有限的队列大小,并查看线程是否增加到最大线程数。谢谢。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Actor 系统无响应:ThreadPoolExecutor 调度程序仅创建核心线程池,显然忽略最大线程池大小 的相关文章

  • Java程序中的数组奇怪的行为[重复]

    这个问题在这里已经有答案了 我遇到了这个 Java 程序及其以意想不到的方式运行 以下程序计算 int 数组中元素对之间的差异 import java util public class SetTest public static void
  • 如何测试 JUnit 测试的 Comparator?

    我需要测试 Compare 方法 但我对如何测试感到困惑 我可以看看该怎么做吗 public class MemberComparator implements Comparator
  • 异步多播委托

    我最近在一个广泛使用事件的项目上做了一些工作 我需要做的事情之一是在多播委托上异步调用多个事件处理程序 我认为诀窍是对 GetInvocableList 中的每个项目调用 BeginInvoke 但似乎那里不存在 BeginInvoke 有
  • ExceptionConverter:java.io.IOException:文档没有页面。我正在使用 iText

    当我执行下面的代码时 File f new File c sample pdf PdfWriter getInstance document new FileOutputStream f document open System out p
  • 使用 ANTLR 为 java 源代码生成抽象语法树

    如何使用 ANTLR 从 java src 代码生成 AST 有什么帮助吗 好的 步骤如下 前往ANTLR站点 http www antlr org 并下载最新版本 下载Java g和JavaTreeParser g文件来自here htt
  • 如何在 Java 中禁用 System.out 以提高速度

    我正在用 Java 编写一个模拟重力的程序 其中有一堆日志语句 到 System out 我的程序运行速度非常慢 我认为日志记录可能是部分原因 有什么方法可以禁用 System out 以便我的程序在打印时不会变慢 或者我是否必须手动检查并
  • HDFS:使用 Java / Scala API 移动多个文件

    我需要使用 Java Scala 程序移动 HDFS 中对应于给定正则表达式的多个文件 例如 我必须移动所有名称为 xml从文件夹a到文件夹b 使用 shell 命令我可以使用以下命令 bin hdfs dfs mv a xml b 我可以
  • jdbc4.MySQLSyntaxErrorException:数据库中不存在表

    我正在使用 SpringBoot 开发一个网络应用程序 这是我的application properties文件来指定访问数据库的凭据 spring datasource driverClassName com mysql jdbc Dri
  • hibernate总是自己删除表中的所有数据

    您好 我正在开发一个 spring mvc 应用程序 它使用 hibernate 连接到存储文件的 mysql 数据库 我有两个方法 一个方法添加我选择的特定文件路径中的所有文件 另一种方法调用查询以返回从 mysql 存储的文件列表 问题
  • 如何在多线程C++ 17程序中交换两个指针?

    我有两个指针 pA 和 pB 它们指向两个大的哈希映射对象 当pB指向的哈希图完全更新后 我想交换pB和pA 在C 17中 如何快速且线程安全地交换它们 原子 我是 c 17 的新手 2个指针的原子无等待交换可以通过以下方式实现 inclu
  • 在具有相同属性名称的不同数据类型上使用 ModelMapper

    我有两节课说Animal AnimalDto我想用ModelMapper将 Entity 转换为 DTO 反之亦然 但是对于具有相似名称的一些属性 这些类应该具有不同的数据类型 我该如何实现这一目标 动物 java public class
  • Spring Data 与 Spring Data JPA 与 JdbcTemplate

    我有信心Spring Data and Spring Data JPA指的是相同的 但后来我在 youtube 上观看了一个关于他正在使用JdbcTemplate在那篇教程中 所以我在那里感到困惑 我想澄清一下两者之间有什么区别Spring
  • Android JNI C 简单追加函数

    我想制作一个简单的函数 返回两个字符串的值 基本上 java public native String getAppendedString String name c jstring Java com example hellojni He
  • android Accessibility-service 突然停止触发事件

    我有一个 AccessibilityService 工作正常 但由于开发过程中的某些原因它停止工作 我似乎找不到这个原因 请看一下我的代码并告诉我为什么它不起作用 public class MyServicee extends Access
  • 休眠以持久保存日期

    有没有办法告诉 Hibernate java util Date 应该持久保存 我需要这个来解决 MySQL 中缺少的毫秒分辨率问题 您能想到这种方法有什么缺点吗 您可以自己创建字段long 或者使用自定义的UserType 实施后User
  • 如何修复“sessionFactory”或“hibernateTemplate”是必需的问题

    我正在使用 Spring Boot JPA WEB 和 MYSQL 创建我的 Web 应用程序 它总是说 sessionFactory or hibernateTemplate是必需的 我该如何修复它 我已经尝试过的东西 删除了本地 Mav
  • com.jcraft.jsch.JSchException:身份验证失败

    当我从本地磁盘上传文件到远程服务器时 出现这样的异常 com jcraft jsch JSchException Auth fail at org apache tools ant taskdefs optional ssh Scp exe
  • KeyPressed 和 KeyTyped 混淆[重复]

    这个问题在这里已经有答案了 我搜索过之间的区别KeyPressedand KeyTyped事件 但我仍然不清楚 我发现的一件事是 Keypressed 比 KeyTyped 首先被触发 请澄清一下这些事件何时被准确触发 哪个适合用于哪个目的
  • java8 Collectors.toMap() 限制?

    我正在尝试使用java8Collectors toMap on a Stream of ZipEntry 这可能不是最好的想法 因为在处理过程中可能会发生异常 但我想这应该是可能的 我现在收到一个我不明白的编译错误 我猜是类型推理引擎 这是
  • javax.persistence.Table.indexes()[Ljavax/persistence/Index 中的 NoSuchMethodError

    我有一个 Play Framework 应用程序 并且我was使用 Hibernate 4 2 5 Final 通过 Maven 依赖项管理器检索 我决定升级到 Hibernate 4 3 0 Final 成功重新编译我的应用程序并运行它

随机推荐