Discussion:
How to replace / update a httpClient instance?
Daly, Paul
2018-04-25 08:12:20 UTC
Permalink
Hi All,


First time poster, hoping you can provide some advice/help!


WE have developed a connector to a back end server using HTTP Client. The component with the HTTPClient runs as part of, and is used by, a larger application - ie not a standalone application which we have control to completely change. As per performance optimisations guide I reuse the HTTPClient object within this communication component. Its's initialised on first use and within the running application, the httpClient object will be passed out to multiple threads who each will execute their own particular request to the back end. Request objects are reset() by the thread which used them.


So far so good. All seems to work ok.

However, the application we are running within provides a front end for users. For admins, this allows changing of various configuration items, some of which are the timeouts for this component. If an admin changes those values we want to be able to change the HTTPClient to use the new values without a restart of the application. The application framework provides an annotation I can use in my class to pick up config change events. I can react on that to refresh my timeout values and recreate the client.

This is where my question starts. My solution so far is to simply replace the static httpClient with the newly build object which has the new timeout values. But this may lead to problems because I am not sure if the original object will actually be tidied up by GC once the threads using it have closed their connections.

Ideally I would want to explicitly close the original httpClient before pointing the static at the new one. However, this means threads which have already been handed this httpClient reference will fail (user impact - not acceptable).

So I am kind of stuck on how to implement this safely

Ideally I could just change the configured timeouts in the existing httpClient but I don't see how to do that.

Code snippets are below.

Any ideas / suggestions would be appreciated!




/**
* A HTTP Client to be used by the EIS PH
*/
private static CloseableHttpClient httpClient = null;


// get client
public static CloseableHttpClient getClient() {

if (httpClient == null) {
// create new client
init(false);
}

return httpClient;
}


// initialize the client
private static synchronized void init(boolean forceNewClient) {

if (forceNewClient || (httpClient == null)) {

// get config, timeouts etc from application framework...
.....

// create the client
CloseableHttpClient newClient = HttpClientBuilder.create().useSystemProperties()
.setDefaultRequestConfig(config).setMaxConnPerRoute(maxConnectionsPerRoute)
.setMaxConnTotal(totalMaxConnection).evictExpiredConnections()
.evictIdleConnections(idleEvictTime, TimeUnit.MINUTES)
.setConnectionTimeToLive(timeToLive, TimeUnit.MINUTES).build();

// set the static member to be the new client now that its built
httpClient = newClient;

}


// listen for application config change events which affect this component
@ConfigChangedListener(ConfigurationHelper.OWNER)
public void onConfigChanged() {
init(true);
}


Thanks in advance!

Paul.




Paul Daly

Diebold Nixdorf
3022 Lake Drive,
Citywest Business Park,
Dublin 24,
Ireland
Mobile: +353 87 276 4736
***@dieboldnixdorf.com<mailto:***@dieboldnixdorf.com>
DieboldNixdorf.com

[1_twitter_logo_24px]<https://twitter.com/DieboldNixdorf> [2_facebook_logo_24px] <https://www.facebook.com/DieboldNixdorf> [3_youtube_logo_24px] <https://www.youtube.com/DieboldNixdorf> [4_linkedin_logo_24px] <https://www.linkedin.com/company/diebold> [5_blog_logo_24px] <http://blog.dieboldnixdorf.com/>
Reg. in England No. 3841833
This document and any attachments to it contain information that is private and confidential and should only be read by those persons to whom they are addressed. No person, without subsequent written confirmation of their contents, should rely upon the contents of this e-mail. This e-mail and the information it contains are supplied in good faith, but Diebold Nixdorf (Ireland) Limited shall not be under any liability in damages or otherwise for any reliance that may be placed upon them by the recipient. Further, this document is sent for information and / or negotiating purposes only, and shall not have the effect of creating a contract between the parties. If you have received this e-mail in error, please notify the sender(s) immediately by telephone. Please also destroy and delete the message from your computer. Any form of reproduction, dissemination, copying, disclosure, modification, distribution and / or publication of this e-mail is strictly prohibited save unless expressly authorised by the sender
Yossi Tamari
2018-04-25 09:48:53 UTC
Permalink
Hi Paul,



Depending on exactly what timeouts you need to change dynamically, maybe you
can use RequestConfig to set it per request instead of per Client?

If not, you could override PoolingHttpClientConnectionManager, add a
shutdown flag, and override releaseConnection, so that if this flag is true,
it will check if there are any other leased connections (using
getTotalStats), and if not it will call shutdown(). Then you can stay with
your current approach of creating a new Client, but feel safe that you only
close the previous Client when it is no longer in use.



Yossi.



From: Daly, Paul <***@dieboldnixdorf.com>
Sent: 25 April 2018 11:12
To: httpclient-***@hc.apache.org
Subject: How to replace / update a httpClient instance?



Hi All,





First time poster, hoping you can provide some advice/help!





WE have developed a connector to a back end server using HTTP Client. The
component with the HTTPClient runs as part of, and is used by, a larger
application - ie not a standalone application which we have control to
completely change. As per performance optimisations guide I reuse the
HTTPClient object within this communication component. Its's initialised on
first use and within the running application, the httpClient object will be
passed out to multiple threads who each will execute their own particular
request to the back end. Request objects are reset() by the thread which
used them.





So far so good. All seems to work ok.



However, the application we are running within provides a front end for
users. For admins, this allows changing of various configuration items, some
of which are the timeouts for this component. If an admin changes those
values we want to be able to change the HTTPClient to use the new values
without a restart of the application. The application framework provides an
annotation I can use in my class to pick up config change events. I can
react on that to refresh my timeout values and recreate the client.



This is where my question starts. My solution so far is to simply replace
the static httpClient with the newly build object which has the new timeout
values. But this may lead to problems because I am not sure if the original
object will actually be tidied up by GC once the threads using it have
closed their connections.



Ideally I would want to explicitly close the original httpClient before
pointing the static at the new one. However, this means threads which have
already been handed this httpClient reference will fail (user impact - not
acceptable).



So I am kind of stuck on how to implement this safely



Ideally I could just change the configured timeouts in the existing
httpClient but I don't see how to do that.



Code snippets are below.



Any ideas / suggestions would be appreciated!











/**

* A HTTP Client to be used by the EIS PH

*/

private static CloseableHttpClient httpClient = null;





// get client

public static CloseableHttpClient getClient() {



if (httpClient == null) {

// create new client

init(false);

}



return httpClient;

}





// initialize the client

private static synchronized void init(boolean forceNewClient) {



if (forceNewClient || (httpClient == null)) {



// get config, timeouts etc from application framework.

...



// create the client

CloseableHttpClient newClient =
HttpClientBuilder.create().useSystemProperties()


.setDefaultRequestConfig(config).setMaxConnPerRoute(maxConnectionsPerRoute)

.setMaxConnTotal(totalMaxConnection).evictExpiredConnections()

.evictIdleConnections(idleEvictTime, TimeUnit.MINUTES)

.setConnectionTimeToLive(timeToLive, TimeUnit.MINUTES).build();



// set the static member to be the new client now that its built

httpClient = newClient;



}





// listen for application config change events which affect this component

@ConfigChangedListener(ConfigurationHelper.OWNER)

public void onConfigChanged() {

init(true);

}





Thanks in advance!



Paul.









Paul Daly



Diebold Nixdorf

3022 Lake Drive,

Citywest Business Park,

Dublin 24,

Ireland

Mobile: +353 87 276 4736

***@dieboldnixdorf.com <mailto:***@dieboldnixdorf.com>

DieboldNixdorf.com



<https://twitter.com/DieboldNixdorf>
<https://www.facebook.com/DieboldNixdorf>
<https://www.youtube.com/DieboldNixdorf>
<https://www.linkedin.com/company/diebold>
<http://blog.dieboldnixdorf.com/>

Reg. in England No. 3841833

This document and any attachments to it contain information that is private
and confidential and should only be read by those persons to whom they are
addressed. No person, without subsequent written confirmation of their
contents, should rely upon the contents of this e-mail. This e-mail and the
information it contains are supplied in good faith, but Diebold Nixdorf
(Ireland) Limited shall not be under any liability in damages or otherwise
for any reliance that may be placed upon them by the recipient. Further,
this document is sent for information and / or negotiating purposes only,
and shall not have the effect of creating a contract between the parties. If
you have received this e-mail in error, please notify the sender(s)
immediately by telephone. Please also destroy and delete the message from
your computer. Any form of reproduction, dissemination, copying, disclosure,
modification, distribution and / or publication of this e-mail is strictly
prohibited save unless expressly authorised by the sender
Oleg Kalnichevski
2018-04-25 10:08:31 UTC
Permalink
Post by Yossi Tamari
Hi Paul,
 
Depending on exactly what timeouts you need to change dynamically, maybe you
can use RequestConfig to set it per request instead of per Client?
If not, you could override PoolingHttpClientConnectionManager, add a
shutdown flag, and override releaseConnection, so that if this flag is true,
it will check if there are any other leased connections (using
getTotalStats), and if not it will call shutdown(). Then you can stay with
your current approach of creating a new Client, but feel safe that you only
close the previous Client when it is no longer in use.
+1 to that

Generally one should only need to modify HttpContext associated with
logically related requests, not HttpClient instance used to execute
them.

Cheers

Oleg
Post by Yossi Tamari
 
               Yossi.
 
Sent: 25 April 2018 11:12
Subject: How to replace / update a httpClient instance?
 
Hi All,
 
 
First time poster, hoping you can provide some advice/help!
 
 
WE have developed a connector to a back end server using HTTP Client. The
component with the HTTPClient runs as part of, and is used by, a larger
application - ie not a standalone application which we have control to
completely change. As per performance optimisations guide I reuse the
HTTPClient object within this communication component. Its's
initialised on
first use and within the running application, the httpClient object will be
passed out to multiple threads who each will execute their own
particular
request to the back end. Request objects are reset() by the thread which
used them.
 
 
So far so good. All seems to work ok.
 
However, the application we are running within provides a front end for
users. For admins, this allows changing of various configuration items, some
of which are the timeouts for this component. If an admin changes those
values we want to be able to change the HTTPClient to use the new values
without a restart of the application. The application framework provides an
annotation I can use in my class to pick up config change events. I can
react on that to refresh my timeout values and recreate the client.
 
This is where my question starts.  My solution so far is to simply
replace
the static httpClient with the newly build object which has the new timeout
values. But this may lead to problems because I am not sure if the original
object will actually be tidied up by GC once the threads using it have
closed their connections. 
 
Ideally I would want to explicitly close the original httpClient before
pointing the static at the new one. However, this means threads which have
already been handed this httpClient reference will fail (user impact - not
acceptable).
 
So I am kind of stuck on how to implement this safely
 
Ideally I could just change the configured timeouts in the existing
httpClient but I don't see how to do that. 
 
Code snippets are below.
 
Any ideas / suggestions would be appreciated!
 
 
 
 
 
/**
* A HTTP Client to be used by the EIS PH
*/
private static CloseableHttpClient httpClient = null;
 
 
// get client
public static CloseableHttpClient getClient() {
 
if (httpClient == null) {
// create new client
       init(false);
}
 
return httpClient;
}
 
 
// initialize the client
private static synchronized void init(boolean forceNewClient) {
 
if (forceNewClient || (httpClient == null)) {
 
// get config, timeouts etc from application framework.
...
 
       // create the client
CloseableHttpClient newClient =
HttpClientBuilder.create().useSystemProperties()
 
.setDefaultRequestConfig(config).setMaxConnPerRoute(maxConnectionsPer
Route)
             .setMaxConnTotal(totalMaxConnection).evictExpiredConnect
ions()
             .evictIdleConnections(idleEvictTime, TimeUnit.MINUTES)
             .setConnectionTimeToLive(timeToLive,
TimeUnit.MINUTES).build();
 
// set the static member to be the new client now that its built
httpClient = newClient;
 
}
 
 
// listen for application config change events which affect this component
@ConfigChangedListener(ConfigurationHelper.OWNER)
public void onConfigChanged() {
       init(true);
}
 
 
Thanks in advance!
 
Paul.
 
 
 
 
Paul Daly
 
Diebold Nixdorf
3022 Lake Drive,
Citywest Business Park,
Dublin 24,
Ireland
Mobile: +353 87 276 4736
DieboldNixdorf.com
 
 <https://twitter.com/DieboldNixdorf>
<https://www.facebook.com/DieboldNixdorf>
<https://www.youtube.com/DieboldNixdorf>
<https://www.linkedin.com/company/diebold>
<http://blog.dieboldnixdorf.com/> 
Reg. in England No. 3841833 
This document and any attachments to it contain information that is private
and confidential and should only be read by those persons to whom they are
addressed. No person, without subsequent written confirmation of their
contents, should rely upon the contents of this e-mail. This e-mail and the
information it contains are supplied in good faith, but Diebold Nixdorf
(Ireland) Limited shall not be under any liability in damages or otherwise
for any reliance that may be placed upon them by the recipient. Further,
this document is sent for information and / or negotiating purposes only,
and shall not have the effect of creating a contract between the parties. If
you have received this e-mail in error, please notify the sender(s)
immediately by telephone. Please also destroy and delete the message from
your computer. Any form of reproduction, dissemination, copying, disclosure,
modification, distribution and / or publication of this e-mail is strictly
prohibited save unless expressly authorised by the sender
 
---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-***@hc.apache.org
For additional commands, e-mail: httpclient-users-***@hc.apache.org
Daly, Paul
2018-04-25 11:46:57 UTC
Permalink
Thank you both for the hints!

I didn’t realise I could set connection specific configs in the request context. So that is what I have done now - for each request I just grab the socket, connection and pool timeout from our framework configuration service and apply it on the context before sending the request.

So no need to update the httpclient at all. Simple tweak to code in the end and works as expected.

// create the client
httpClient = HttpClientFactory.getClient();

// create the context for this thread
HttpClientContext httpContext = HttpClientContext.create();

// get timeouts from config
httpContext.setRequestConfig(getRequestConfig());

HttpResponse serviceResponse = httpClient.execute(httpRequest, httpContext);


Thanks again!

Paul.



-----Original Message-----
From: Oleg Kalnichevski [mailto:***@apache.org]
Sent: Wednesday, April 25, 2018 11:09 AM
To: HttpClient User Discussion <httpclient-***@hc.apache.org>
Subject: Re: How to replace / update a httpClient instance?
Post by Yossi Tamari
Hi Paul,
 
Depending on exactly what timeouts you need to change dynamically, maybe you
can use RequestConfig to set it per request instead of per Client?
If not, you could override PoolingHttpClientConnectionManager, add a
shutdown flag, and override releaseConnection, so that if this flag is true,
it will check if there are any other leased connections (using
getTotalStats), and if not it will call shutdown(). Then you can stay with
your current approach of creating a new Client, but feel safe that you only
close the previous Client when it is no longer in use.
+1 to that

Generally one should only need to modify HttpContext associated with
logically related requests, not HttpClient instance used to execute
them.

Cheers

Oleg
Post by Yossi Tamari
 
               Yossi.
 
Sent: 25 April 2018 11:12
Subject: How to replace / update a httpClient instance?
 
Hi All,
 
 
First time poster, hoping you can provide some advice/help!
 
 
WE have developed a connector to a back end server using HTTP Client. The
component with the HTTPClient runs as part of, and is used by, a larger
application - ie not a standalone application which we have control to
completely change. As per performance optimisations guide I reuse the
HTTPClient object within this communication component. Its's
initialised on
first use and within the running application, the httpClient object will be
passed out to multiple threads who each will execute their own
particular
request to the back end. Request objects are reset() by the thread which
used them.
 
 
So far so good. All seems to work ok.
 
However, the application we are running within provides a front end for
users. For admins, this allows changing of various configuration items, some
of which are the timeouts for this component. If an admin changes those
values we want to be able to change the HTTPClient to use the new values
without a restart of the application. The application framework provides an
annotation I can use in my class to pick up config change events. I can
react on that to refresh my timeout values and recreate the client.
 
This is where my question starts.  My solution so far is to simply
replace
the static httpClient with the newly build object which has the new timeout
values. But this may lead to problems because I am not sure if the original
object will actually be tidied up by GC once the threads using it have
closed their connections. 
 
Ideally I would want to explicitly close the original httpClient before
pointing the static at the new one. However, this means threads which have
already been handed this httpClient reference will fail (user impact - not
acceptable).
 
So I am kind of stuck on how to implement this safely
 
Ideally I could just change the configured timeouts in the existing
httpClient but I don't see how to do that. 
 
Code snippets are below.
 
Any ideas / suggestions would be appreciated!
 
 
 
 
 
/**
* A HTTP Client to be used by the EIS PH
*/
private static CloseableHttpClient httpClient = null;
 
 
// get client
public static CloseableHttpClient getClient() {
 
if (httpClient == null) {
// create new client
       init(false);
}
 
return httpClient;
}
 
 
// initialize the client
private static synchronized void init(boolean forceNewClient) {
 
if (forceNewClient || (httpClient == null)) {
 
// get config, timeouts etc from application framework.
...
 
       // create the client
CloseableHttpClient newClient =
HttpClientBuilder.create().useSystemProperties()
 
.setDefaultRequestConfig(config).setMaxConnPerRoute(maxConnectionsPer
Route)
             .setMaxConnTotal(totalMaxConnection).evictExpiredConnect
ions()
             .evictIdleConnections(idleEvictTime, TimeUnit.MINUTES)
             .setConnectionTimeToLive(timeToLive,
TimeUnit.MINUTES).build();
 
// set the static member to be the new client now that its built
httpClient = newClient;
 
}
 
 
// listen for application config change events which affect this component
@ConfigChangedListener(ConfigurationHelper.OWNER)
public void onConfigChanged() {
       init(true);
}
 
 
Thanks in advance!
 
Paul.
 
 
 
 
Paul Daly
 
Diebold Nixdorf
3022 Lake Drive,
Citywest Business Park,
Dublin 24,
Ireland
Mobile: +353 87 276 4736
DieboldNixdorf.com
 
 <https://twitter.com/DieboldNixdorf>
<https://www.facebook.com/DieboldNixdorf>
<https://www.youtube.com/DieboldNixdorf>
<https://www.linkedin.com/company/diebold>
<http://blog.dieboldnixdorf.com/> 
Reg. in England No. 3841833 
This document and any attachments to it contain information that is private
and confidential and should only be read by those persons to whom they are
addressed. No person, without subsequent written confirmation of their
contents, should rely upon the contents of this e-mail. This e-mail and the
information it contains are supplied in good faith, but Diebold Nixdorf
(Ireland) Limited shall not be under any liability in damages or otherwise
for any reliance that may be placed upon them by the recipient. Further,
this document is sent for information and / or negotiating purposes only,
and shall not have the effect of creating a contract between the parties. If
you have received this e-mail in error, please notify the sender(s)
immediately by telephone. Please also destroy and delete the message from
your computer. Any form of reproduction, dissemination, copying, disclosure,
modification, distribution and / or publication of this e-mail is strictly
prohibited save unless expressly authorised by the sender
 
---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-***@hc.apache.org
For additional commands, e-mail: httpclient-users-***@hc.apache.org

B�KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKCB��[��X��ܚX�KK[XZ[��Y[� ]\�\��][��X��ܚX�P˘\X�K�ܙ�B��܈Y][ۘ[��[X[
Loading...