quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.64k stars 2.65k forks source link

Connecting to a Redis cluster returning only port numbers for nodes results in an error #39593

Closed lw-mcno closed 2 months ago

lw-mcno commented 6 months ago

Describe the bug

Using Quarkus 3.7.4 and the Redis extension, a connection to a Redis cluster (in cluster mode), results in an error when trying to parse one of the node addresses.

Upon connection to some endpoint, the cluster returns ":6379" for a node address (without IP / hostname), which allowed per Redis (cluster) specification. Vert.x Redis client should use the original connection's host / IP in this case, but instead it fails trying to parse an address like redis://:6379.

See e.g. https://redis.io/docs/reference/cluster-spec/ for MOVED (a different use case than the first connection, but describes the generally expected behavior):

The client needs to reissue the query to the specified node's endpoint address and port. The endpoint can be either an IP address, a hostname, or it can be empty (e.g. -MOVED 3999 :6380). An empty endpoint indicates that the server node has an unknown endpoint, and the client should send the next request to the same endpoint as the current request but with the provided port.

It fails on this line: this.redisURI = new RedisURI(connectionString);

Full stack trace:

<init>:138, RedisConnectionManager$RedisConnectionProvider (io.vertx.redis.client.impl)
<init>:424, RedisConnectionManager$RedisEndpoint (io.vertx.redis.client.impl)
connectionEndpointProvider:73, RedisConnectionManager (io.vertx.redis.client.impl)
lambda$getConnection$6:394, RedisConnectionManager (io.vertx.redis.client.impl)
create:-1, RedisConnectionManager$$Lambda$3450/0x00000117be19e410 (io.vertx.redis.client.impl)
lambda$getConnection$1:50, ConnectionManager (io.vertx.core.net.impl.pool)
apply:-1, ConnectionManager$$Lambda$3452/0x00000117be19e860 (io.vertx.core.net.impl.pool)
computeIfAbsent:1708, ConcurrentHashMap (java.util.concurrent)
getConnection:50, ConnectionManager (io.vertx.core.net.impl.pool)
getConnection:40, ConnectionManager (io.vertx.core.net.impl.pool)
getConnection:394, RedisConnectionManager (io.vertx.redis.client.impl)
connect:170, RedisClusterClient (io.vertx.redis.client.impl)
lambda$connect$11:150, RedisClusterClient (io.vertx.redis.client.impl)
handle:-1, RedisClusterClient$$Lambda$3467/0x00000117be1b0cc8 (io.vertx.redis.client.impl)
onSuccess:91, FutureImpl$1 (io.vertx.core.impl.future)
onSuccess:297, FutureImpl$ListenerArray (io.vertx.core.impl.future)
emitSuccess:66, FutureBase (io.vertx.core.impl.future)
tryComplete:246, FutureImpl (io.vertx.core.impl.future)
onSuccess:49, PromiseImpl (io.vertx.core.impl.future)
handle:41, PromiseImpl (io.vertx.core.impl.future)
handle:23, PromiseImpl (io.vertx.core.impl.future)
lambda$null$16:259, RedisClusterClient (io.vertx.redis.client.impl)
handle:-1, RedisClusterClient$$Lambda$3494/0x00000117be1ccfc0 (io.vertx.redis.client.impl)
lambda$getSlots$18:283, RedisClusterClient (io.vertx.redis.client.impl)
handle:-1, RedisClusterClient$$Lambda$3495/0x00000117be1cd1e8 (io.vertx.redis.client.impl)
onSuccess:176, FutureImpl$4 (io.vertx.core.impl.future)
emitSuccess:66, FutureBase (io.vertx.core.impl.future)
tryComplete:246, FutureImpl (io.vertx.core.impl.future)
onSuccess:63, Transformation$1 (io.vertx.core.impl.future)
emitSuccess:66, FutureBase (io.vertx.core.impl.future)
addListener:231, FutureImpl (io.vertx.core.impl.future)
onSuccess:44, Transformation (io.vertx.core.impl.future)
emitSuccess:66, FutureBase (io.vertx.core.impl.future)
tryComplete:246, FutureImpl (io.vertx.core.impl.future)
handle:418, RedisStandaloneConnection (io.vertx.redis.client.impl)
handleResponse:296, RESPParser (io.vertx.redis.client.impl)
handleMulti:262, RESPParser (io.vertx.redis.client.impl)
handle:102, RESPParser (io.vertx.redis.client.impl)
handle:24, RESPParser (io.vertx.redis.client.impl)
lambda$new$1:101, NetSocketImpl (io.vertx.core.net.impl)
handle:-1, NetSocketImpl$$Lambda$3481/0x00000117be1ba7d0 (io.vertx.core.net.impl)
handleEvent:255, InboundBuffer (io.vertx.core.streams.impl)
write:134, InboundBuffer (io.vertx.core.streams.impl)
handle:402, NetSocketImpl$DataMessageHandler (io.vertx.core.net.impl)
emit:335, ContextImpl (io.vertx.core.impl)
emit:328, ContextImpl (io.vertx.core.impl)
handleMessage:378, NetSocketImpl (io.vertx.core.net.impl)
read:159, ConnectionBase (io.vertx.core.net.impl)
channelRead:153, VertxHandler (io.vertx.core.net.impl)
invokeChannelRead:442, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:412, AbstractChannelHandlerContext (io.netty.channel)
channelRead:1410, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeChannelRead:440, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:919, DefaultChannelPipeline (io.netty.channel)
read:166, AbstractNioByteChannel$NioByteUnsafe (io.netty.channel.nio)
processSelectedKey:788, NioEventLoop (io.netty.channel.nio)
processSelectedKeysOptimized:724, NioEventLoop (io.netty.channel.nio)
processSelectedKeys:650, NioEventLoop (io.netty.channel.nio)
run:562, NioEventLoop (io.netty.channel.nio)
run:997, SingleThreadEventExecutor$4 (io.netty.util.concurrent)
run:74, ThreadExecutorMap$2 (io.netty.util.internal)
run:30, FastThreadLocalRunnable (io.netty.util.concurrent)
run:833, Thread (java.lang)

Expected behavior

The client can work with node address being only a port number (completing it using the original connection's host / IP address).

Actual behavior

The connection fails because of Redis URI parsing errror.

How to Reproduce?

Deploy a Redis with cluster-preferred-endpoint-type unknown-endpoint or probably even bind 0.0.0.0. The redis-cli cluster nodes should return a node without an IP address / hostname:

9ed8f1e3223045eb166c536af2f56fd02db79b31 :6379@16379 myself,master - 0 0 1 connected 0-16383

Connect to the cluster from Quarkus:

  redis:
    hosts: 'redis://redis-cluster.redis.svc.cluster.local:6379'
    client-type: cluster
    replicas: share

Output of uname -a or ver

No response

Output of java -version

17

Quarkus version or git rev

3.7.4

Build tool (ie. output of mvnw --version or gradlew --version)

Maven 3.9.6

Additional information

No response

quarkus-bot[bot] commented 6 months ago

/cc @cescoffier (redis), @gsmet (redis), @machi1990 (redis)

lw-mcno commented 6 months ago

Hi @Ladicek, here's the bug report that we've talked about.

Ladicek commented 6 months ago

This requires a fix in the Vert.x Redis client:

Ladicek commented 6 months ago

The PRs to Vert.x have been merged, this will be fixed when Quarkus upgrades to the next Vert.x 4.5 release.

Ladicek commented 2 months ago

This was fixed in Quarkus 3.8.4 / 3.9.2 by upgrading to Vert.x 4.5.7 (although the fix is in Vert.x 4.5.6, see the PR linked above).