Netty 连接重试
Posted
技术标签:
【中文标题】Netty 连接重试【英文标题】:Netty Connection Retries 【发布时间】:2013-02-21 15:42:30 【问题描述】:在 Netty 中重试连接
我正在构建一个客户端套接字系统。要求是: 首先尝试连接到远程服务器 当第一次尝试失败时继续尝试,直到服务器在线。
我想知道netty中是否有这样的功能可以做到这一点,或者我怎样才能最好地解决这个问题。
非常感谢
这是我正在努力解决的代码 sn-p:
protected void connect() throws Exception
this.bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Configure the event pipeline factory.
bootstrap.setPipelineFactory(new SmpPipelineFactory());
bootstrap.setOption("writeBufferHighWaterMark", 10 * 64 * 1024);
bootstrap.setOption("sendBufferSize", 1048576);
bootstrap.setOption("receiveBufferSize", 1048576);
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("keepAlive", true);
// Make a new connection.
final ChannelFuture connectFuture = bootstrap
.connect(new InetSocketAddress(config.getRemoteAddr(), config
.getRemotePort()));
channel = connectFuture.getChannel();
connectFuture.addListener(new ChannelFutureListener()
@Override
public void operationComplete(ChannelFuture future)
throws Exception
if (connectFuture.isSuccess())
// Connection attempt succeeded:
// Begin to accept incoming traffic.
channel.setReadable(true);
else
// Close the connection if the connection attempt has
// failed.
channel.close();
logger.info("Unable to Connect to the Remote Socket server");
);
【问题讨论】:
没有内置功能可以做到这一点,你需要自己做。 @BrianRoach:你能指导我实现这样的要求吗,因为我不是netty的极客。 不幸的是,这远远超出了 *** 的答案范围。使用 netty 编写客户端并不容易,需要对框架有相当多的了解。要为您指明正确的方向,您需要查看Channel.closeFuture()
- 您需要注册 ChannelFutureListener
并在未来完成时收到通知(意味着频道已关闭)。
实际上,在初始连接尝试中,您使用引导程序的 connect()
调用返回的 Future
- 我可以在这里合理地回答 - 秒。
@BrianRoach:谢谢。我做了连接和未来。这有助于我检查连接是否成功。问题是当服务器可用时如何重试失败,直到我连接。
【参考方案1】:
假设 netty 3.x 最简单的例子是:
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
ChannelFuture future = null;
while (true)
future = bootstrap.connect(new InetSocketAddress("127.0.0.1", 80));
future.awaitUninterruptibly();
if (future.isSuccess())
break;
显然,您希望有自己的循环逻辑来设置最大尝试次数等。Netty 4.x 的引导程序略有不同,但逻辑是相同的。这也是同步的,阻塞的,忽略InterruptedException
;在实际应用程序中,您可能会使用Future
注册ChannelFutureListener
,并在Future
完成时收到通知。
在 OP 编辑问题后添加:
您有一个收到通知的ChannelFutureListener
。如果您想然后重试连接,您将不得不让该侦听器持有对引导程序的引用,或者与您的主线程交流连接尝试失败并让它重试操作。如果您让侦听器执行此操作(这是最简单的方法),请注意您需要限制重试次数以防止无限递归 - 它是在 Netty 工作线程的上下文中执行的。如果您再次用尽重试,您需要将其传达回您的主线程;你可以通过一个 volatile 变量来做到这一点,或者可以使用观察者模式。
在处理异步时,您确实必须同时考虑。有很多方法可以剥那只猫的皮。
【讨论】:
public void operationComplete(ChannelFuture future) throws Exception if (connectFuture.isSuccess()) ;连接=真; else if(!connected) // 如果连接尝试失败,则关闭连接。通道.close();尝试 Thread.sleep(频率); catch (InterruptedException e) bootstrap.connect(sockAddr).addListener(this); ); @Norman Maurer:如果您在线,请您帮我解决这个问题?【参考方案2】:谢谢布赖恩·罗奇。连接的变量是易失的,可以在代码之外访问或进一步处理。
final InetSocketAddress sockAddr = new InetSocketAddress(
config.getRemoteAddr(), config.getRemotePort());
final ChannelFuture connectFuture = bootstrap
.connect(sockAddr);
channel = connectFuture.getChannel();
connectFuture.addListener(new ChannelFutureListener()
@Override
public void operationComplete(ChannelFuture future)
throws Exception
if (future.isSuccess())
// Connection attempt succeeded:
// Begin to accept incoming traffic.
channel.setReadable(true);
connected = true;
else
// Close the connection if the connection attempt has
// failed.
channel.close();
if(!connected)
logger.debug("Attempt to connect within " + ((double)frequency/(double)1000) + " seconds");
try
Thread.sleep(frequency);
catch (InterruptedException e)
logger.error(e.getMessage());
bootstrap.connect(sockAddr).addListener(this);
);
【讨论】:
以上是关于Netty 连接重试的主要内容,如果未能解决你的问题,请参考以下文章