简体   繁体   English

Spring Integration在事务中将消息发送到Executor

[英]Spring Integration send messages to Executor in transaction

I have a huge number of messages coming from CSV files, that then get sent to a rate limited API. 我有大量来自CSV文件的消息,然后将其发送到限速API。 I'm using a Queue Channel backed by a database channel message store to make the messages durable while processing. 我正在使用由数据库通道消息存储支持的队列通道,以使消息在处理时持久。 I want to get as close to the rate limit as possible, so I need to be sending messages to the API across multiple threads. 我想尽可能接近速率限制,因此我需要跨多个线程将消息发送到API。

What I had in my head of how it should work is something reads the DB, sees what messages are available, and then delegates each message to one of the threads to be processed in a transaction. 我对如何工作的想法是读取数据库,查看可用的消息,然后将每个消息委托给要在事务中处理的线程之一。

But I haven't been able to do that, what I've had to do is have a transactional poller which has a thread pool of N threads, a fixed rate of say 5 seconds, and a max messages per poll of 10 (something more than what could be processed in 5 seconds) ... which works ok, but has problems when there are not many messages waiting (ie if there were 10 messages they would be processed by a single thread) this isn't going to be a problem in practice because we will have 1000's of messages. 但是我无法做到这一点,我要做的是拥有一个事务轮询器,该轮询器具有N个线程的线程池,固定的速率(例如5秒)和每次轮询的最大消息数量为10(某种程度)超过了5秒钟内可以处理的内容)...可以正常工作,但是当没有太多消息等待时(例如,如果有10条消息,它们将由一个线程处理)就会出现问题实际上是一个问题,因为我们将收到1000条消息。 But it seems conceptually more complex than how I thought it should work. 但是,从概念上讲,它似乎比我认为的工作原理更为复杂。

I might not have explained this very well, but it seems like what might be a common problem when messages come in fast, but go out slower? 我可能没有很好地解释这一点,但是当消息快速传入但输出速度较慢时,似乎是一个常见问题?

Your solution is really correct, but you need to think do not shift messages into an Exectuor since that way you you jump out of the transaction boundaries. 您的解决方案确实是正确的,但是您需要考虑不要将消息转移到Exectuor因为那样您会跳出事务边界。

The fact that you have 10 messages processed in the same thread is exactly an implementation details and it looks like this: 您在同一线程中处理了10条消息的事实恰好是实现细节,它看起来像这样:

AbstractPollingEndpoint.this.taskExecutor.execute(() -> {
            int count = 0;
            while (AbstractPollingEndpoint.this.initialized
                    && (AbstractPollingEndpoint.this.maxMessagesPerPoll <= 0
                    || count < AbstractPollingEndpoint.this.maxMessagesPerPoll)) {
                try {
                    if (!Poller.this.pollingTask.call()) {
                        break;
                    }
                    count++;
                }

So, we poll messages until maxMessagesPerPoll in the same thread. 因此,我们在同一线程中轮询消息,直到maxMessagesPerPoll

To make it really more parallel and still keep transaction do not lose messages you need to consider to use fixedRate : 为了使其真正更并行并且仍保持事务不丢失消息,您需要考虑使用fixedRate

/**
 * Specify whether the periodic interval should be measured between the
 * scheduled start times rather than between actual completion times.
 * The latter, "fixed delay" behavior, is the default.
 */
public void setFixedRate(boolean fixedRate)

And increase an amount of thread used by the TaskScheduler for the polling. 并增加TaskScheduler用于轮询的线程数量。 You can do that declaring a ThreadPoolTaskScheduler bean with the name as IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME to override a default one with the pool as 10 . 您可以这样做声明一个名称为IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAMEThreadPoolTaskScheduler bean,以覆盖池为10的默认值。 Or use Global Properties to just override the pool size in that default TaskScheduler : https://docs.spring.io/spring-integration/docs/5.0.6.RELEASE/reference/html/configuration.html#global-properties 或使用全局属性仅覆盖默认TaskScheduler的池大小: https : TaskScheduler

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM