INT-2515 More Orderly Shutdown

* Add beginShutdown() and endShutdown() to OrderlyShutdownCapable
* JMS/AMQP stop listener containers
* TCP (server side)
** after beginShutdown() disallow new connections, drop (log) new messages
** after endShutdown() close server socket
* HTTP (server side)
** after beginShutdown() disallow any new requests (503 Service Unavailable)

* Docbook updates
** What's new section
** Orderly Shutdown section.
This commit is contained in:
Gary Russell
2012-06-19 15:21:53 -04:00
committed by Gunnar Hillert
parent da858b7451
commit ae0abc4f6c
17 changed files with 516 additions and 140 deletions

View File

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -49,6 +50,7 @@ import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.integration.Message;
import org.springframework.integration.MessageHeaders;
import org.springframework.integration.MessagingException;
import org.springframework.integration.core.OrderlyShutdownCapable;
import org.springframework.integration.gateway.MessagingGatewaySupport;
import org.springframework.integration.http.converter.MultipartAwareFormHttpMessageConverter;
import org.springframework.integration.http.converter.SerializingHttpMessageConverter;
@@ -95,7 +97,8 @@ import org.springframework.web.util.UrlPathHelper;
* @author Gary Russell
* @since 2.0
*/
abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySupport {
abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySupport
implements OrderlyShutdownCapable {
private static final boolean jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder",
HttpRequestHandlingEndpointSupport.class.getClassLoader());
@@ -132,6 +135,10 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
private volatile Map<String, Expression> headerExpressions;
private volatile boolean shuttingDown;
private final AtomicInteger activeCount = new AtomicInteger();
public HttpRequestHandlingEndpointSupport() {
this(true);
}
@@ -264,6 +271,10 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
this.multipartResolver = multipartResolver;
}
protected boolean isShuttingDown() {
return this.shuttingDown;
}
@Override
public String getComponentType() {
return (this.expectReply) ? "http:inbound-gateway" : "http:inbound-channel-adapter";
@@ -298,13 +309,30 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
this.validateSupportedMethods();
}
@Override
protected void doStart() {
this.shuttingDown = false;
super.doStart();
}
/**
* Handles the HTTP request by generating a Message and sending it to the request channel. If this gateway's
* 'expectReply' property is true, it will also generate a response from the reply Message once received.
* @return a the response Message
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected final Message<?> doHandleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException {
if (this.isShuttingDown()) {
return createServiceUnavailableResponse();
}
else {
return actualDoHandleRequest(servletRequest, servletResponse);
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private Message<?> actualDoHandleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException {
this.activeCount.incrementAndGet();
try {
ServletServerHttpRequest request = this.prepareRequest(servletRequest);
if (!this.supportedMethods.contains(request.getMethod())) {
@@ -386,9 +414,22 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
}
finally {
this.postProcessRequest(servletRequest);
this.activeCount.decrementAndGet();
}
}
/**
* @return
*/
private Message<?> createServiceUnavailableResponse() {
if (logger.isDebugEnabled()) {
logger.debug("Endpoint is shutting down; returning status " + HttpStatus.SERVICE_UNAVAILABLE);
}
return MessageBuilder.withPayload("Endpoint is shutting down")
.setHeader(org.springframework.integration.http.HttpHeaders.STATUS_CODE, HttpStatus.SERVICE_UNAVAILABLE)
.build();
}
/**
* Converts the reply message to the appropriate HTTP reply object and
* sets up the servlet response.
@@ -521,4 +562,13 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
}
}
}
public int beforeShutdown() {
this.shuttingDown = true;
return this.activeCount.get();
}
public int afterShutdown() {
return this.activeCount.get();
}
}