有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有JDBC持久性的java ActiveMQ会在代理上产生OutOfMemory

我使用的是ActiveMQ 5.16.0,broker以512MB堆大小(-Xms=512m -Xmx=512)启动。 配置文件activemq.xml如下所示:

<bean id="postgresql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.postgresql.Driver" />
    <property name="url" value="jdbc:postgresql://localhost:5432/postgres?currentSchema=amq" />
    <property name="username" value="..." />
    <property name="password" value="..." />
</bean>

(...)

<systemUsage>
    <systemUsage>
        <memoryUsage>
            <memoryUsage percentOfJvmHeap="70" />
        </memoryUsage>
        <storeUsage>
            <storeUsage limit="2 gb"/>
        </storeUsage>
        <tempUsage>
            <tempUsage limit="5 gb"/>
        </tempUsage>
    </systemUsage>
</systemUsage>

(...)

<destinationPolicy>
    <policyMap>
      <policyEntries>
        <policyEntry queue=">" producerFlowControl="true" memoryLimit="50 mb"  maxPageSize="100" maxBrowsePageSize="100" lazyDispatch="true"></policyEntry>
        </policyEntry>
      </policyEntries>
    </policyMap>
</destinationPolicy>

我使用的是单生产者,它将500条持久消息推送到单个队列中,每条消息大约1MB。在producer完成消息的生成后,一切似乎都正常,在activemq_msgs表中有500条记录可用,ActiveMQ web控制台显示大约9%的内存使用率,如果我的计算正确的话,这应该是正确的:

  • 70% * 512MB = 358.4MB-总可用内存
  • 70% * 50MB = 35MB-单个队列的总可用内存
  • 35MB / 358.4MB * 100 = ~9%-已使用内存

现在,当我重新启动代理时,问题就出现了。AMQ启动后不久,我遇到了一个例外:

org.postgresql.util.PSQLException: Ran out of memory retrieving query results.
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2255)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:322)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
        at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)
        at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:122)
        at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:122)
        at org.apache.activemq.store.jdbc.adapter.DefaultJDBCAdapter.doRecoverNextMessages(DefaultJDBCAdapter.java:1081)
        at org.apache.activemq.store.jdbc.JDBCMessageStore.recoverNextMessages(JDBCMessageStore.java:365)
        at org.apache.activemq.store.ProxyMessageStore.recoverNextMessages(ProxyMessageStore.java:110)
        at org.apache.activemq.broker.region.cursors.QueueStorePrefetch.doFillBatch(QueueStorePrefetch.java:127)
        at org.apache.activemq.broker.region.cursors.AbstractStoreCursor.fillBatch(AbstractStoreCursor.java:476)
        at org.apache.activemq.broker.region.cursors.AbstractStoreCursor.reset(AbstractStoreCursor.java:179)
        at org.apache.activemq.broker.region.cursors.StoreQueueCursor.reset(StoreQueueCursor.java:166)
        at org.apache.activemq.broker.region.Queue.doPageInForDispatch(Queue.java:2047)
        at org.apache.activemq.broker.region.Queue.pageInMessages(Queue.java:2283)
        at org.apache.activemq.broker.region.Queue.doBrowse(Queue.java:1183)
        at org.apache.activemq.broker.region.Queue.expireMessages(Queue.java:957)
        at org.apache.activemq.broker.region.Queue.access$100(Queue.java:108)
        at org.apache.activemq.broker.region.Queue$2.run(Queue.java:152)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.OutOfMemoryError: Java heap space
        at org.postgresql.core.PGStream.receiveTupleV3(PGStream.java:561)
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2251)
        ... 23 more

我检查了PostgreSQL日志,注意到有一个SELECT查询几乎检索整个表,所以看起来AMQ试图从表中加载所有内容,所以可能这就是OOM的原因:

LOG:  execute <unnamed>: SELECT ID, MSG FROM ACTIVEMQ_MSGS WHERE CONTAINER=$1 AND ID < $2 AND ID > $3 AND XID IS NULL ORDER BY ID LIMIT 32767
DETAIL:  parameters: $1 = 'queue://TEST', $2 = '501', $3 = '-1'

我尝试了一些目的地策略属性,比如:maxPageSizelazyDispatch,但它似乎对这个问题没有任何影响

也许我做错了什么?我会很感激你的任何想法,谢谢


共 (0) 个答案