Simple retry mechanism to cope with a temporarily unavailable endpoint

Motivation:
Use simple retry mechanism when try to connect to peer so a slow-startup will not produce an error

Modification:
Add new Servlet params which allow to configure retry count and wait time. Default behaviour is the same as before

Result:
It is now possible to configure retry when the peer is not up yet and the Servlet is init.
This commit is contained in:
jbertram 2014-03-11 13:28:05 -05:00 committed by Norman Maurer
parent a4a3e8c5b6
commit 1808046061
1 changed files with 49 additions and 1 deletions

View File

@ -63,11 +63,15 @@ public class HttpTunnelingServlet extends HttpServlet {
private static final long serialVersionUID = 4259910275899756070L;
private static final String ENDPOINT = "endpoint";
private static final String CONNECT_ATTEMPTS = "connectAttempts";
private static final String RETRY_DELAY = "retryDelay";
static final InternalLogger logger = InternalLoggerFactory.getInstance(HttpTunnelingServlet.class);
private volatile SocketAddress remoteAddress;
private volatile ChannelFactory channelFactory;
private volatile long connectAttempts = 1;
private volatile long retryDelay;
@Override
public void init() throws ServletException {
@ -93,6 +97,34 @@ public class HttpTunnelingServlet extends HttpServlet {
throw new ServletException("Failed to create a channel factory.", e);
}
String temp = config.getInitParameter(CONNECT_ATTEMPTS);
if (temp != null) {
try {
connectAttempts = Long.parseLong(temp);
} catch (NumberFormatException e) {
throw new ServletException(
"init-param '" + CONNECT_ATTEMPTS + "' is not a valid number. Actual value: " + temp);
}
if (connectAttempts < 1) {
throw new ServletException(
"init-param '" + CONNECT_ATTEMPTS + "' must be >= 1. Actual value: " + connectAttempts);
}
}
temp = config.getInitParameter(RETRY_DELAY);
if (temp != null) {
try {
retryDelay = Long.parseLong(temp);
} catch (NumberFormatException e) {
throw new ServletException(
"init-param '" + RETRY_DELAY + "' is not a valid number. Actual value: " + temp);
}
if (retryDelay < 0) {
throw new ServletException(
"init-param '" + RETRY_DELAY + "' must be >= 0. Actual value: " + retryDelay);
}
}
// Stuff for testing purpose
//ServerBootstrap b = new ServerBootstrap(new DefaultLocalServerChannelFactory());
//b.getPipeline().addLast("logger", new LoggingHandler(getClass(), InternalLogLevel.INFO, true));
@ -147,7 +179,23 @@ public class HttpTunnelingServlet extends HttpServlet {
pipeline.addLast("handler", handler);
Channel channel = channelFactory.newChannel(pipeline);
ChannelFuture future = channel.connect(remoteAddress).awaitUninterruptibly();
int tries = 0;
ChannelFuture future = null;
while (tries < connectAttempts) {
future = channel.connect(remoteAddress).awaitUninterruptibly();
if (!future.isSuccess()) {
tries++;
try {
Thread.sleep(retryDelay);
} catch (InterruptedException e) {
// ignore
}
} else {
break;
}
}
if (!future.isSuccess()) {
Throwable cause = future.getCause();
logger.warn("Endpoint unavailable: " + cause.getMessage(), cause);