我在春季启动中有一个兔子 amqp 侦听器,它在不关闭应用程序的情况下保持不变
Posted
技术标签:
【中文标题】我在春季启动中有一个兔子 amqp 侦听器,它在不关闭应用程序的情况下保持不变【英文标题】:I have an rabbit amqp listener in springboot, It stucks without closing the application 【发布时间】:2019-05-31 14:40:04 【问题描述】:我的实际代码中有以下代码 sn-p。我有多个消费者在听队列。
@RabbitListener
private void abc(ETLConfigDTO config)
try
log.info("load started");
loadService.loadData(config);
catch(Exception e)
log.error("Load failed"):
finally
log.info("finished processing"):
loadData() 需要几分钟到几个小时的处理时间。它的一种etl处理。此方法内部有密集的日志记录,因此我知道该过程处于哪个状态。 问题是该过程有点卡在 loadPlans() 方法中。队列中的消息处于未确认状态,因为它仍在处理我需要的那种方式。 没有例外,因为 catch 没有打印任何内容,甚至没有打印 finally 块。 我在同一个班级也有一个 spring cron(5 分钟间隔),它也运行良好并完成了它的任务。
需要注意的是,如果我不使用rabbit amqp,它运行良好。
是否有任何连接/网络中断?或者任何超时?还是主线程挂起/死了?我真的不明白这里发生了什么。
提前致谢。
更新:
谢谢加里,
我在jstack 19
看到这个:
"SimpleAsyncTaskExecutor-1" #25 prio=5 os_prio=0 tid=0x00007f5615b3d800 nid=0x2f runnable [0x00007f56703cd000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
at sun.security.ssl.InputRecord.read(InputRecord.java:503)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
- locked <0x000000067a6bada8> (a java.lang.Object)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:940)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
- locked <0x000000067a6baea0> (a sun.security.ssl.AppInputStream)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
- locked <0x000000067a717cb8> (a java.io.BufferedInputStream)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1569)
- locked <0x000000067a6b4b60> (a sun.net.www.protocol.https.DelegateHttpsURLConnection)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
- locked <0x000000067a6b4b60> (a sun.net.www.protocol.https.DelegateHttpsURLConnection)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:48)
at org.springframework.http.client.AbstractClientHttpResponse.getStatusCode(AbstractClientHttpResponse.java:33)
at org.springframework.web.client.DefaultResponseErrorHandler.getHttpStatusCode(DefaultResponseErrorHandler.java:56)
at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:50)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:602)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:570)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:530)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:448)
..
...
...
...
Please advise.
新更新: 我已经增加内存 -XX:MaxMetaspaceSize=1024M -Xms4096M -Xmx4096M
线程现在卡在oracle连接上。
"SimpleAsyncTaskExecutor-1" #25 prio=5 os_prio=0 tid=0x00007ff6102c8800 nid=0x33 runnable [0x00007ff619ad9000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at oracle.net.ns.Packet.receive(Packet.java:300)
at oracle.net.ns.DataPacket.receive(DataPacket.java:106)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:315)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:260)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:185)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:102)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:124)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:80)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1137)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:290)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:193)
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:1033)
at oracle.jdbc.driver.OracleStatement.executeBatch(OracleStatement.java:4536)
- locked <0x00000007b01c6b20> (a oracle.jdbc.driver.T4CConnection)
at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:230)
at org.springframework.jdbc.core.JdbcTemplate$1BatchUpdateStatementCallback.doInStatement(JdbcTemplate.java:572)
at org.springframework.jdbc.core.JdbcTemplate$1BatchUpdateStatementCallback.doInStatement(JdbcTemplate.java:559)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:405)
at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:611)
...
...
【问题讨论】:
你能发布属性文件吗? 我已经通过 beans 配置了 rabbit 【参考方案1】:你的听众很不寻常;在大多数情况下,它是void listen(SomeObject)
,侦听器处理对象并退出并确认消息。
您似乎忽略了消息的内容,只是利用它的存在来触发loadData()
。
无论如何,默认情况下,在方法退出之前不会确认消息;容器线程将一直保留在侦听器方法中,直到它退出。
容器的默认确认模式是 AUTO,这意味着容器将在方法退出时自动确认(或拒绝)消息。
您可以将确认模式更改为 NONE,这意味着 RabbitMQ 根本不需要确认,并且会立即删除消息。
但是,容器线程仍然会在方法中运行,直到方法退出。
如果应用程序崩溃,消息将会丢失。
【讨论】:
很抱歉更新了监听器,它正在读取消息并在 loadData() 中处理它 那么问题是什么?正如我所说,在加载完成和侦听器退出之前不确认消息是正常的,除非您将确认模式更改为 NONE。 问题是主线程卡在 loadData() 中,它不应该......它永远留在那里.. 但这是您的代码,与框架无关,因此我们无能为力 - 进行线程转储以查看它在做什么。 我该怎么做?有没有办法记录线程活动?以上是关于我在春季启动中有一个兔子 amqp 侦听器,它在不关闭应用程序的情况下保持不变的主要内容,如果未能解决你的问题,请参考以下文章