Camel JDBC StreamList 查询似乎在拆分之前加载了整个结果集

Posted

技术标签:

【中文标题】Camel JDBC StreamList 查询似乎在拆分之前加载了整个结果集【英文标题】:Camel JDBC StreamList query appears to load whole resultset before splitting 【发布时间】:2019-05-13 09:39:36 【问题描述】:

我正在运行一个 SQL 使用者来读取表中的更改,这一切都很好。但是,在某些情况下,批量发生更改,然后我的查询因内存不足错误而中断,正如您所料。

不幸的是,我被困在 Camel 2.17.6 上,因此 SQL 组件的 StreamList 选项不可用。 (尽管根据Camel-SQL Why using StreamList seems to load all ResultSet?,由于 Spring JDBC 限制,这不能作为流列表工作。)

所以我使用支持流列表的 JDBC 组件重新编写了我的路由,但只要我增加要提取的记录数,我仍然会出现内存不足异常。似乎出于某种原因,JDBC 组件试图在传递给拆分器之前提取所有记录。

我现在的形式是:

from("timer:timer...")
  .to( "language:constant:resource:classpath:pathToSqlStatement/sqlStatement.sql" )
  .to( "jdbc:msSqlServerDataSource?outputType=StreamList" )
  .split( body() ).streaming()
  .setBody().simple("$body[XMLDOC]")
  .setHeader("HeaderName").xpath("xpath/to/data")
  .to("jms:topic:name");

我最初确实有一个聚合策略 UseLatestAggregationStrategysplit() 之后的一个额外步骤,但我已经删除了它,试图删除可能导致整个查询被保存在内存中的所有内容,但我看不到我现在还能做什么。

我注意到问题camel jdbc out of memory exception 提出了类似的问题,但似乎没有解决方案。

(我应该注意我遇到的内存不足错误确实出现在不同的地方,包括GC overhead limit exceeded WinNTFileSystem,我不明白,还有其他与ZippedInputStream有关的事情,这又是我不明白。)

这是否意味着 StreamList 在 JDBC 组件上也不起作用,还是我必须做一些特定的事情来确保 JDBC 组件不会尝试缓存整个结果?

【问题讨论】:

【参考方案1】:

我在使用 postgres 时遇到了类似的问题。将事务放在 jdbc 查询前面解决了我的问题。

问题的原因是,对于 postgres,自动提交标志必须为 false 才能获得流式传输结果,在骆驼路线中这样做的唯一方法似乎是在调用之前进行处理。

【讨论】:

【参考方案2】:

从 v.18.x 版本开始,camel-sql 支持StreamList 输出类型。在早期版本中,camel-sql 组件加载result set in memory as list。我认为在 camel-sql 版本 2.17.x 中无法避免。

通过camel-sql组件将结果加载到内存后,聚合/拆分确实适用。

Another related answer.

【讨论】:

嗨@skadya!谢谢 - 正如我在我的问题中所说,我意识到 StreamList 不在 2.17.x 中,所以根据手册重铸使用从 2.14 支持 StreamList 的camel-jdbc 的路线。 有趣的是,我刚刚在更高版本中进行了测试,而 Camel JDBC 组件仍然没有流式传输查询。但是,2.20 SQL 组件确实可以像我期望的那样使用 StreamList!但是,现在我被困在 2.17 上,所以在我升级服务器之前没有多大帮助。

以上是关于Camel JDBC StreamList 查询似乎在拆分之前加载了整个结果集的主要内容,如果未能解决你的问题,请参考以下文章

camel jdbc和outputClass选项

从 Camel 和 Spring Boot 到 MS SQL Server 的 JDBC

为 Apache Camel 配置数据源

Camel:使用 spring-boot 配置的数据源

使用准备好的语句时出现 Camel -Spring SQLException

Stream API