Skip to content

Commit de4975c

Browse files
author
jeffreykzli
committed
update IdleConnectionMonitor
1 parent ff8e08f commit de4975c

File tree

4 files changed

+125
-7
lines changed

4 files changed

+125
-7
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>com.qcloud</groupId>
66
<artifactId>cos_api</artifactId>
7-
<version>5.6.240</version>
7+
<version>5.6.240.2</version>
88
<packaging>jar</packaging>
99
<name>cos-java-sdk</name>
1010
<description>java sdk for qcloud cos</description>

src/main/java/com/qcloud/cos/ClientConfig.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ public class ClientConfig {
133133

134134
private boolean isRedirectsEnabled = false;
135135

136+
private boolean useConnectionMonitor = false;
137+
138+
private long connectionMaxIdleMillis = 60 * 1000;
139+
136140
// 不传入region 用于后续调用List Buckets(获取所有的bucket信息)
137141
public ClientConfig() {
138142
super();
@@ -477,4 +481,20 @@ public boolean isRedirectsEnabled() {
477481
public void setRedirectsEnabled(boolean redirectsEnabled) {
478482
isRedirectsEnabled = redirectsEnabled;
479483
}
484+
485+
public boolean isUseConnectionMonitor() {
486+
return useConnectionMonitor;
487+
}
488+
489+
public void setUseConnectionMonitor(boolean isUseConnectionMonitor) {
490+
useConnectionMonitor = isUseConnectionMonitor;
491+
}
492+
493+
public long getConnectionMaxIdleMillis() {
494+
return connectionMaxIdleMillis;
495+
}
496+
497+
public void setConnectionMaxIdleMillis(long connectionMaxIdleMillis) {
498+
this.connectionMaxIdleMillis = connectionMaxIdleMillis;
499+
}
480500
}

src/main/java/com/qcloud/cos/http/DefaultCosHttpClient.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public class DefaultCosHttpClient implements CosHttpClient {
119119
private RequestConfig requestConfig;
120120
protected HttpClient httpClient;
121121
private PoolingHttpClientConnectionManager connectionManager;
122-
private IdleConnectionMonitorThread idleConnectionMonitor;
122+
private IdleConnectionMonitorThread idleConnectionMonitorThread;
123123
private int maxErrorRetry;
124124
private RetryPolicy retryPolicy;
125125
private BackoffStrategy backoffStrategy;
@@ -208,10 +208,14 @@ private void initHttpClient() {
208208
.setSocketTimeout(this.clientConfig.getSocketTimeout())
209209
.setRedirectsEnabled(this.clientConfig.isRedirectsEnabled())
210210
.build();
211-
this.idleConnectionMonitor = new IdleConnectionMonitorThread(this.connectionManager);
212-
this.idleConnectionMonitor.setIdleAliveMS(this.clientConfig.getIdleConnectionAlive());
213-
this.idleConnectionMonitor.setDaemon(true);
214-
this.idleConnectionMonitor.start();
211+
if (clientConfig.isUseConnectionMonitor()) {
212+
IdleConnectionMonitor.registerConnectionManager(this.connectionManager, clientConfig.getConnectionMaxIdleMillis());
213+
} else {
214+
this.idleConnectionMonitorThread = new IdleConnectionMonitorThread(this.connectionManager);
215+
this.idleConnectionMonitorThread.setIdleAliveMS(this.clientConfig.getIdleConnectionAlive());
216+
this.idleConnectionMonitorThread.setDaemon(true);
217+
this.idleConnectionMonitorThread.start();
218+
}
215219
}
216220

217221
@Override
@@ -231,7 +235,12 @@ public void shutdown() {
231235
log.info(trace.toString());
232236
}
233237
cosHttpClientTimer.shutdown();
234-
this.idleConnectionMonitor.shutdown();
238+
if (clientConfig.isUseConnectionMonitor()) {
239+
IdleConnectionMonitor.removeConnectionManager(this.connectionManager);
240+
this.connectionManager.shutdown();
241+
} else {
242+
this.idleConnectionMonitorThread.shutdown();
243+
}
235244
}
236245

237246
// 因为Apache HTTP库自带的URL Encode对一些特殊字符如*等不进行转换, 和COS HTTP服务的URL Encode标准不一致
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.qcloud.cos.http;
2+
3+
import org.apache.http.conn.HttpClientConnectionManager;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.Map;
10+
import java.util.concurrent.ConcurrentHashMap;
11+
import java.util.concurrent.TimeUnit;
12+
13+
public class IdleConnectionMonitor extends Thread {
14+
private static final Logger log = LoggerFactory.getLogger(IdleConnectionMonitor.class);
15+
private static final Map<HttpClientConnectionManager, Long> connectionManagers = new ConcurrentHashMap<HttpClientConnectionManager, Long>();
16+
private static final int PERIOD_MILLISECONDS = 1000 * 60;
17+
private static volatile IdleConnectionMonitor instance;
18+
19+
private volatile boolean shuttingDown;
20+
21+
private IdleConnectionMonitor() {
22+
super("cos-java-sdk-http-connection-monitor");
23+
setDaemon(true);
24+
}
25+
26+
private void markShuttingDown() {
27+
shuttingDown = true;
28+
}
29+
30+
public static boolean registerConnectionManager(HttpClientConnectionManager connectionManager, long maxIdleInMs) {
31+
if (instance == null) {
32+
synchronized (IdleConnectionMonitor.class) {
33+
if (instance == null) {
34+
instance = new IdleConnectionMonitor();
35+
instance.start();
36+
}
37+
}
38+
}
39+
return connectionManagers.put(connectionManager, maxIdleInMs) == null;
40+
}
41+
42+
public static boolean removeConnectionManager(HttpClientConnectionManager connectionManager) {
43+
boolean wasRemoved = connectionManagers.remove(connectionManager) != null;
44+
if (connectionManagers.isEmpty()) {
45+
shutdown();
46+
}
47+
return wasRemoved;
48+
}
49+
50+
public static List<HttpClientConnectionManager> getRegisteredConnectionManagers() {
51+
return new ArrayList<HttpClientConnectionManager>(connectionManagers.keySet());
52+
}
53+
54+
public static synchronized boolean shutdown() {
55+
if (instance != null) {
56+
instance.markShuttingDown();
57+
instance.interrupt();
58+
connectionManagers.clear();
59+
instance = null;
60+
return true;
61+
}
62+
return false;
63+
}
64+
65+
@Override
66+
public void run() {
67+
while (!shuttingDown) {
68+
try {
69+
for (Map.Entry<HttpClientConnectionManager, Long> entry : connectionManagers.entrySet()) {
70+
// When we release connections, the connection manager leaves them
71+
// open so they can be reused. We want to close out any idle
72+
// connections so that they don't sit around in CLOSE_WAIT.
73+
try {
74+
entry.getKey().closeExpiredConnections();
75+
entry.getKey().closeIdleConnections(entry.getValue(), TimeUnit.MILLISECONDS);
76+
} catch (Exception e) {
77+
log.warn("Unable to closeExpiredConnections and closeIdleConnections, ", e);
78+
}
79+
}
80+
81+
Thread.sleep(PERIOD_MILLISECONDS);
82+
} catch (Throwable t) {
83+
log.error("error occurred when closeExpiredConnections and closeIdleConnections, err:", t);
84+
}
85+
}
86+
87+
log.debug("Shutting down reaper thread.");
88+
}
89+
}

0 commit comments

Comments
 (0)