2015-12-03 101 views
1

我有一个定制的API来与他们的消息系统进行交互。但是这个API并没有给我任何方式来确认我已经建立了一个连接,而无法连接一个异常将被抛出。环路异常

当我在连接时收到异常时,我有一个尝试重新连接到服务器的异常侦听器。我想这样循环的异常重试连接。进行无限循环直到我能够连接,或者直到程序关闭。我尝试与突破标签要做到这一点,像这样:

reconnect: try{ 
    attemptReconnection(); 
}catch(Exception e){ 
    log.error(e); 
    break reconnect; 
} 

但无法找到重新连接标签对我来说,是一个有点接近使用GOTO语句比我会很舒服投产。如果执行流量达到break;指令那么这意味着你成功连接

do { // optional loop choice 
    try{ 
     attemptReconnection(); 
     break; // Connection was successful, break out of the loop 
    } catch(Exception e){ 
     // Exception thrown, do nothing and move on to the next connection attempt (iteration) 
     log.error(e); 
    } 
}while(true); 

回答

2

继续这样。否则,它将继续前进到下一次迭代。 (注意循环的选择是可选的,你可以使用几乎任何你想要的循环)

1

Have tryReconnection在连接成功时返回true,否则返回false。

tryReconnection方法还应该捕获并记录异常。

然后:

while(!attemptReconnection()){ 

log.error("Connection failure"); 

} 
+0

嗯..我有同样的概念,但这更清洁,更合适。不得不说我喜欢这个答案更哈哈。 –

1

不能说我有经验的API,但我认为这样的事情会实现你之后的结果。

boolean success = false; 
while (!success){ 
    try{ 
     attemptReconnection(); 
     success = true; 
    } 
    catch(Exception e){ 
     log.error(e); 
    } 
} 

一旦attemptReconnection()执行没有错误,success将被设置为true,终止循环。

1

我建议控制重新连接的尝试不是用while循环,而是用预定的事件。这一点,你可以很容易地发起多个连接并执行回退机制,不要过度消耗资源,同时尝试重新连接

private ScheduledExecutorService scheduler; 
... 

public void connect() { 

    for (int i = 0; i < numberOfConnections; i++) { 
     final Runnable r = new Runnable() { 
      int j = 1; 

      public void run() { 
       try { 
        final Connection connection = createNewConnection(); 

       } catch (IOException e) { 
        //here we do a back off mechanism every 1,2,4,8,16... 512 seconds 
        final long sleep = j * 1000L; 
        if (j < 512) { 
         j *= 2; 
        } else { 
         j = 1; 
        } 
        LOGGER.error("Failed connect to host:port: {}:{}. Retrying... in {} millis", 
          host, port, sleep); 
        LOGGER.debug("{}", e); 
        scheduler.schedule(this, sleep, TimeUnit.MILLISECONDS); 
       } catch (InterruptedException e) { 
        Thread.currentThread.interrupt(); 
       } 
      } 
     }; 
     scheduler.schedule(r, 1, TimeUnit.SECONDS); 
    } 
} 

,如果你想关闭应用程序,以避免treadpool不要忘了做一个scheduler.shutdownNow()正在泄漏。

您甚至可以在连接后实现重新连接机制,并且在连接状态发生更改时让侦听器执行connect方法以断开连接。

0

使用Failsafe

RetryPolicy retryPolicy = new RetryPolicy() 
    .retryOn(ConnectException.class); 
    .withBackoff(1, 30, TimeUnit.SECONDS); 

Failsafe.with(retryPolicy).run(() -> attemptReconnection()); 

通过这种方法,故障保护需要照顾的重试你,和Failsafe让你在指定的时候重试应进行一定的灵活性,以及​​是否要重试之间的延迟。