问题描述
我创建了 CrockroachCloud 免费(测试版)集群,并且能够使用命令行连接到数据库。但是当我尝试从 Spring Data R2DBC 驱动程序连接时,出现异常。
我在 application.yml 中使用以下连接字符串:
server:
port: ${PORT:8080}
spring:
r2dbc:
url: r2dbc:postgres://{username}:{password}@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/{dbname}?ssl=true&sslmode=verify-full&sslrootcert=cc-ca.crt&options=--cluster={clustername}-554
username: {username}
password: {password}
然后我得到以下异常:
"Failed to obtain R2DBC Connection; nested exception is io.r2dbc.postgresql.client.ReactorNettyClient$PostgresConnectionClosedException: Connection unexpectedly closed"
完整的堆栈跟踪:
org.springframework.dao.DataAccessResourceFailureException: Failed to obtain R2DBC Connection; nested exception is io.r2dbc.postgresql.client.ReactorNettyClient$PostgresConnectionClosedException: Connection unexpectedly closed\r\n\tat org.springframework.data.r2dbc.connectionfactory.ConnectionFactoryUtils.lambda$getConnection$0(ConnectionFactoryUtils.java:70)\r\n\tSuppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: \nError has been observed at the following site(s):\n\t|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]\n\t|_ checkpoint ⇢ HTTP POST \"/api/countries\" [ExceptionHandlingWebHandler]\nStack trace:\r\n\t\tat org.springframework.data.r2dbc.connectionfactory.ConnectionFactoryUtils.lambda$getConnection$0(ConnectionFactoryUtils.java:70)\r\n\t\tat reactor.core.publisher.Mono.lambda$onErrorMap$30(Mono.java:3325)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:88)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100)\r\n\t\tat reactor.core.publisher.FluxRetry$RetrySubscriber.onError(FluxRetry.java:88)\r\n\t\tat reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onError(FluxPeekFuseable.java:227)\r\n\t\tat reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:165)\r\n\t\tat reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:214)\r\n\t\tat reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:214)\r\n\t\tat reactor.pool.AbstractPool$Borrower.fail(AbstractPool.java:427)\r\n\t\tat reactor.pool.SimpleDequePool.lambda$drainLoop$5(SimpleDequePool.java:310)\r\n\t\tat reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onError(FluxDoOnEach.java:172)\r\n\t\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onError(FluxMap.java:252)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100)\r\n\t\tat reactor.core.publisher.Operators.error(Operators.java:196)\r\n\t\tat reactor.core.publisher.MonoError.subscribe(MonoError.java:52)\r\n\t\tat reactor.core.publisher.Mono.subscribe(Mono.java:4252)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97)\r\n\t\tat reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:165)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100)\r\n\t\tat reactor.core.publisher.Operators.error(Operators.java:196)\r\n\t\tat reactor.core.publisher.MonoError.subscribe(MonoError.java:52)\r\n\t\tat reactor.core.publisher.Mono.subscribe(Mono.java:4252)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100)\r\n\t\tat reactor.core.publisher.Operators.error(Operators.java:196)\r\n\t\tat reactor.core.publisher.MonoError.subscribe(MonoError.java:52)\r\n\t\tat reactor.core.publisher.Mono.subscribe(Mono.java:4252)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97)\r\n\t\tat reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:126)\r\n\t\tat reactor.core.publisher.MonoDelayUntil$DelayUntilTrigger.onError(MonoDelayUntil.java:330)\r\n\t\tat reactor.core.publisher.FluxHandle$HandleSubscriber.onError(FluxHandle.java:196)\r\n\t\tat reactor.core.publisher.FluxHandle$HandleConditionalSubscriber.onError(FluxHandle.java:406)\r\n\t\tat reactor.core.publisher.FluxCreate$BaseSink.error(FluxCreate.java:452)\r\n\t\tat reactor.core.publisher.FluxCreate$BufferAsyncSink.drain(FluxCreate.java:781)\r\n\t\tat reactor.core.publisher.FluxCreate$BufferAsyncSink.error(FluxCreate.java:726)\r\n\t\tat reactor.core.publisher.FluxCreate$SerializedSink.drainLoop(FluxCreate.java:229)\r\n\t\tat reactor.core.publisher.FluxCreate$SerializedSink.drain(FluxCreate.java:205)\r\n\t\tat reactor.core.publisher.FluxCreate$SerializedSink.error(FluxCreate.java:181)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient$Conversation.onError(ReactorNettyClient.java:746)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.close(ReactorNettyClient.java:1018)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient.drainError(ReactorNettyClient.java:518)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient.handleClose(ReactorNettyClient.java:506)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient.access$200(ReactorNettyClient.java:94)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onComplete(ReactorNettyClient.java:909)\r\n\t\tat reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:206)\r\n\t\tat reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onComplete(FluxPeekFuseable.java:931)\r\n\t\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:262)\r\n\t\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:262)\r\n\t\tat reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:450)\r\n\t\tat reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:256)\r\n\t\tat reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:387)\r\n\t\tat reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:373)\r\n\t\tat reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:429)\r\n\t\tat reactor.netty.channel.ChannelOperations.onInboundClose(ChannelOperations.java:390)\r\n\t\tat reactor.netty.channel.ChannelOperationsHandler.channelInactive(ChannelOperationsHandler.java:76)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\t\tat io.netty.handler.codec.BytetoMessageDecoder.channelInputClosed(BytetoMessageDecoder.java:389)\r\n\t\tat io.netty.handler.codec.BytetoMessageDecoder.channelInactive(BytetoMessageDecoder.java:354)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\t\tat io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient$EnsureSubscribersCompleteChannelHandler.channelInactive(ReactorNettyClient.java:535)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\t\tat io.netty.handler.codec.BytetoMessageDecoder.channelInputClosed(BytetoMessageDecoder.java:389)\r\n\t\tat io.netty.handler.codec.BytetoMessageDecoder.channelInactive(BytetoMessageDecoder.java:354)\r\n\t\tat io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1121)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\t\tat io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)\r\n\t\tat io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:819)\r\n\t\tat io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)\r\n\t\tat io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)\r\n\t\tat io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)\r\n\t\tat io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)\r\n\t\tat io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)\r\n\t\tat io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)\r\n\t\tat java.base/java.lang.Thread.run(Thread.java:834)\r\nCaused by: io.r2dbc.postgresql.client.ReactorNettyClient$PostgresConnectionClosedException: Connection unexpectedly closed\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient.lambda$static$0(ReactorNettyClient.java:100)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.close(ReactorNettyClient.java:1018)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient.drainError(ReactorNettyClient.java:518)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient.handleClose(ReactorNettyClient.java:506)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient.access$200(ReactorNettyClient.java:94)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onComplete(ReactorNettyClient.java:909)\r\n\tat reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:206)\r\n\tat reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onComplete(FluxPeekFuseable.java:931)\r\n\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:262)\r\n\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:262)\r\n\tat reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:450)\r\n\tat reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:256)\r\n\tat reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:387)\r\n\tat reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:373)\r\n\tat reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:429)\r\n\tat reactor.netty.channel.ChannelOperations.onInboundClose(ChannelOperations.java:390)\r\n\tat reactor.netty.channel.ChannelOperationsHandler.channelInactive(ChannelOperationsHandler.java:76)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\tat io.netty.handler.codec.BytetoMessageDecoder.channelInputClosed(BytetoMessageDecoder.java:389)\r\n\tat io.netty.handler.codec.BytetoMessageDecoder.channelInactive(BytetoMessageDecoder.java:354)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\tat io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient$EnsureSubscribersCompleteChannelHandler.channelInactive(ReactorNettyClient.java:535)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\tat io.netty.handler.codec.BytetoMessageDecoder.channelInputClosed(BytetoMessageDecoder.java:389)\r\n\tat io.netty.handler.codec.BytetoMessageDecoder.channelInactive(BytetoMessageDecoder.java:354)\r\n\tat io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1121)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\tat io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)\r\n\tat io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:819)\r\n\tat io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)\r\n\tat io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)\r\n\tat io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)\r\n\tat io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)\r\n\tat io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)\r\n\tat io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)\r\n\tat java.base/java.lang.Thread.run(Thread.java:834)\r\n
任何帮助将不胜感激。
解决方法
我怀疑问题出在您的 url
参数上。我发现 options=--cluster={clustername}-554
语法并不像预期的那样工作。相反,请删除 options
参数并更改指定数据库名称的方式。
例如,您目前拥有这个...
url: r2dbc:postgres://{username}:{password}@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/{dbname}?ssl=true&sslmode=verify-full&sslrootcert=cc-ca.crt&options=--cluster={clustername}-554
请尝试类似的方法...
url: r2dbc:postgres://{username}:{password}@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/{clustername}-554.defaultdb?ssl=true&sslmode=verify-full&sslrootcert=cc-ca.crt
请注意,数据库应该是您唯一的集群 ID + .defaultdb
,并且 options
参数已被完全删除。