В моем фактическом коде есть следующий фрагмент кода. У меня есть несколько потребителей, слушающих очередь.
@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. У меня также есть весенний 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
Поток сейчас застревает на соединении оракула.
"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




Ваш слушатель довольно необычный; в большинстве случаев это будет void listen(SomeObject), где слушатель обрабатывает объект и завершает работу, а сообщение подтверждается.
Похоже, вы игнорируете содержимое сообщения и просто используете его присутствие для запуска loadData().
Тем не менее, по умолчанию сообщение не будет подтверждено, пока метод не завершится; поток контейнера останется в методе слушателя, пока он не завершится.
По умолчанию для контейнера установлен режим подтверждения AUTO, что означает, что контейнер автоматически подтвердит (или отклонит) сообщение при выходе из метода.
Вы можете изменить режим подтверждения на NONE, что означает, что RabbitMQ вообще не требует подтверждения и немедленно удалит сообщение.
Однако поток контейнера по-прежнему будет выполняться в методе до выхода из метода.
Сообщение будет потеряно, если приложение выйдет из строя.
Извините, что обновил слушателя, он читает сообщение и обрабатывает его в loadData ()
Так в чем же вопрос? Как я уже сказал, нормально оставлять сообщение неподтвержденным до завершения загрузки и выхода слушателя, если только вы не измените режим подтверждения на NONE.
Вопрос в том, что основной поток застревает в loadData (), чего не должен ... Он остается там навсегда ..
Но это ваш код и не имеет ничего общего с фреймворком, поэтому мы ничего не можем с этим поделать - сделайте дамп потока, чтобы увидеть, что он делает.
Как я могу это сделать? Есть ли способ зарегистрировать активность потока?
Есть несколько способов. например JDK поставляется с инструментом jstack, просто найдите pid jvm (например, с jps).
Спасибо, Гэри, выше я обновил трассировку стека с помощью команды jstack. Вроде есть блокировка. Посоветуйте, пожалуйста, что нужно сделать, чтобы этого избежать?
at java.net.SocketInputStream.socketRead0(Native Method) - похоже, вы заблокированы в ожидании каких-то данных от HTTP-сервера; это совершенно не связано с spring-amqp; Я предлагаю вам отладить это самостоятельно.
Да, я попадаю в некоторые конечные точки, анализирую данные и загружаю их в базу данных с помощью этого метода.
Привет, Гэри! Обновите новую трассировку стека. это связано с блокировками БД?
Я здесь, чтобы поддержать фреймворки, над которыми работаю; У меня нет времени помогать вам отлаживать код вашего приложения. at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:230) - на этот раз он ожидает результата от базы данных - возможно, вы можете добавить в свое приложение ведение журнала отладки, чтобы показать прогресс (чтение с FTP, запись в базу данных и т. д.).
Вы можете разместить файл свойств?