Skip to content

HTTP keep alive management #290

@bgranvea

Description

@bgranvea

In my application I have random connection errors like this:

ClickHouseStatementImpl - Error during connection to ru.yandex.clickhouse.settings.ClickHouseProperties@785d9e37, reporting failure to data source, message: localhost:8123 failed to respond
org.apache.http.NoHttpResponseException: localhost:8123 failed to respond
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:143)
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)

(I've modified the code to print the stacktrace in ClickHouseStatementImpl)

I think the root cause is that in some rare cases, Apache Http client doesn't detect a connection closed by the server (half-closed socket). I have a Wireshark capture which confirms this.

I've seen that the server returns how long it will keep the connection open but it doesn't seem to be used client side:

POST /?compress=1&extremes=0&database=default HTTP/1.1
Content-Length: 55
Content-Type: text/plain; charset=UTF-8
Host: xxxxxx:8123
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_152)

select timezone() FORMAT TabSeparatedWithNamesAndTypes;HTTP/1.1 200 OK
Date: Mon, 14 Jan 2019 08:04:41 GMT
Connection: Keep-Alive
Content-Type: text/tab-separated-values; charset=UTF-8
X-ClickHouse-Server-Display-Name: xxxxxxxxx
Transfer-Encoding: chunked
Keep-Alive: timeout=3
(...)

and

private ConnectionKeepAliveStrategy createKeepAliveStrategy() {
        return new ConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpContext) {
                // in case of errors keep-alive not always works. close connection just in case
                if (httpResponse.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) {
                    return -1;
                }
                HeaderElementIterator it = new BasicHeaderElementIterator(
                        httpResponse.headerIterator(HTTP.CONN_DIRECTIVE));
                while (it.hasNext()) {
                    HeaderElement he = it.nextElement();
                    String param = he.getName();
                    //String value = he.getValue();
                    if (param != null && param.equalsIgnoreCase(HTTP.CONN_KEEP_ALIVE)) {
                        return properties.getKeepAliveTimeout();
                    }
                }
                return -1;
            }
        };
    }

So, shouldn't it be better to parse 'Keep-Alive: timeout=3' to get the keep-alive duration, and if it fails, use properties.getKeepAliveTimeout() ?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions