1616import org .apache .hc .client5 .http .config .RequestConfig ;
1717import org .apache .hc .client5 .http .impl .classic .CloseableHttpClient ;
1818import org .apache .hc .client5 .http .impl .classic .HttpClientBuilder ;
19+ import org .apache .hc .client5 .http .impl .io .BasicHttpClientConnectionManager ;
1920import org .apache .hc .client5 .http .impl .io .PoolingHttpClientConnectionManagerBuilder ;
21+ import org .apache .hc .client5 .http .io .HttpClientConnectionManager ;
2022import org .apache .hc .client5 .http .protocol .HttpClientContext ;
23+ import org .apache .hc .client5 .http .socket .ConnectionSocketFactory ;
24+ import org .apache .hc .client5 .http .socket .PlainConnectionSocketFactory ;
2125import org .apache .hc .client5 .http .ssl .SSLConnectionSocketFactory ;
2226import org .apache .hc .core5 .http .ClassicHttpResponse ;
2327import org .apache .hc .core5 .http .ConnectionRequestTimeoutException ;
2832import org .apache .hc .core5 .http .HttpHost ;
2933import org .apache .hc .core5 .http .HttpStatus ;
3034import org .apache .hc .core5 .http .NoHttpResponseException ;
35+ import org .apache .hc .core5 .http .config .RegistryBuilder ;
3136import org .apache .hc .core5 .http .io .SocketConfig ;
3237import org .apache .hc .core5 .http .io .entity .EntityTemplate ;
3338import org .apache .hc .core5 .io .IOCallback ;
4853import java .net .URI ;
4954import java .net .URISyntaxException ;
5055import java .net .UnknownHostException ;
56+ import java .security .NoSuchAlgorithmException ;
5157import java .util .Base64 ;
5258import java .util .Map ;
5359import java .util .concurrent .TimeUnit ;
@@ -72,7 +78,8 @@ public HttpAPIClientHelper(Map<String, String> configuration) {
7278
7379 RequestConfig .Builder reqConfBuilder = RequestConfig .custom ();
7480 MapUtils .applyLong (chConfiguration , "connection_request_timeout" ,
75- (t ) -> reqConfBuilder .setConnectionRequestTimeout (t , TimeUnit .MILLISECONDS ));
81+ (t ) -> reqConfBuilder
82+ .setConnectionRequestTimeout (t , TimeUnit .MILLISECONDS ));
7683
7784 this .baseRequestConfig = reqConfBuilder .build ();
7885
@@ -82,42 +89,19 @@ public HttpAPIClientHelper(Map<String, String> configuration) {
8289 LOG .info ("client compression: {}, server compression: {}, http compression: {}" , usingClientCompression , usingServerCompression , useHttpCompression );
8390 }
8491
85- public CloseableHttpClient createHttpClient () {
86-
87- // Top Level builders
88- HttpClientBuilder clientBuilder = HttpClientBuilder .create ();
89-
90-
91- // Socket configuration
92- SocketConfig .Builder soCfgBuilder = SocketConfig .custom ();
93- MapUtils .applyInt (chConfiguration , ClickHouseClientOption .SOCKET_TIMEOUT .getKey (),
94- (t ) -> soCfgBuilder .setSoTimeout (t , TimeUnit .MILLISECONDS ));
95- MapUtils .applyInt (chConfiguration , ClickHouseClientOption .SOCKET_RCVBUF .getKey (),
96- soCfgBuilder ::setRcvBufSize );
97- MapUtils .applyInt (chConfiguration , ClickHouseClientOption .SOCKET_SNDBUF .getKey (),
98- soCfgBuilder ::setSndBufSize );
99- MapUtils .applyInt (chConfiguration , ClickHouseClientOption .SOCKET_LINGER .getKey (),
100- (v ) -> soCfgBuilder .setSoLinger (v , TimeUnit .SECONDS ));
101-
102- // Connection manager
103- PoolingHttpClientConnectionManagerBuilder connMgrBuilder = PoolingHttpClientConnectionManagerBuilder .create ()
104- .setConnPoolPolicy (PoolReusePolicy .LIFO )
105- .setPoolConcurrencyPolicy (PoolConcurrencyPolicy .STRICT );
106-
107- ConnectionConfig .Builder connConfig = ConnectionConfig .custom ();
108- MapUtils .applyInt (chConfiguration , ClickHouseClientOption .CONNECTION_TIMEOUT .getKey (),
109- (t ) -> connConfig .setConnectTimeout (t , TimeUnit .MILLISECONDS ));
110-
111-
112- connMgrBuilder .setDefaultConnectionConfig (connConfig .build ());
113- connMgrBuilder .setMaxConnTotal (Integer .MAX_VALUE ); // as we do not know how many routes we will have
114- MapUtils .applyInt (chConfiguration , ClickHouseHttpOption .MAX_OPEN_CONNECTIONS .getKey (),
115- connMgrBuilder ::setMaxConnPerRoute );
116-
92+ /**
93+ * Creates or returns default SSL context.
94+ * @return SSLContext
95+ */
96+ public SSLContext createSSLContext () {
97+ SSLContext sslContext ;
98+ try {
99+ sslContext = SSLContext .getDefault ();
100+ } catch (NoSuchAlgorithmException e ) {
101+ throw new ClientException ("Failed to create default SSL context" , e );
102+ }
117103 ClickHouseSslContextProvider sslContextProvider = ClickHouseSslContextProvider .getProvider ();
118-
119104 String trustStorePath = chConfiguration .get (ClickHouseClientOption .TRUST_STORE .getKey ());
120- SSLContext sslContext = null ;
121105 if (trustStorePath != null ) {
122106 try {
123107 sslContext = sslContextProvider .getSslContextFromKeyStore (
@@ -142,12 +126,57 @@ public CloseableHttpClient createHttpClient() {
142126 throw new ClientMisconfigurationException ("Failed to create SSL context from certificates" , e );
143127 }
144128 }
145- if ( sslContext != null ) {
146- connMgrBuilder . setSSLSocketFactory ( new SSLConnectionSocketFactory ( sslContext ));
147- }
129+ return sslContext ;
130+ }
131+
148132
149- connMgrBuilder .setDefaultSocketConfig (soCfgBuilder .build ());
150- clientBuilder .setConnectionManager (connMgrBuilder .build ());
133+ private HttpClientConnectionManager basicConnectionManager (SSLContext sslContext , SocketConfig socketConfig ) {
134+ RegistryBuilder <ConnectionSocketFactory > registryBuilder = RegistryBuilder .create ();
135+ registryBuilder .register ("http" , PlainConnectionSocketFactory .getSocketFactory ());
136+ registryBuilder .register ("https" , new SSLConnectionSocketFactory (sslContext ));
137+
138+
139+ BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager (registryBuilder .build ());
140+ connManager .setSocketConfig (socketConfig );
141+ return connManager ;
142+ }
143+
144+ private HttpClientConnectionManager poolConnectionManager (SSLContext sslContext , SocketConfig socketConfig ) {
145+ PoolingHttpClientConnectionManagerBuilder connMgrBuilder = PoolingHttpClientConnectionManagerBuilder .create ()
146+ .setConnPoolPolicy (PoolReusePolicy .LIFO )
147+ .setPoolConcurrencyPolicy (PoolConcurrencyPolicy .STRICT );
148+
149+ ConnectionConfig .Builder connConfig = ConnectionConfig .custom ();
150+ MapUtils .applyInt (chConfiguration , ClickHouseClientOption .CONNECTION_TIMEOUT .getKey (),
151+ (t ) -> connConfig .setConnectTimeout (t , TimeUnit .MILLISECONDS ));
152+
153+
154+ connMgrBuilder .setDefaultConnectionConfig (connConfig .build ());
155+ connMgrBuilder .setMaxConnTotal (Integer .MAX_VALUE ); // as we do not know how many routes we will have
156+ MapUtils .applyInt (chConfiguration , ClickHouseHttpOption .MAX_OPEN_CONNECTIONS .getKey (),
157+ connMgrBuilder ::setMaxConnPerRoute );
158+
159+ connMgrBuilder .setSSLSocketFactory (new SSLConnectionSocketFactory (sslContext ));
160+ connMgrBuilder .setDefaultSocketConfig (socketConfig );
161+ return connMgrBuilder .build ();
162+ }
163+
164+ public CloseableHttpClient createHttpClient () {
165+
166+ // Top Level builders
167+ HttpClientBuilder clientBuilder = HttpClientBuilder .create ();
168+ SSLContext sslContext = createSSLContext ();
169+
170+ // Socket configuration
171+ SocketConfig .Builder soCfgBuilder = SocketConfig .custom ();
172+ MapUtils .applyInt (chConfiguration , ClickHouseClientOption .SOCKET_TIMEOUT .getKey (),
173+ (t ) -> soCfgBuilder .setSoTimeout (t , TimeUnit .MILLISECONDS ));
174+ MapUtils .applyInt (chConfiguration , ClickHouseClientOption .SOCKET_RCVBUF .getKey (),
175+ soCfgBuilder ::setRcvBufSize );
176+ MapUtils .applyInt (chConfiguration , ClickHouseClientOption .SOCKET_SNDBUF .getKey (),
177+ soCfgBuilder ::setSndBufSize );
178+ MapUtils .applyInt (chConfiguration , ClickHouseClientOption .SOCKET_LINGER .getKey (),
179+ (v ) -> soCfgBuilder .setSoLinger (v , TimeUnit .SECONDS ));
151180
152181 // Proxy
153182 String proxyHost = chConfiguration .get (ClickHouseClientOption .PROXY_HOST .getKey ());
@@ -173,6 +202,15 @@ public CloseableHttpClient createHttpClient() {
173202 .equalsIgnoreCase ("false" )) {
174203 clientBuilder .disableCookieManagement ();
175204 }
205+ SocketConfig socketConfig = soCfgBuilder .build ();
206+
207+ // Connection manager
208+ boolean isConnectionPooling = MapUtils .getFlag (chConfiguration , "connection_pool_enabled" );
209+ if (isConnectionPooling ) {
210+ clientBuilder .setConnectionManager (poolConnectionManager (sslContext , socketConfig ));
211+ } else {
212+ clientBuilder .setConnectionManager (basicConnectionManager (sslContext , socketConfig ));
213+ }
176214
177215 return clientBuilder .build ();
178216 }
0 commit comments