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 连接重试的主要内容,如果未能解决你的问题,请参考以下文章

Nacos Config连接超时重试

在 Java 中重试 JDBC 连接

Robot Framework Telnet 连接重试

Vagrant卡住连接超时重试

使用 C# 连接/重试连接的最有效方法?

Spring Data Cassandra如何设置有限的连接重试次数?