Spring 集成 - 任务执行器卡住了
Spring Integration - Task Executor stuck
我正在处理卡住的现有 Spring 集成代码。
下面的代码被击中了。从 sql 查询中提取大约 20,000 条记录并发送到拆分器。
代码:
<int-jdbc:outbound-gateway query="..." />
<int:splitter input-channel="..." output-channel="queueChannel"/>
<int:channel id="queueChannel">
<int:queue capacity="25" />
</int:channel>
<int:service-activator ref="..."
input-channel="queueChannel" output-channel="..." method="xxx">
<int:poller max-messages-per-poll="25" fixed-delay="100"
receive-timeout="30000" task-executor="reqExecutor"/>
</int:service-activator>
<task:executor id="reqExecutor" pool-size="25" queue-capacity="5" rejection-policy="CALLER_RUNS" />
在网上搜索了一下,这是我对代码的理解。请纠正我,如果我错了:
拆分器输出通道是容量为 25 的队列通道,这意味着它将从查询中获取一批 25 条记录。
现在,服务激活器中编写的代码将每 100 毫秒轮询一次,并从队列通道中获取 25 条消息。多线程环境中的服务激活器 运行s 与任务执行器。
任务执行器的池大小为 25。这是一次可以 运行 的最大线程数。队列容量为 5。如果所有线程都忙,则 Executor 会将它们放入队列。如果队列容量达到 5,则执行器将拒绝该任务。
拒绝政策是CALLER_RUNS。 Executor 将在拒绝时使用主进程。
应用程序性能可能会受到 CALLER_RUNS 拒绝策略的影响。但是其他策略会丢弃或中止线程。所以,改变拒绝政策不是解决办法。
我应该更改任务执行器的池大小或队列容量来解决问题吗?有没有优先值。会有什么影响。
或者,我应该更改轮询器的固定延迟吗?
编辑 1:
在日志中,重复出现以下行并且进程未完成:
Received no Message during the poll, returning 'false'
编辑 2:
我的问题是否与下面 link 中提到的问题有关:
另外,我对poller的receive-timeout属性也不是很了解
receive-timeout
是轮询器 (reqExecutor
) 线程在队列通道中等待消息到达的时间。如果在没有消息到达后过期,则线程返回到池中。
如果消息到达,它会在线程上进行处理,然后然后线程会返回到池中。
如果你不能从线程转储中解决它,post 它在某个地方(不在这里 - 可能太大)- pastebin 或 github 要点。
经过一些代码优化后解决。代码中有两个主要问题:
HashMap 的键的 hashcode 和 equals 方法没有被覆盖。 hashmap 用于缓存查询,但由于没有覆盖方法,它无法正常工作。
Spring 集成代码中有一个插入查询,插入记录大约 20,000 次。因为,据我所知,我们无法在 Spring 集成中进行批量更新。因此,我将插入查询提取到 java class 并进行了批量更新。
但是,我想知道,为什么线程转储和内存转储没有给出任何提示?
感谢 Geek 和 Gary 帮助我。
我正在处理卡住的现有 Spring 集成代码。
下面的代码被击中了。从 sql 查询中提取大约 20,000 条记录并发送到拆分器。
代码:
<int-jdbc:outbound-gateway query="..." />
<int:splitter input-channel="..." output-channel="queueChannel"/>
<int:channel id="queueChannel">
<int:queue capacity="25" />
</int:channel>
<int:service-activator ref="..."
input-channel="queueChannel" output-channel="..." method="xxx">
<int:poller max-messages-per-poll="25" fixed-delay="100"
receive-timeout="30000" task-executor="reqExecutor"/>
</int:service-activator>
<task:executor id="reqExecutor" pool-size="25" queue-capacity="5" rejection-policy="CALLER_RUNS" />
在网上搜索了一下,这是我对代码的理解。请纠正我,如果我错了:
拆分器输出通道是容量为 25 的队列通道,这意味着它将从查询中获取一批 25 条记录。
现在,服务激活器中编写的代码将每 100 毫秒轮询一次,并从队列通道中获取 25 条消息。多线程环境中的服务激活器 运行s 与任务执行器。
任务执行器的池大小为 25。这是一次可以 运行 的最大线程数。队列容量为 5。如果所有线程都忙,则 Executor 会将它们放入队列。如果队列容量达到 5,则执行器将拒绝该任务。
拒绝政策是CALLER_RUNS。 Executor 将在拒绝时使用主进程。
应用程序性能可能会受到 CALLER_RUNS 拒绝策略的影响。但是其他策略会丢弃或中止线程。所以,改变拒绝政策不是解决办法。
我应该更改任务执行器的池大小或队列容量来解决问题吗?有没有优先值。会有什么影响。
或者,我应该更改轮询器的固定延迟吗?
编辑 1:
在日志中,重复出现以下行并且进程未完成:
Received no Message during the poll, returning 'false'
编辑 2:
我的问题是否与下面 link 中提到的问题有关:
另外,我对poller的receive-timeout属性也不是很了解
receive-timeout
是轮询器 (reqExecutor
) 线程在队列通道中等待消息到达的时间。如果在没有消息到达后过期,则线程返回到池中。
如果消息到达,它会在线程上进行处理,然后然后线程会返回到池中。
如果你不能从线程转储中解决它,post 它在某个地方(不在这里 - 可能太大)- pastebin 或 github 要点。
经过一些代码优化后解决。代码中有两个主要问题:
HashMap 的键的 hashcode 和 equals 方法没有被覆盖。 hashmap 用于缓存查询,但由于没有覆盖方法,它无法正常工作。
Spring 集成代码中有一个插入查询,插入记录大约 20,000 次。因为,据我所知,我们无法在 Spring 集成中进行批量更新。因此,我将插入查询提取到 java class 并进行了批量更新。
但是,我想知道,为什么线程转储和内存转储没有给出任何提示?
感谢 Geek 和 Gary 帮助我。