On Wed, 2015-05-20 at 14:53 +0000, Mark A. Claassen wrote: > (3) or whenever message content is fully consumed. > > response closure but at as soon as the content stream returns -1 > > Nice. I never thought to check that. Unfortunately, this wasn't happening > in my test case. We have our own message structure where we know how long > the response is going to be and so never read past the end (getting the -1). > However, because we don't know the length immediately, we can't put it in the > content length header. I would imagine that this doesn't give HttpClient a > chance to detect the EOF condition. >
This does not seem to add up. HttpClient keeps connections alive only if it is sure the last message has been fully consumed. Otherwise it drops the connection as non-reusable. Oleg > I believe I am using the library "correctly", but I guess I found a condition > use case that corrupts the pool a bit. Is this something that can be > considered for a future version, or is this one of those things where making > a slight change would cause a lot of complications? > > Mark Claassen > Senior Software Engineer > > Donnell Systems, Inc. > 130 South Main Street > Leighton Plaza Suite 375 > South Bend, IN 46601 > E-mail: mailto:[email protected] > Voice: (574)232-3784 > Fax: (574)232-4014 > > > > -----Original Message----- > From: Oleg Kalnichevski [mailto:[email protected]] > Sent: Wednesday, May 20, 2015 9:41 AM > To: HttpClient User Discussion > Subject: Re: Strange SSL error > > On Wed, 2015-05-20 at 13:30 +0000, Mark A. Claassen wrote: > > > 'updated' represents the time of the last update on the client > > side as opposed to 'expiry' which represents keep-alive period > > > > Maybe, but the expire time is then set based on the new value of "updated". > > So, even though no network activity occurred, the new expiration time is > > set as if there was. > > The impact of this is that, after reading a response from the server, any > > processing time that is done between the reading of the data and the > > releasing of the connection is ignored. > > You see, the connection release is triggered whenever either of these events > take place. > > (1) request is aborted > (2) response is closed > (3) or whenever message content is fully consumed. > > So, in the normal course of request execution the expiry time gets updated > not at the time of response closure but at as soon as the content stream > returns -1 (end of stream). That is, pretty much at the same time as the > keep-alive timer starts ticking at the server side. > > Oleg > > > > > If the KeepAlive duration is 5 seconds, but some code takes 6 seconds to > > process the results, an expired entry will be placed back into the pool. > > This might not be a big deal, but it defeats the purpose of the check. It > > will also force a stale connection check on a connection that is known to > > be expired. > > > > This is assuming the pattern of: > > Open Connection > > try { > > Send request > > Read response > > Do some initial processing of the response > > } > > finally { > > Close connection > > } > > > > Perhaps the "newExpiry" should be calculated before the "updated" is set to > > the current time? > > > > public synchronized void updateExpiry(final long time, final TimeUnit > > tunit) { > > Args.notNull(tunit, "Time unit"); > > this.updated = System.currentTimeMillis(); > > final long newExpiry; > > if (time > 0) { > > newExpiry = this.updated + tunit.toMillis(time); > > } else { > > newExpiry = Long.MAX_VALUE; > > } > > this.expiry = Math.min(newExpiry, this.validityDeadline); > > } > > > > > > > > Mark Claassen > > Senior Software Engineer > > > > Donnell Systems, Inc. > > 130 South Main Street > > Leighton Plaza Suite 375 > > South Bend, IN 46601 > > E-mail: mailto:[email protected] > > Voice: (574)232-3784 > > Fax: (574)232-4014 > > > > ------------------------------------------- > > Confidentiality Notice: OCIESERVICE > > ------------------------------------------- > > The contents of this e-mail message and any attachments are intended solely > > for the addressee(s) named in this message. This communication is intended > > to be and to remain confidential. If you are not the intended recipient of > > this message, or if this message has been addressed to you in error, please > > immediately alert the sender by reply e-mail and then delete this message > > and its attachments. Do not deliver, distribute, copy, disclose the > > contents or take any action in reliance upon the information contained in > > the communication or any attachments. > > > > -----Original Message----- > > From: Oleg Kalnichevski [mailto:[email protected]] > > Sent: Tuesday, May 19, 2015 4:26 AM > > To: HttpClient User Discussion > > Subject: Re: Strange SSL error > > > > On Fri, 2015-05-15 at 16:08 +0000, Mark A. Claassen wrote: > > > Thanks. However, I am still getting the error; even when I do: > > > connectionManager.setValidateAfterInactivity(1); > > > > > > I think this is just because the server can close a keepalive > > > connection at any time. So, if the server decides to kill off the > > > connection in that time slice, the request fails. This most often > > > comes back as a org.apache.http.NoHttpResponseException which the > > > default retry handler will not retry. It seems the only way I can > > > be sure than my connections succeed is to disable keep-alives > > > entirely with a ConnectionReuseStrategy. (Also, Using > > > RequestConfig.setStaleConnectionCheckEnabled(true) seems works > > > better than the setting the setValidateAfterInactivity to 1. I am > > > not sure > > > why.) > > > > > > Question: > > > releaseConnection in PoolingHttpClientConnectionManager calls > > > updateExpiry in PoolEntry. However, this method in PoolEntry also sets > > > the "updated" time. What is "updated" supposed to represent? If it is > > > mainly used to test the keepalive stuff, then it should be updated based > > > on network activity. It doesn’t seem that changing a time to expire > > > value should be counted as "activity" on the connection. > > > > > > > > > > 'updated' represents the time of the last update on the client side as > > opposed to 'expiry' which represents keep-alive period as communicated by > > the server. One might want to close connections after, say, 3 seconds of > > inactivity on client side even though the server's keep-alive is, say, 5 > > seconds. > > > > Oleg > > > > > > > > Mark Claassen > > > Senior Software Engineer > > > > > > Donnell Systems, Inc. > > > 130 South Main Street > > > Leighton Plaza Suite 375 > > > South Bend, IN 46601 > > > E-mail: mailto:[email protected] > > > Voice: (574)232-3784 > > > Fax: (574)232-4014 > > > > > > ------------------------------------------- > > > Confidentiality Notice: OCIESERVICE > > > ------------------------------------------- > > > The contents of this e-mail message and any attachments are intended > > > solely for the addressee(s) named in this message. This communication is > > > intended to be and to remain confidential. If you are not the intended > > > recipient of this message, or if this message has been addressed to you > > > in error, please immediately alert the sender by reply e-mail and then > > > delete this message and its attachments. Do not deliver, distribute, > > > copy, disclose the contents or take any action in reliance upon the > > > information contained in the communication or any attachments. > > > > > > > > > -----Original Message----- > > > From: Oleg Kalnichevski [mailto:[email protected]] > > > Sent: Thursday, May 14, 2015 4:38 AM > > > To: HttpClient User Discussion > > > Subject: Re: Strange SSL error > > > > > > On Wed, 2015-05-13 at 20:58 +0000, Mark A. Claassen wrote: > > > > The 4.4.1 code doesn't seem to help. > > > > > > > > I have been able to reproduce the issue more regularly now. It seems > > > > to have to do with keep-alives and if the client takes longer to read > > > > the message than the keep alive value. > > > > > > > > > > Hi Mark > > > > > > Then, it is all very simple. There are several ways to make HttpClient > > > either discard potentially half-closed connections, test them for > > > 'staleness' or automatically recover from NoHttpResponseException. > > > > > > > > > > In my test case I open the connection, read all the data, sleep for a > > > > while, then close the connection. > > > > If my sleep is a bit longer than the keep-alive value, I will get a > > > > org.apache.http.NoHttpResponseException. If my sleep value is larger, > > > > I will get a java.net.SocketException. > > > > (Keep-Alive is 5000 millis. If I sleep for 6000, I will get a > > > > NoHttpResponseException. If I sleep for 11000, I will get a > > > > SocketException. > > > > > > > > > > The default maximum inactivity period used by the pooling connection > > > manager is exactly 5000 ms. Please try reducing this value to, say, > > > 2000 ms > > > > > > --- > > > PoolingHttpClientConnectionManager cm = new > > > PoolingHttpClientConnectionManager(); > > > cm.setValidateAfterInactivity(2000); > > > > > > CloseableHttpClient client = HttpClients.custom() > > > .setConnectionManager(cm) > > > .build(); > > > --- > > > > > > This should make the problem go away. > > > > > > > If I use the NoConnectionReuseStrategy, the problem goes away. > > > > > > > > Is something set up for my keep alives? I put some breakpoints in > > > > CPool.java. I can see connections being created, but the validate() > > > > method of CPool is never getting called. > > > > > > > > I am curious this part of AbstractConnPool.java. This seems like if > > > > the server invalidated a connection early, the validate check would > > > > never happen. > > > > > > > > } else if (this.validateAfterInactivity > 0) { > > > > if (entry.getUpdated() + > > > > this.validateAfterInactivity <= System.currentTimeMillis()) { > > > > if (!validate(entry)) { > > > > entry.close(); > > > > } > > > > } > > > > } > > > > Scenario: > > > > Server sends data. > > > > Client reads packet, processes it for 6 seconds > > > > Server senses that inactivity for 5 seconds, closes connection > > > > Client closes connection and places entry back in the pool > > > > Connection immediately leased to another thread > > > > Time between release and close is almost nothing > > > > Pool releases stale connection. > > > > > > > > > > You can force TTL (total time to live) for connections to avoid this > > > problem > > > > > > --- > > > PoolingHttpClientConnectionManager cm = new > > > PoolingHttpClientConnectionManager(3000, TimeUnit.MILLISECONDS); > > > cm.setValidateAfterInactivity(1000); > > > > > > CloseableHttpClient client = HttpClients.custom() > > > .setConnectionManager(cm) > > > .build(); > > > --- > > > > > > Hope this helps > > > > > > Oleg > > > > > > > > > -------------------------------------------------------------------- > > > - To unsubscribe, e-mail: [email protected] > > > For additional commands, e-mail: [email protected] > > > > > > > > > -------------------------------------------------------------------- > > > - To unsubscribe, e-mail: [email protected] > > > For additional commands, e-mail: [email protected] > > > > > > > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [email protected] > > For additional commands, e-mail: [email protected] > > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [email protected] > > For additional commands, e-mail: [email protected] > > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
