New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ISE: Connection is still allocated #44
Comments
@llorllale Do you know Apache HttpClient? Want to fix this one? |
@amihaiemil yes, I've used this lib before. This is one of those surprises (there will be more). Question: do we need this method at all? /**
* Ping the Docker Engine.
* @return True if it responds with 200 OK, false otherwise.
* @throws IOException If there's network problem.
*/
boolean ping() throws IOException; |
@amihaiemil anyway, I can work on this |
@llorllale Yes, we need that method. That's the first thing a user does when using an API, right? Try to ping it :D And the issue is with other methods as well, anyway. I would look into that Pooling connection manager, I think that's the way to go. |
@0crat in |
@amihaiemil Job #44 is now in scope, role is |
@amihaiemil Job #44 is already in scope |
Bug was reported, see §29: +15 points just awarded to @amihaiemil/z |
@llorllale This would be a reasearch task, I guess (not sure how much you can figure out in 30min). Of course, it's ok to leave a puzzle with your findings. |
@amihaiemil will this work for you? @Override
public final boolean ping() throws IOException {
final HttpGet get = new HttpGet(this.baseUri.toString() + "/_ping");
final HttpResponse response = this.client.execute(get);
get.releaseConnection(); // http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/methods/HttpRequestBase.html#releaseConnection()
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
} |
@llorllale We should also do that, close the connection wherever possible, but it is not enough. The issue is the way the HttpClient is built: Basic connection manager is used, which has a single connection. We need Pooling connection manager because we won't be able to close any connection right away. For instance, As you see, a single HttpClient instance is passed around the library, so if we only rely on closing connections manually, the following snippet won't work: final Container container = docker.containers.get(...);
final InputStream logsStream = container.followLogs(); //here we did not close it
docker.ping();//fail here, connection is still assigned. |
@amihaiemil got it: we need to support concurrency |
@amihaiemil I think you've done the research already. I'm think this connection pooling should be done both for unix and non-unix/remote endpoints. So we should probably extract that (huge!) block of code that creates the client connection manager in |
@llorllale yes, we could do that, but not yet. The building of the remote HttpClient will be even funnier: you have to register So, for now, let's not extract anything, just make them work separately and refactor later. |
@amihaiemil sorry for requesting confirmation so much WDYT of this? Notice the new ctor that accepts /**
* Ctor.
* @param socketFile Unix socket on disk.
*/
UnixHttpClient(final File socketFile) {
this(() -> {
final PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(
RegistryBuilder
.<ConnectionSocketFactory>create()
.register(
"unix",
new ConnectionSocketFactory() {
@Override
public Socket createSocket(
final HttpContext httpContext
) throws IOException {
return UnixSocketChannel.open().socket();
}
@Override
public Socket connectSocket(
final int connectionTimeout,
final Socket socket,
final HttpHost host,
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpContext context
) throws IOException {
socket.setSoTimeout(connectionTimeout);
socket.getChannel().connect(
new UnixSocketAddress(socketFile)
);
return socket;
}
})
.build()
);
pool.setDefaultMaxPerRoute(0);
pool.setMaxTotal(0);
return HttpClientBuilder.create()
.setConnectionManager(pool)
.build();
});
}
/**
* Ctor.
* @param client The HttpClient.
*/
UnixHttpClient(Supplier<HttpClient> client) {
this(client.get());
}
/**
* Ctor.
* @param client Decorated HttpClient.
*/
UnixHttpClient(final HttpClient client) {
this.client = client;
} |
Not a problem. Although you can also make fast PRs and we can discuss there :-? same for me. Yes, looks nice, given that you have to call those setters on the Pooling cm. Are you sure it cannot accept them through its ctor? |
@llorllale I see, ok |
@amihaiemil do we agree that adding a test for this requires completing that other task about implementing a socket server? |
* UnixHttpClient: swapped BasicHttpClientConnectionManager for PoolingHttpClientConnectionManager
@llorllale yes, I think we may need that. But for now, you can simply add a second |
* UnixHttpClient: swapped BasicHttpClientConnectionManager for PoolingHttpClientConnectionManager
@amihaiemil 2 puzzles #51, #52 are still not solved. |
@amihaiemil can we close this?
|
@llorllale sure, thanks |
Order was finished: +30 points just awarded to @llorllale/z |
The job #44 is now out of scope |
@amihaiemil the puzzle #51 is still not solved; solved: #52. |
Apparently, using
BasicHttpClientConnectionManager
(e.g. insideUnixHttpClient
) is not ok since it provides a single connection.This throws the exception:
Becuase the connection is still allocated from the first call. We should either close the connection after each call somehow (not always wanted, of course), or maybe use PoolingClientConnectionManager?
The text was updated successfully, but these errors were encountered: