根据版本x文档将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$0 - 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$1(RedisConnectionImpl.java:136)
at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
at io.vertx.core.impl.EventLoopContext.lambda$executeAsync$0(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$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
有人知道为什么会发生这种事吗?或者知道如何解决这个问题吗?
如果您的连接长时间空闲,Redis服务器可能会关闭连接。有几种方法可以解决这个问题。类似的内容在本期中有解释
-
添加固定的周期性伪命令(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