Skip to content

Commit

Permalink
#354 HttpClient > Add keepAlive configuration options TCP_KEEPIDLE,TC… (
Browse files Browse the repository at this point in the history
#355)

* #354 HttpClient > Add keepAlive configuration options TCP_KEEPIDLE,TCP_KEEPINTVL,TCP_KEEPCNT

* ui + test

Co-authored-by: Paolo Venturi - Diennea <[email protected]>
  • Loading branch information
pv3ntur1 and Paolo Venturi - Diennea committed Jun 6, 2022
1 parent 8a2c747 commit 883f2ac
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ public static final class ConnectionPoolBean {
private int stuckRequestTimeout;
private int idleTimeout;
private int disposeTimeout;
private int keepaliveIdle;
private int keepaliveInterval;
private int keepaliveCount;
private boolean enabled;
private int totalConnections;

private int totalConnections;
}

@GET
Expand All @@ -89,6 +92,9 @@ public Map<String, ConnectionPoolBean> getAll() {
conf.getStuckRequestTimeout(),
conf.getIdleTimeout(),
conf.getDisposeTimeout(),
conf.getKeepaliveIdle(),
conf.getKeepaliveInterval(),
conf.getKeepaliveCount(),
conf.isEnabled(),
poolsStats.getOrDefault(conf.getId(), 0)
);
Expand All @@ -107,6 +113,9 @@ public Map<String, ConnectionPoolBean> getAll() {
defaultConnectionPool.getStuckRequestTimeout(),
defaultConnectionPool.getIdleTimeout(),
defaultConnectionPool.getDisposeTimeout(),
defaultConnectionPool.getKeepaliveIdle(),
defaultConnectionPool.getKeepaliveInterval(),
defaultConnectionPool.getKeepaliveCount(),
defaultConnectionPool.isEnabled(),
poolsStats.getOrDefault(defaultConnectionPool.getId(), 0)
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import com.google.common.annotations.VisibleForTesting;
import io.micrometer.core.instrument.Metrics;
import io.netty.channel.ChannelOption;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.FullHttpResponse;
Expand All @@ -51,6 +53,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import jdk.net.ExtendedSocketOptions;
import org.carapaceproxy.EndpointStats;
import org.carapaceproxy.SimpleHTTPResponse;
import org.carapaceproxy.server.mapper.MapResult;
Expand Down Expand Up @@ -324,8 +327,14 @@ public Publisher<Void> forward(ProxyRequest request, boolean cache) {
.followRedirect(false) // clients has to request the redirect, not the proxy
.compress(parent.getCurrentConfiguration().isRequestCompressionEnabled())
.responseTimeout(Duration.ofMillis(connectionConfig.getStuckRequestTimeout()))
.option(ChannelOption.SO_KEEPALIVE, true) // Enables TCP keepalive: TCP starts sending keepalive probes when a connection is idle for some time.
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectionConfig.getConnectTimeout())
.option(ChannelOption.SO_KEEPALIVE, true) // Enables TCP keepalive: TCP starts sending keepalive probes when a connection is idle for some time.
.option(NioChannelOption.of(ExtendedSocketOptions.TCP_KEEPIDLE), connectionConfig.getKeepaliveIdle())
.option(NioChannelOption.of(ExtendedSocketOptions.TCP_KEEPINTERVAL), connectionConfig.getKeepaliveInterval())
.option(NioChannelOption.of(ExtendedSocketOptions.TCP_KEEPCOUNT), connectionConfig.getKeepaliveCount())
.option(EpollChannelOption.TCP_KEEPIDLE, connectionConfig.getKeepaliveIdle())
.option(EpollChannelOption.TCP_KEEPINTVL, connectionConfig.getKeepaliveInterval())
.option(EpollChannelOption.TCP_KEEPCNT, connectionConfig.getKeepaliveCount())
.doOnRequest((req, conn) -> {
if (CarapaceLogger.isLoggingDebugEnabled()) {
CarapaceLogger.debug("Start sending request for "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ public class RuntimeServerConfiguration {
private int connectTimeout = 10_000;
private int borrowTimeout = 60_000;
private int disposeTimeout = 300_000; // 5 min;
private int keepaliveIdle = 300; // sec
private int keepaliveInterval = 60; // sec
private int keepaliveCount = 8;
private long cacheMaxSize = 0;
private long cacheMaxFileSize = 0;
private boolean cacheDisabledForSecureRequestsWithoutPublic = false;
Expand Down Expand Up @@ -109,6 +112,9 @@ public RuntimeServerConfiguration() {
stuckRequestTimeout,
idleTimeout,
disposeTimeout,
keepaliveIdle,
keepaliveInterval,
keepaliveCount,
true
);
}
Expand All @@ -125,13 +131,18 @@ public void configure(ConfigurationStore properties) throws ConfigurationNotVali
this.connectTimeout = properties.getInt("connectionsmanager.connecttimeout", connectTimeout);
this.borrowTimeout = properties.getInt("connectionsmanager.borrowtimeout", borrowTimeout);
this.disposeTimeout = properties.getInt("connectionsmanager.disposetimeout", disposeTimeout);
this.keepaliveIdle = properties.getInt("connectionsmanager.keepaliveidle", keepaliveIdle);
this.keepaliveInterval = properties.getInt("connectionsmanager.keepaliveinterval", keepaliveInterval);
this.keepaliveCount = properties.getInt("connectionsmanager.keepalivecount", keepaliveCount);
LOG.log(Level.INFO, "connectionsmanager.maxconnectionsperendpoint={0}", maxConnectionsPerEndpoint);
LOG.log(Level.INFO, "connectionsmanager.idletimeout={0}", idleTimeout);
LOG.log(Level.INFO, "connectionsmanager.stuckrequesttimeout={0}", stuckRequestTimeout);
LOG.log(Level.INFO, "connectionsmanager.backendsunreachableonstuckrequests={0}", backendsUnreachableOnStuckRequests);
LOG.log(Level.INFO, "connectionsmanager.connecttimeout={0}", connectTimeout);
LOG.log(Level.INFO, "connectionsmanager.borrowtimeout={0}", borrowTimeout);
LOG.log(Level.INFO, "connectionsmanager.disposetimeout={0}", disposeTimeout);
LOG.log(Level.INFO, "connectionsmanager.keepaliveidle={0}", keepaliveIdle);
LOG.log(Level.INFO, "connectionsmanager.keepaliveinterval={0}", keepaliveInterval);
LOG.log(Level.INFO, "connectionsmanager.keepalivecount={0}", keepaliveCount);

this.mapperClassname = properties.getClassname("mapper.class", StandardEndpointMapper.class.getName());
LOG.log(Level.INFO, "mapper.class={0}", this.mapperClassname);
Expand Down Expand Up @@ -305,6 +316,9 @@ private void configureConnectionPools(ConfigurationStore properties) throws Conf
int stuckrequesttimeout = properties.getInt(prefix + "stuckrequesttimeout", stuckRequestTimeout);
int idletimeout = properties.getInt(prefix + "idletimeout", idleTimeout);
int disposetimeout = properties.getInt(prefix + "disposetimeout", disposeTimeout);
int keepaliveidle = properties.getInt(prefix + "keepaliveidle", keepaliveIdle);
int keepaliveinterval = properties.getInt(prefix + "keepaliveinterval", keepaliveInterval);
int keepalivecount = properties.getInt(prefix + "keepalivecount", keepaliveCount);
boolean enabled = properties.getBoolean(prefix + "enabled", false);

ConnectionPoolConfiguration connectionPool = new ConnectionPoolConfiguration(
Expand All @@ -315,6 +329,9 @@ private void configureConnectionPools(ConfigurationStore properties) throws Conf
stuckrequesttimeout,
idletimeout,
disposetimeout,
keepaliveidle,
keepaliveinterval,
keepalivecount,
enabled
);
connectionPools.add(connectionPool);
Expand All @@ -330,6 +347,9 @@ private void configureConnectionPools(ConfigurationStore properties) throws Conf
getStuckRequestTimeout(),
getIdleTimeout(),
getDisposeTimeout(),
getKeepaliveIdle(),
getKeepaliveInterval(),
getKeepaliveCount(),
true
);
LOG.log(Level.INFO, "Configured default connectionpool: {0}", defaultConnectionPool);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public class ConnectionPoolConfiguration {
private int stuckRequestTimeout;
private int idleTimeout;
private int disposeTimeout;
private int keepaliveIdle;
private int keepaliveInterval;
private int keepaliveCount;

private boolean enabled;

}
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ private void configureAndStartServer() throws Exception {
config.put("connectionsmanager.stuckrequesttimeout", "15000");
config.put("connectionsmanager.idletimeout", "20000");
config.put("connectionsmanager.disposetimeout", "50000");
config.put("connectionsmanager.keepaliveidle", "500");
config.put("connectionsmanager.keepaliveinterval", "50");
config.put("connectionsmanager.keepalivecount", "5");

// Custom connection pool (with defaults)
config.put("connectionpool.1.id", "localhost");
Expand All @@ -142,6 +145,9 @@ private void configureAndStartServer() throws Exception {
config.put("connectionpool.3.stuckrequesttimeout", "23000");
config.put("connectionpool.3.idletimeout", "24000");
config.put("connectionpool.3.disposetimeout", "25000");
config.put("connectionpool.3.keepaliveidle", "250");
config.put("connectionpool.3.keepaliveinterval", "25");
config.put("connectionpool.3.keepalivecount", "2");
config.put("connectionpool.3.enabled", "true");

changeDynamicConfiguration(config);
Expand All @@ -159,7 +165,7 @@ public void test() throws Exception {

// default pool
ConnectionPoolConfiguration defaultPool = new ConnectionPoolConfiguration(
"*", "*", 10, 5_000, 10_000, 15_000, 20_000, 50_000, true
"*", "*", 10, 5_000, 10_000, 15_000, 20_000, 50_000, 500, 50, 5, true
);
{
ConnectionProvider provider = connectionPools.get(defaultPool);
Expand All @@ -171,7 +177,7 @@ public void test() throws Exception {

// pool with defaults
ConnectionPoolConfiguration poolWithDefaults = new ConnectionPoolConfiguration(
"localhost", "localhost", 10, 5_000, 10_000, 15_000, 20_000, 50_000, true
"localhost", "localhost", 10, 5_000, 10_000, 15_000, 20_000, 50_000, 500, 50, 5, true
);
{
ConnectionProvider provider = connectionPools.get(poolWithDefaults);
Expand All @@ -183,7 +189,7 @@ public void test() throws Exception {

// custom pool
ConnectionPoolConfiguration customPool = new ConnectionPoolConfiguration(
"localhosts", "localhost[0-9]", 20, 21_000, 22_000, 23_000, 24_000, 25_000, true
"localhosts", "localhost[0-9]", 20, 21_000, 22_000, 23_000, 24_000, 25_000, 250, 25, 2, true
);
{
ConnectionProvider provider = connectionPools.get(customPool);
Expand All @@ -196,7 +202,7 @@ public void test() throws Exception {
// connection pool selection
ProxyRequestsManager.ConnectionsManager connectionsManager = server.getProxyRequestsManager().getConnectionsManager();

// default providder
// default provider
{
HttpServerRequest request = mock(HttpServerRequest.class);
ProxyRequest proxyRequest = mock(ProxyRequest.class);
Expand Down Expand Up @@ -288,22 +294,22 @@ public void testAPIResource() throws Exception {

// default pool
assertThat(pools.get("*"), is(new ConnectionPoolsResource.ConnectionPoolBean(
"*", "*", 10, 5_000, 10_000, 15_000, 20_000, 50_000, true, 0
"*", "*", 10, 5_000, 10_000, 15_000, 20_000, 50_000, 500, 50, 5, true, 0
)));

// pool with defaults
assertThat(pools.get("localhost"), is(new ConnectionPoolsResource.ConnectionPoolBean(
"localhost", "localhost", 10, 5_000, 10_000, 15_000, 20_000, 50_000, true, 1
"localhost", "localhost", 10, 5_000, 10_000, 15_000, 20_000, 50_000, 500, 50, 5, true, 1
)));

// disabled custom pool
assertThat(pools.get("localhost2"), is(new ConnectionPoolsResource.ConnectionPoolBean(
"localhost2", "localhost2", 10, 5_000, 10_000, 15_000, 20_000, 50_000, false, 0
"localhost2", "localhost2", 10, 5_000, 10_000, 15_000, 20_000, 50_000, 500, 50, 5, false, 0
)));

// custom pool
assertThat(pools.get("localhosts"), is(new ConnectionPoolsResource.ConnectionPoolBean(
"localhosts", "localhost[0-9]", 20, 21_000, 22_000, 23_000, 24_000, 25_000, true, 0
"localhosts", "localhost[0-9]", 20, 21_000, 22_000, 23_000, 24_000, 25_000, 250, 25, 2, true, 0
)));
}
}
Expand Down
15 changes: 15 additions & 0 deletions carapace-ui/src/main/webapp/src/components/ConnectionPools.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@
label: "Dispose Timeout (ms)",
sortable: true
},
{
key: "keepaliveIdle",
label: "Keepalive Idle (sec)",
sortable: true
},
{
key: "keepaliveInterval",
label: "Keepalive Interval (sec)",
sortable: true
},
{
key: "keepaliveCount",
label: "Keepalive Count",
sortable: true
},
{
key: "enabled",
label: "Enabled",
Expand Down

0 comments on commit 883f2ac

Please sign in to comment.