Skip to content

Commit 4cdb968

Browse files
committed
Utilise Reactor Netty's new graceful shutdown support
Closes gh-20613
1 parent 6b47dd0 commit 4cdb968

File tree

2 files changed

+16
-49
lines changed

2 files changed

+16
-49
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyGracefulShutdown.java

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,13 @@
1717
package org.springframework.boot.web.embedded.netty;
1818

1919
import java.time.Duration;
20-
import java.util.concurrent.atomic.AtomicLong;
21-
import java.util.function.BiFunction;
2220
import java.util.function.Supplier;
2321

2422
import org.apache.commons.logging.Log;
2523
import org.apache.commons.logging.LogFactory;
26-
import org.reactivestreams.Publisher;
2724
import reactor.netty.DisposableServer;
28-
import reactor.netty.http.server.HttpServerRequest;
29-
import reactor.netty.http.server.HttpServerResponse;
3025

3126
import org.springframework.boot.web.server.GracefulShutdown;
32-
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
3327

3428
/**
3529
* {@link GracefulShutdown} for a Reactor Netty {@link DisposableServer}.
@@ -42,17 +36,12 @@ final class NettyGracefulShutdown implements GracefulShutdown {
4236

4337
private final Supplier<DisposableServer> disposableServer;
4438

45-
private final Duration lifecycleTimeout;
46-
4739
private final Duration period;
4840

49-
private final AtomicLong activeRequests = new AtomicLong();
50-
5141
private volatile boolean shuttingDown;
5242

53-
NettyGracefulShutdown(Supplier<DisposableServer> disposableServer, Duration lifecycleTimeout, Duration period) {
43+
NettyGracefulShutdown(Supplier<DisposableServer> disposableServer, Duration period) {
5444
this.disposableServer = disposableServer;
55-
this.lifecycleTimeout = lifecycleTimeout;
5645
this.period = period;
5746
}
5847

@@ -64,32 +53,19 @@ public boolean shutDownGracefully() {
6453
if (server == null) {
6554
return false;
6655
}
67-
if (this.lifecycleTimeout != null) {
68-
server.disposeNow(this.lifecycleTimeout);
69-
}
70-
else {
71-
server.disposeNow();
72-
}
7356
this.shuttingDown = true;
74-
long end = System.currentTimeMillis() + this.period.toMillis();
7557
try {
76-
while (this.activeRequests.get() > 0 && System.currentTimeMillis() < end) {
77-
try {
78-
Thread.sleep(50);
79-
}
80-
catch (InterruptedException ex) {
81-
Thread.currentThread().interrupt();
82-
break;
83-
}
84-
}
85-
long activeRequests = this.activeRequests.get();
86-
if (activeRequests == 0) {
87-
logger.info("Graceful shutdown complete");
88-
return true;
58+
if (this.period != null) {
59+
server.disposeNow(this.period);
8960
}
90-
if (logger.isInfoEnabled()) {
91-
logger.info("Grace period elapsed with " + activeRequests + " request(s) still active");
61+
else {
62+
server.disposeNow();
9263
}
64+
logger.info("Graceful shutdown complete");
65+
return true;
66+
}
67+
catch (IllegalStateException ex) {
68+
logger.info("Grace period elapsed with one ore more requests still active");
9369
return false;
9470
}
9571
finally {
@@ -102,15 +78,4 @@ public boolean isShuttingDown() {
10278
return this.shuttingDown;
10379
}
10480

105-
BiFunction<? super HttpServerRequest, ? super HttpServerResponse, ? extends Publisher<Void>> wrapHandler(
106-
ReactorHttpHandlerAdapter handlerAdapter) {
107-
if (this.period == null) {
108-
return handlerAdapter;
109-
}
110-
return (request, response) -> {
111-
this.activeRequests.incrementAndGet();
112-
return handlerAdapter.apply(request, response).doOnTerminate(() -> this.activeRequests.decrementAndGet());
113-
};
114-
}
115-
11681
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.function.BiFunction;
2323
import java.util.function.Predicate;
2424

25+
import io.netty.channel.group.DefaultChannelGroup;
26+
import io.netty.util.concurrent.DefaultEventExecutor;
2527
import org.apache.commons.logging.Log;
2628
import org.apache.commons.logging.LogFactory;
2729
import org.reactivestreams.Publisher;
@@ -84,16 +86,16 @@ public NettyWebServer(HttpServer httpServer, ReactorHttpHandlerAdapter handlerAd
8486
Duration shutdownGracePeriod) {
8587
Assert.notNull(httpServer, "HttpServer must not be null");
8688
Assert.notNull(handlerAdapter, "HandlerAdapter must not be null");
87-
this.httpServer = httpServer;
8889
this.lifecycleTimeout = lifecycleTimeout;
90+
this.handler = handlerAdapter;
8991
if (shutdownGracePeriod != null) {
92+
this.httpServer = httpServer.channelGroup(new DefaultChannelGroup(new DefaultEventExecutor()));
9093
NettyGracefulShutdown gracefulShutdown = new NettyGracefulShutdown(() -> this.disposableServer,
91-
lifecycleTimeout, shutdownGracePeriod);
92-
this.handler = gracefulShutdown.wrapHandler(handlerAdapter);
94+
shutdownGracePeriod);
9395
this.shutdown = gracefulShutdown;
9496
}
9597
else {
96-
this.handler = handlerAdapter;
98+
this.httpServer = httpServer;
9799
this.shutdown = new ImmediateGracefulShutdown();
98100
}
99101
}

0 commit comments

Comments
 (0)