eclipse-ee4j / eclipse-ee4j/jersey
Apache connector - issue with connection persistance
- Dominant language
- Java
- Stars
- 730
- Forks
- 382
- PR merge metrics
- No merged PRs in 30d
Description
We have a a fairly simple use case for using apache connector to leverage bounded connection pool of persistent http connections. We found an issue in version 2.22.2 but in perusing the code, it seems to be a problem in the later versions as well.
The code below (refer section called "Code") is the use case with ```initWithApacheHC()``` initializing the pool and ```get()``` being the operational method used to invoke the URL.
In running the apache http client in debug mode, we found that the connections were getting discarded (scroll down) for the log excerpts)
Based on some analysis, it seems the stream obtained from the http client in the connector is not markSupported(), due to which a BufferedInputStream is created. (https://github.com/jersey/jersey/blob/master/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java#L651). Unfortunately, the ```InboundMessageContext``` does not close buffered streams after ```readEntity``` executes . - (https://github.com/jersey/jersey/blob/master/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java#L885)
**If the streams are not closed, then Apache HttpClient discards the connections**. The only way to close streams is to use response.close() but it results in the connection being closed. So either way, we don't seem to have a truly persistent connection. One way to fix this would be to read the entire stream into a byte array input stream in the connector and close the inputstream. This assure the connections in the pool are retained.
**Code**
```
..
public void initWithApacheHC() {
ClientConfig clientConfig = new ClientConfig();
clientConfig = clientConfig.connectorProvider(new ApacheConnectorProvider())
.property(ClientProperties.CONNECT_TIMEOUT, CONNECT_TIMEOUT)
.property(ClientProperties.READ_TIMEOUT, READ_TIMEOUT);
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(300, TimeUnit.SECONDS);
connectionManager.setDefaultMaxPerRoute(MAX_CONN_PER_ROUTE);
connectionManager.setMaxTotal(MAX_CONN);
clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
client = ClientBuilder.newClient(clientConfig);
}
public void get() {
WebTarget webTarget = client.target(URL);
//webTarget = configureApiKey(buildWebTargetForPathAndParams(webTarget, optPath, params));
// System.out.println(webTarget.getUri());
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
Response response = invocationBuilder.get();
if (response.getStatusInfo().getFamily().equals(Response.Status.Family.SERVER_ERROR) ) {
throw new RuntimeException("Bad response :" + response.readEntity(String.class));
}
String s = response.readEntity(String.class);
System.out.println(s);
}
...
```
**Log Excerpt**
```
2017/08/21 21:56:23:762 CDT [DEBUG] DefaultManagedHttpClientConnection - http-outgoing-0: Shutdown connection
2017/08/21 21:56:23:763 CDT [DEBUG] MainClientExec - Connection discarded
2017/08/21 21:56:23:763 CDT [DEBUG] DefaultManagedHttpClientConnection - http-outgoing-0: Close connection
2017/08/21 21:56:23:764 CDT [DEBUG] PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {s}->https://burrow-ent-stg.us-central-1ttc.test.core.k8s.tgt:443][total kept alive: 0; route allocated: 0 of 1; total allocated: 0 of 1]
```
Contributor guide
Assessment
This issue has not been assessed yet.