Планировщик Spring Webflux (Reactor) не завершает работу после ошибок
Я новичок в Spring Webflux/Reactive Programming в Spring, и у меня есть некоторые проблемы с задачей планировщика:
Планировщик (поток исполнителя) не завершает работу после возникновения ошибки, например, при попытке сохранить объект в базе данных, которая находится в автономном режиме с использованием потоков Schedulers.parallel().
Мой код на самом деле выглядит так:
public Mono<Void> addCatalogEvent(Mono<CatalogEvent> catalogWriteEvent) {
return catalogWriteEvent
.filter(event -> event.getStoreId() != null && event.getCatalogEventType() != null && event.getProductId() != null && event.getUnitPrice() != null)
.switchIfEmpty(Mono.error(new BadRequestException("Not all required fields have been provided for the event!")))
.publishOn(Schedulers.parallel())
.map(event -> {
catalogEventRepository.save(event);
return event;
}).log()
.then()
.onErrorResume(e -> {
Schedulers.shutdownNow();
return Mono.error(new PersistenceException("Persistence failed: " + e.getMessage()));
});
}
Однако, когда база данных переходит в автономный режим, я получаю сообщения об ошибках, распечатанные на консоль, но планировщик / исполнитель не прекращает попытки сохранить объект в базе данных. Процесс продолжается, и сообщения об ошибках снова и снова выводятся на консоль...
Как я могу сказать планировщику / исполнителю прекратить работу при возникновении ошибки, чтобы эти потоки не работали вечно при возникновении ошибки?
И как я могу автоматически перезапустить эти потоки планировщика / исполнителя, как только база данных снова будет в сети?
Я только что добавил оператор.log() после оператора.map(), который выполняет операцию сохранения. Кажется, что операция.log() не выполняется снова после того, как Mono.error() был брошен:
2018-09-21 12:17:12.942 INFO 28234 --- [ctor-http-nio-8] reactor.Mono.Map.2 : onSubscribe(FluxMap.MapSubscriber)
2018-09-21 12:17:12.942 INFO 28234 --- [ctor-http-nio-8] reactor.Mono.Map.2 : request(unbounded)
2018-09-21 12:17:12.965 WARN 28234 --- [ parallel-3] org.postgresql.jdbc.PgConnection : Validating connection.
org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:333) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:155) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:132) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgConnection.isValid(PgConnection.java:1364) ~[postgresql-42.2.2.jar:42.2.2]
at com.zaxxer.hikari.pool.PoolBase.isConnectionAlive(PoolBase.java:150) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:172) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:148) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128) [HikariCP-2.7.9.jar:na]
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.NonContextualJdbcConnectionAccess.obtainConnection(NonContextualJdbcConnectionAccess.java:35) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:106) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:136) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:254) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:262) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:214) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:56) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:164) [spring-orm-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:400) [spring-orm-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:378) [spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:474) [spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:289) [spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) [spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) [spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) [spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) [spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135) [spring-data-jpa-2.0.8.RELEASE.jar:2.0.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) [spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) [spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) [spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) [spring-data-commons-2.0.8.RELEASE.jar:2.0.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) [spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) [spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at com.sun.proxy.$Proxy92.save(Unknown Source) [na:na]
at com.catalog.api.reactive.service.CatalogEventService.lambda$addCatalogEvent$1(CatalogEventService.java:33) [classes/:na]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
at reactor.core.publisher.MonoPublishOn$PublishOnSubscriber.run(MonoPublishOn.java:178) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:50) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:27) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) ~[na:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:na]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:844) ~[na:na]
Caused by: java.io.EOFException: null
at org.postgresql.core.PGStream.receiveChar(PGStream.java:295) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1947) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:306) ~[postgresql-42.2.2.jar:42.2.2]
... 45 common frames omitted
2018-09-21 12:17:12.966 WARN 28234 --- [ parallel-3] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection org.postgresql.jdbc.PgConnection@74772caf (This connection has been closed.)
2018-09-21 12:17:12.969 WARN 28234 --- [ parallel-3] org.postgresql.jdbc.PgConnection : Validating connection.
2018-09-21 12:17:12.970 WARN 28234 --- [ parallel-3] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection org.postgresql.jdbc.PgConnection@5b22b00 (This connection has been closed.)
2018-09-21 12:17:12.972 WARN 28234 --- [ parallel-3] org.postgresql.jdbc.PgConnection : Validating connection.
org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
at [...]
Caused by: java.io.EOFException: null
at [...]
2018-09-21 12:17:12.973 WARN 28234 --- [ parallel-3] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection org.postgresql.jdbc.PgConnection@48ed6d4d (This connection has been closed.)
2018-09-21 12:17:12.975 WARN 28234 --- [onnection adder] unknown.jul.logger : ConnectException occurred while connecting to localhost:5432
java.net.ConnectException: Connection refused (Connection refused)
at [...]
2018-09-21 12:17:12.975 WARN 28234 --- [ parallel-3] org.postgresql.jdbc.PgConnection : Validating connection.
org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
at [...]
Caused by: java.io.EOFException: null
at [...]
2018-09-21 12:17:12.976 WARN 28234 --- [ parallel-3] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection org.postgresql.jdbc.PgConnection@4f66a7fc (This connection has been closed.)
2018-09-21 12:17:12.977 ERROR 28234 --- [onnection adder] org.postgresql.Driver : Connection error:
org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at [...]
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at [...]
2018-09-21 12:17:12.978 WARN 28234 --- [ parallel-3] org.postgresql.jdbc.PgConnection : Validating connection.
[SAME ERROR is repeating again until Mono.error() is thrown which results in the following]
2018-09-21 12:17:42.955 WARN 28234 --- [ parallel-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08001
2018-09-21 12:17:42.956 ERROR 28234 --- [ parallel-3] o.h.engine.jdbc.spi.SqlExceptionHelper : HikariPool-1 - Connection is not available, request timed out after 30005ms.
2018-09-21 12:17:42.956 WARN 28234 --- [ parallel-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08001
2018-09-21 12:17:42.956 ERROR 28234 --- [ parallel-3] o.h.engine.jdbc.spi.SqlExceptionHelper : Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
2018-09-21 12:17:42.969 ERROR 28234 --- [ parallel-3] reactor.Mono.Map.2 : onError(org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection)
2018-09-21 12:17:42.970 ERROR 28234 --- [ parallel-3] reactor.Mono.Map.2 :
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:450) ~[spring-orm-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:378) ~[spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:474) ~[spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:289) ~[spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135) ~[spring-data-jpa-2.0.8.RELEASE.jar:2.0.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.0.8.RELEASE.jar:2.0.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at com.sun.proxy.$Proxy92.save(Unknown Source) ~[na:na]
at com.catalog.api.reactive.service.CatalogEventService.lambda$addCatalogEvent$1(CatalogEventService.java:33) ~[classes/:na]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
at reactor.core.publisher.MonoPublishOn$PublishOnSubscriber.run(MonoPublishOn.java:178) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:50) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:27) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) ~[na:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:na]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:844) ~[na:na]
Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:48) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:109) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:136) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:254) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:262) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:214) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:56) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:164) ~[spring-orm-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:400) ~[spring-orm-5.0.7.RELEASE.jar:5.0.7.RELEASE]
... 26 common frames omitted
Caused by: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30005ms.
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:669) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:183) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:148) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128) ~[HikariCP-2.7.9.jar:na]
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.NonContextualJdbcConnectionAccess.obtainConnection(NonContextualJdbcConnectionAccess.java:35) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:106) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
... 33 common frames omitted
Caused by: org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:245) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.Driver.makeConnection(Driver.java:452) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.Driver.connect(Driver.java:254) ~[postgresql-42.2.2.jar:42.2.2]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:117) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:123) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:365) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:194) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:460) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.access$100(HikariPool.java:71) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:699) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:685) ~[HikariCP-2.7.9.jar:na]
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) ~[na:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:na]
... 3 common frames omitted
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:400) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:243) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:225) ~[na:na]
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:402) ~[na:na]
at java.base/java.net.Socket.connect(Socket.java:591) ~[na:na]
at org.postgresql.core.PGStream.<init>(PGStream.java:69) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:156) ~[postgresql-42.2.2.jar:42.2.2]
... 17 common frames omitted
2018-09-21 12:17:51.326 WARN 28234 --- [onnection adder] unknown.jul.logger : ConnectException occurred while connecting to localhost:5432
java.net.ConnectException: Connection refused (Connection refused)
at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:400) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:243) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:225) ~[na:na]
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:402) ~[na:na]
at java.base/java.net.Socket.connect(Socket.java:591) ~[na:na]
at org.postgresql.core.PGStream.<init>(PGStream.java:69) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:156) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49) [postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195) [postgresql-42.2.2.jar:42.2.2]
at org.postgresql.Driver.makeConnection(Driver.java:452) [postgresql-42.2.2.jar:42.2.2]
at org.postgresql.Driver.connect(Driver.java:254) [postgresql-42.2.2.jar:42.2.2]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:117) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:123) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:365) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:194) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:460) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.access$100(HikariPool.java:71) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:699) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:685) [HikariCP-2.7.9.jar:na]
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) [na:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) [na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) [na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [na:na]
at java.base/java.lang.Thread.run(Thread.java:844) [na:na]
2018-09-21 12:17:51.326 ERROR 28234 --- [onnection adder] org.postgresql.Driver : Connection error:
org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:245) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.Driver.makeConnection(Driver.java:452) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.Driver.connect(Driver.java:254) ~[postgresql-42.2.2.jar:42.2.2]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:117) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:123) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:365) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:194) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:460) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool.access$100(HikariPool.java:71) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:699) [HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:685) [HikariCP-2.7.9.jar:na]
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) [na:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) [na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) [na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [na:na]
at java.base/java.lang.Thread.run(Thread.java:844) [na:na]
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:400) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:243) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:225) ~[na:na]
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:402) ~[na:na]
at java.base/java.net.Socket.connect(Socket.java:591) ~[na:na]
at org.postgresql.core.PGStream.<init>(PGStream.java:69) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:156) ~[postgresql-42.2.2.jar:42.2.2]
[REPEATED FOREVER]
ОБНОВИТЬ
Кажется, что потоки Hikari не прекратят устанавливать соединение, если моя база данных выйдет из строя. Однако, когда я снова перезагружаю свою базу данных, регистрация ошибок, кажется, останавливается и операция сохранения не выполняется.
Могу ли я остановить восстановление процесса подключения, когда моя база данных находится в автономном режиме, чтобы не тратить ресурсы?
1 ответ
С проектным реактором, doOn***
операторы являются операторами "побочных эффектов", и вы не должны реализовывать в них бизнес-логику или операции ввода-вывода.
В этом случае я считаю, что исключение, сгенерированное вашим вызовом репозитория, не преобразуется в сигнал об ошибке в реактивной цепочке. Это объясняет, почему это не ведет себя так, как вы ожидаете. Вы, вероятно, должны использовать что-то еще, как map
оператор.
public Mono<Void> addEvent(Mono<Event> event){
return event
.filter(event -> event.getID()!= null)
.switchIfEmpty(Mono.error(new BadRequestException("ID shouldn't be null!")))
.publishOn(Schedulers.parallel())
.map(event -> {
// if this throws an exception, this will be turned into an error message
eventRepository.save(event);
return event;
})
.then();
Теперь мы упоминаем, что:
планировщик / исполнитель не прекращает попытки сохранить объект в базе данных
Глядя на ваши журналы, кажется, что пул Hikari пытается подключиться к базе данных. После истечения времени ожидания соединения пул выдает ошибку Mono.error
срабатывает. На фоне кажется, что Хикари все еще пытается восстановить соединение (возможно, с экспоненциальным откатом), потому что это его работа. Потоки, на которые вы смотрите, - это не те из Планировщика, а те из пула соединений.
Несколько других замечаний о вашем фрагменте кода:
- Следует избегать любой ценой использования блокирующих библиотек в реактивном приложении. Вы в значительной степени теряете все преимущества использования реактивного программирования.
switchIfEmpty(Mono.error(new BadRequestException("ID shouldn't be null!")))
эффективно переводит пустой Mono (в случае, если id здесь null) в сигнал ошибки. Когда сигнал ошибки течет по цепочке,doOnNext
не будет звонить.doOnError(e -> Mono.error(new PersistenceException("Persistence failed....")))
не будет делать то, что, как ты думаешь, должно; Опять же, это метод побочных эффектов, поэтому он не преобразует ошибку в исключение персистентности. Там вы должны просто зарегистрировать ошибку, но не реагировать на нее.onErrorResume
предназначен для переключения на резервный метод в случае ошибки