2727
2828import org .apache .http .ConnectionReuseStrategy ;
2929import org .apache .http .Header ;
30- import org .apache .http .HeaderElement ;
31- import org .apache .http .HeaderElementIterator ;
3230import org .apache .http .HttpHeaders ;
3331import org .apache .http .HttpHost ;
3432import org .apache .http .HttpResponse ;
33+ import org .apache .http .NoHttpResponseException ;
3534import org .apache .http .auth .AuthScope ;
3635import org .apache .http .auth .UsernamePasswordCredentials ;
3736import org .apache .http .client .AuthCache ;
3837import org .apache .http .client .CredentialsProvider ;
38+ import org .apache .http .client .HttpRequestRetryHandler ;
3939import org .apache .http .client .config .RequestConfig ;
4040import org .apache .http .client .protocol .HttpClientContext ;
4141import org .apache .http .config .ConnectionConfig ;
4242import org .apache .http .config .RegistryBuilder ;
43- import org .apache .http .conn .ConnectionKeepAliveStrategy ;
4443import org .apache .http .conn .socket .ConnectionSocketFactory ;
4544import org .apache .http .conn .socket .PlainConnectionSocketFactory ;
4645import org .apache .http .conn .ssl .NoopHostnameVerifier ;
5049import org .apache .http .impl .client .BasicAuthCache ;
5150import org .apache .http .impl .client .BasicCredentialsProvider ;
5251import org .apache .http .impl .client .CloseableHttpClient ;
52+ import org .apache .http .impl .client .DefaultHttpRequestRetryHandler ;
5353import org .apache .http .impl .client .HttpClientBuilder ;
5454import org .apache .http .impl .conn .PoolingHttpClientConnectionManager ;
5555import org .apache .http .message .BasicHeader ;
56- import org .apache .http .message .BasicHeaderElementIterator ;
57- import org .apache .http .protocol .HTTP ;
5856import org .apache .http .protocol .HttpContext ;
5957
6058import ru .yandex .clickhouse .settings .ClickHouseProperties ;
@@ -71,16 +69,32 @@ public ClickHouseHttpClientBuilder(ClickHouseProperties properties) {
7169 public CloseableHttpClient buildClient () throws Exception {
7270 return HttpClientBuilder .create ()
7371 .setConnectionManager (getConnectionManager ())
72+ .setRetryHandler (getRequestRetryHandler ())
7473 .setConnectionReuseStrategy (getConnectionReuseStrategy ())
7574 .setDefaultConnectionConfig (getConnectionConfig ())
7675 .setDefaultRequestConfig (getRequestConfig ())
7776 .setDefaultHeaders (getDefaultHeaders ())
7877 .setDefaultCredentialsProvider (getDefaultCredentialsProvider ())
79- .disableContentCompression () // gzip здесь ни к чему. Используется lz4 при compress=1
78+ .disableContentCompression () // gzip is not needed. Use lz4 when compress=1
8079 .disableRedirectHandling ()
8180 .build ();
8281 }
8382
83+ private HttpRequestRetryHandler getRequestRetryHandler () {
84+ final int maxRetries = properties .getMaxRetries ();
85+ return new DefaultHttpRequestRetryHandler (maxRetries , false ) {
86+ @ Override
87+ public boolean retryRequest (IOException exception , int executionCount , HttpContext context ) {
88+ if (executionCount > maxRetries || context == null
89+ || !Boolean .TRUE .equals (context .getAttribute ("is_idempotent" ))) {
90+ return false ;
91+ }
92+
93+ return (exception instanceof NoHttpResponseException ) || super .retryRequest (exception , executionCount , context );
94+ }
95+ };
96+ }
97+
8498 public static HttpClientContext createClientContext (ClickHouseProperties props ) {
8599 if (props == null
86100 || !isConfigurationValidForAuth (props ))
@@ -155,29 +169,6 @@ private Collection<Header> getDefaultHeaders() {
155169 return headers ;
156170 }
157171
158- private ConnectionKeepAliveStrategy createKeepAliveStrategy () {
159- return new ConnectionKeepAliveStrategy () {
160- @ Override
161- public long getKeepAliveDuration (HttpResponse httpResponse , HttpContext httpContext ) {
162- // in case of errors keep-alive not always works. close connection just in case
163- if (httpResponse .getStatusLine ().getStatusCode () != HttpURLConnection .HTTP_OK ) {
164- return -1 ;
165- }
166- HeaderElementIterator it = new BasicHeaderElementIterator (
167- httpResponse .headerIterator (HTTP .CONN_DIRECTIVE ));
168- while (it .hasNext ()) {
169- HeaderElement he = it .nextElement ();
170- String param = he .getName ();
171- //String value = he.getValue();
172- if (param != null && param .equalsIgnoreCase (HTTP .CONN_KEEP_ALIVE )) {
173- return properties .getKeepAliveTimeout ();
174- }
175- }
176- return -1 ;
177- }
178- };
179- }
180-
181172 private SSLContext getSSLContext ()
182173 throws CertificateException , NoSuchAlgorithmException , KeyStoreException , IOException , KeyManagementException {
183174 SSLContext ctx = SSLContext .getInstance ("TLS" );
0 commit comments