8278067: Make HttpURLConnection default keep alive timeout configurable

Reviewed-by: dfuchs
This commit is contained in:
Michael McMahon 2022-02-16 16:01:01 +00:00
parent 7428b37696
commit d8f44aa39e
4 changed files with 261 additions and 13 deletions

View file

@ -122,13 +122,13 @@ public class HttpClient extends NetworkClient {
recomputing the value of keepingAlive */
int keepAliveConnections = -1; /* number of keep-alives left */
/**Idle timeout value, in milliseconds. Zero means infinity,
* iff keepingAlive=true.
* Unfortunately, we can't always believe this one. If I'm connected
* through a Netscape proxy to a server that sent me a keep-alive
* time of 15 sec, the proxy unilaterally terminates my connection
* after 5 sec. So we have to hard code our effective timeout to
* 4 sec for the case where we're using a proxy. *SIGH*
/*
* The timeout if specified by the server. Following values possible
* 0: the server specified no keep alive headers
* -1: the server provided "Connection: keep-alive" but did not specify a
* a particular time in a "Keep-Alive:" headers
* Positive values are the number of seconds specified by the server
* in a "Keep-Alive" header
*/
int keepAliveTimeout = 0;
@ -235,7 +235,6 @@ public class HttpClient extends NetworkClient {
return keepAliveProp;
}
public String getSpnegoCBT() {
return spnegoCBT;
}
@ -898,7 +897,7 @@ public class HttpClient extends NetworkClient {
responses.findValue("Keep-Alive"));
/* default should be larger in case of proxy */
keepAliveConnections = p.findInt("max", usingProxy?50:5);
keepAliveTimeout = p.findInt("timeout", usingProxy?60:5);
keepAliveTimeout = p.findInt("timeout", -1);
}
} else if (b[7] != '0') {
/*
@ -1151,6 +1150,10 @@ public class HttpClient extends NetworkClient {
}
}
public boolean getUsingProxy() {
return usingProxy;
}
/**
* @return the proxy port being used for this client. Meaningless
* if getProxyHostUsed() gives null.

View file

@ -41,6 +41,8 @@ import java.util.concurrent.locks.ReentrantLock;
import jdk.internal.misc.InnocuousThread;
import sun.security.action.GetIntegerAction;
import sun.net.www.protocol.http.HttpURLConnection;
import sun.util.logging.PlatformLogger;
/**
* A class that implements a cache of idle Http connections for keep-alive
@ -54,6 +56,32 @@ public class KeepAliveCache
@java.io.Serial
private static final long serialVersionUID = -2937172892064557949L;
// Keep alive time set according to priority specified here:
// 1. If server specifies a time with a Keep-Alive header
// 2. If user specifies a time with system property below
// 3. Default values which depend on proxy vs server and whether
// a Connection: keep-alive header was sent by server
// name suffixed with "server" or "proxy"
private static final String keepAliveProp = "http.keepAlive.time.";
private static final int userKeepAliveServer;
private static final int userKeepAliveProxy;
static final PlatformLogger logger = HttpURLConnection.getHttpLogger();
@SuppressWarnings("removal")
static int getUserKeepAliveSeconds(String type) {
int v = AccessController.doPrivileged(
new GetIntegerAction(keepAliveProp+type, -1)).intValue();
return v < -1 ? -1 : v;
}
static {
userKeepAliveServer = getUserKeepAliveSeconds("server");
userKeepAliveProxy = getUserKeepAliveSeconds("proxy");
}
/* maximum # keep-alive connections to maintain at once
* This should be 2 by the HTTP spec, but because we don't support pipe-lining
* a larger value is more appropriate. So we now set a default of 5, and the value
@ -127,10 +155,29 @@ public class KeepAliveCache
if (v == null) {
int keepAliveTimeout = http.getKeepAliveTimeout();
v = new ClientVector(keepAliveTimeout > 0 ?
keepAliveTimeout * 1000 : LIFETIME);
v.put(http);
super.put(key, v);
if (keepAliveTimeout == 0) {
keepAliveTimeout = getUserKeepAlive(http.getUsingProxy());
if (keepAliveTimeout == -1) {
// same default for server and proxy
keepAliveTimeout = 5;
}
} else if (keepAliveTimeout == -1) {
keepAliveTimeout = getUserKeepAlive(http.getUsingProxy());
if (keepAliveTimeout == -1) {
// different default for server and proxy
keepAliveTimeout = http.getUsingProxy() ? 60 : 5;
}
}
// at this point keepAliveTimeout is the number of seconds to keep
// alive, which could be 0, if the user specified 0 for the property
assert keepAliveTimeout >= 0;
if (keepAliveTimeout == 0) {
http.closeServer();
} else {
v = new ClientVector(keepAliveTimeout * 1000);
v.put(http);
super.put(key, v);
}
} else {
v.put(http);
}
@ -139,6 +186,11 @@ public class KeepAliveCache
}
}
// returns the keep alive set by user in system property or -1 if not set
private static int getUserKeepAlive(boolean isProxy) {
return isProxy ? userKeepAliveProxy : userKeepAliveServer;
}
/* remove an obsolete HttpClient from its VectorCache */
public void remove(HttpClient h, Object obj) {
cacheLock.lock();
@ -277,6 +329,11 @@ class ClientVector extends ArrayDeque<KeepAliveEntry> {
e.hc.closeServer();
} else {
hc = e.hc;
if (KeepAliveCache.logger.isLoggable(PlatformLogger.Level.FINEST)) {
String msg = "cached HttpClient was idle for "
+ Long.toString(currentTime - e.idleStartTime);
KeepAliveCache.logger.finest(msg);
}
}
} while ((hc == null) && (!isEmpty()));
return hc;