Spring Integration:Poller表现得很奇怪

时间:2015-01-06 14:58:22

标签: java spring spring-integration

我有一个使用jdbc:inbound-channel-adapter从数据库读取数据的配置。配置:

   <int-jdbc:inbound-channel-adapter query="SELECT * FROM requests WHERE processed_status = '' OR processed_status IS NULL LIMIT 5" channel="requestsJdbcChannel"
    data-source="dataSource" update="UPDATE requests  SET processed_status = 'INPROGRESS', date_processed = NOW() WHERE id IN (:id)" >
          <int:poller fixed-rate="30000" />
    </int-jdbc:inbound-channel-adapter>

    <int:splitter input-channel="requestsJdbcChannel" output-channel="requestsQueueChannel"/>

    <int:channel id="requestsQueueChannel">
          <int:queue capacity="1000"/>
    </int:channel>

    <int:chain id="requestsChain" input-channel="requestsQueueChannel" output-channel="requestsApiChannel"> 
          <int:poller  max-messages-per-poll="1" fixed-rate="1000" />
    .
    .
    </int:chain>

在上面的配置中,我定义了jdbc轮询器,fixed-rate为30秒。当有直接通道而不是requestsQueueChannel时,select查询只获得5行(因为我使用限制select查询中的行)并等待另一个30秒进行下一次轮询。

但是,在我使用队列引入requestsQueueChannel并在requestsChain内添加了轮询后,jdbc-inbound并未按预期工作。它不会等待另一个30秒进行下一轮调查。有时它连续两次(在一秒内)轮询数据库,好像有2个线程正在运行并从DB获取两组行。但是,除了上面提到的那些之外,没有异步切换。

我的理解是,即使有requestsQueueChannel,一旦执行了select查询,它应该等待另外30秒来轮询数据库。有什么我想念的吗?我只是想了解这种配置的行为。

2 个答案:

答案 0 :(得分:0)

使用DirectChannel时,下一轮投票在当前投票结束前不予考虑。

使用QueueChannel(或任务执行程序)时,轮询器可以再次运行。

默认情况下,入站适配器的max-messages-per-poll设置为1,因此您的配置应按预期工作。你能在某处发布DEBUG日志吗?

答案 1 :(得分:0)

Spring集成轮询器激活两次的问题,好像它们是2个线程一样,这是我遇到的基本相同的问题,使用文件系统轮询器:

How to prevent duplicate Spring Integration service activations when polling directory

显然这是一种相对常见的错误配置,其中Spring root和servlet上下文都加载了Spring Integration配置。因此,确实存在两个线程,并且可以看到轮询器在其轮询周期内激活两次。通常在彼此的几秒钟内,因为每个都将在其上下文加载时开始。

我确保仅在单个上下文中加载Spring Integration配置的方法是构建项目包以确保分离。

首先定义一个只接受“web”包下的类的Web配置。

@Configuration
@ComponentScan(basePackages = { "com.myapp.web" })
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

创建单独的根配置类以加载bean,例如服务和存储库,这些bean不属于servlet上下文。其中一个应该加载Spring Integration配置。即:

@Configuration
@ComponentScan(basePackages = { "com.myapp.eip" })
@ImportResource(value = { "classpath:META-INF/spring/integration-context.xml"     })
public class EipConfig {
}

配置中需要花费一些时间才能解决的另一个因素是我的servlet过滤器和Web安全配置需要位于根上下文而不是servlet上下文中。