Redis 连接在 Vert.x 3.9.4 上丢失
Redis connection lost on Vert.x 3.9.4
将vertx-redis-client
升级到版本3.9.4
后
需要更新连接代码以符合新版本。
代码基于上述文档中的示例,如下所示:
Redis.createClient(vertx, redisOptions).connect(onConnect -> {
if (onConnect.succeeded()) {
RedisConnection client = onConnect.result();
RedisAPI redis = RedisAPI.api(client);
vertx.getOrCreateContext().put("redis", redis);
}
});
但一个小时后(或多或少),我的连接丢失并出现以下错误堆栈跟踪:
io.vertx.redis.client.impl.ConnectionManager lambda$static[=12=] - Unhandled Error
java.nio.channels.ClosedChannelException
at io.netty.channel.AbstractChannel$AbstractUnsafe.newClosedChannelException(AbstractChannel.java:957)
at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:865)
at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1367)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717)
at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:764)
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
at io.vertx.core.net.impl.ConnectionBase.write(ConnectionBase.java:124)
at io.vertx.core.net.impl.ConnectionBase.writeToChannel(ConnectionBase.java:205)
at io.vertx.core.net.impl.NetSocketImpl.writeMessage(NetSocketImpl.java:130)
at io.vertx.core.net.impl.NetSocketImpl.write(NetSocketImpl.java:174)
at io.vertx.core.net.impl.NetSocketImpl.write(NetSocketImpl.java:168)
at io.vertx.redis.client.impl.RedisConnectionImpl.lambda$send(RedisConnectionImpl.java:136)
at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
at io.vertx.core.impl.EventLoopContext.lambda$executeAsync[=12=](EventLoopContext.java:38)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)
at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
有谁知道为什么会这样?
或者知道如何解决这个问题?
如果您的连接长时间处于空闲状态,Redis 服务器可能会关闭连接。有几种方法可以解决这个问题。 issue
中解释了类似的内容
添加固定周期虚拟命令 (PING),这样连接就不会关闭。
Redis.createClient(vertx, new RedisOptions()).connect(onConnect -> {
if (onConnect.succeeded()) {
RedisConnection client = onConnect.result();
RedisAPI redis = RedisAPI.api(client);
vertx.getOrCreateContext().put("redis", redis);
vertx.setPeriodic(30 * 1000, handler -> {
redis.ping(new ArrayList<>(), result -> {
if (result.failed()) {
System.out.println("Error " + result.cause().getMessage());
}
});
});
}
});
添加将获取和替换您的连接的周期性任务。
final AtomicReference<RedisConnection> vertxConnection = new AtomicReference<>();
private void refreshConnection(Redis client, RedisConnection fallback) {
// get a connection
client.connect()
.onFailure(err -> {
// maybe log, don't change the current connection
System.out.println("connect failed: " + err.getMessage());
vertx.setTimer(5000L, t -> refreshConnection(client, fallback));
})
.onSuccess(conn -> {
// swap old with new
System.out.println("connect swapped: " + (conn != null ? conn.hashCode() : null));
final RedisConnection old = vertxConnection.getAndSet(conn);
vertx.setTimer(5000L, t -> refreshConnection(client, old));
// the fallback isn't needed anymore
if (fallback != null) {
fallback.close();
}
});
}
// create client
Redis client = Redis.createClient(vertx, redisOptions);
// get a connection
refreshConnection(client, null);
发生这种情况时添加异常处理程序以刷新连接,可以在官方文档中找到很好的例子:https://vertx.io/docs/vertx-redis-client/java/#_implementing_reconnect_on_error
vertx-redis-client
升级到版本3.9.4
后
需要更新连接代码以符合新版本。 代码基于上述文档中的示例,如下所示:
Redis.createClient(vertx, redisOptions).connect(onConnect -> {
if (onConnect.succeeded()) {
RedisConnection client = onConnect.result();
RedisAPI redis = RedisAPI.api(client);
vertx.getOrCreateContext().put("redis", redis);
}
});
但一个小时后(或多或少),我的连接丢失并出现以下错误堆栈跟踪:
io.vertx.redis.client.impl.ConnectionManager lambda$static[=12=] - Unhandled Error
java.nio.channels.ClosedChannelException
at io.netty.channel.AbstractChannel$AbstractUnsafe.newClosedChannelException(AbstractChannel.java:957)
at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:865)
at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1367)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717)
at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:764)
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
at io.vertx.core.net.impl.ConnectionBase.write(ConnectionBase.java:124)
at io.vertx.core.net.impl.ConnectionBase.writeToChannel(ConnectionBase.java:205)
at io.vertx.core.net.impl.NetSocketImpl.writeMessage(NetSocketImpl.java:130)
at io.vertx.core.net.impl.NetSocketImpl.write(NetSocketImpl.java:174)
at io.vertx.core.net.impl.NetSocketImpl.write(NetSocketImpl.java:168)
at io.vertx.redis.client.impl.RedisConnectionImpl.lambda$send(RedisConnectionImpl.java:136)
at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
at io.vertx.core.impl.EventLoopContext.lambda$executeAsync[=12=](EventLoopContext.java:38)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)
at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
有谁知道为什么会这样? 或者知道如何解决这个问题?
如果您的连接长时间处于空闲状态,Redis 服务器可能会关闭连接。有几种方法可以解决这个问题。 issue
中解释了类似的内容添加固定周期虚拟命令 (PING),这样连接就不会关闭。
Redis.createClient(vertx, new RedisOptions()).connect(onConnect -> { if (onConnect.succeeded()) { RedisConnection client = onConnect.result(); RedisAPI redis = RedisAPI.api(client); vertx.getOrCreateContext().put("redis", redis); vertx.setPeriodic(30 * 1000, handler -> { redis.ping(new ArrayList<>(), result -> { if (result.failed()) { System.out.println("Error " + result.cause().getMessage()); } }); }); } });
添加将获取和替换您的连接的周期性任务。
final AtomicReference<RedisConnection> vertxConnection = new AtomicReference<>(); private void refreshConnection(Redis client, RedisConnection fallback) { // get a connection client.connect() .onFailure(err -> { // maybe log, don't change the current connection System.out.println("connect failed: " + err.getMessage()); vertx.setTimer(5000L, t -> refreshConnection(client, fallback)); }) .onSuccess(conn -> { // swap old with new System.out.println("connect swapped: " + (conn != null ? conn.hashCode() : null)); final RedisConnection old = vertxConnection.getAndSet(conn); vertx.setTimer(5000L, t -> refreshConnection(client, old)); // the fallback isn't needed anymore if (fallback != null) { fallback.close(); } }); } // create client Redis client = Redis.createClient(vertx, redisOptions); // get a connection refreshConnection(client, null);
发生这种情况时添加异常处理程序以刷新连接,可以在官方文档中找到很好的例子:https://vertx.io/docs/vertx-redis-client/java/#_implementing_reconnect_on_error