apache http client: connection timeout for "no route to host" case - java

I have a problem with apache http client (4.2.1) connection timeouts, if host exists but does not respond in time, the connection is closed by timeout (everything is as expected), but if there is no such host, the client keeps waiting longer than expected (about 12 seconds instead of 5 specified in configuration). Eventually this results in NoRouteToHostException, probably because of the specific network issues (when I was trying to reproduce this in another network, I've got socket read timeout exception after 5 sec of waiting, as expected).
I'm using the following timeout settings:
http.socket.timeout = 5 sec
http.connection.timeout = 5 sec
Any thoughts are appreciated.
Update
If someone ever has the same issue, it is probably caused by the connection retries, performed by the client. I'll update this post when I solve the problem
Update2
Eventually I've been able to fix the issue. The problem was caused by the connection retries performed by DefaultHttpRequestRetryHandler, used by AbstractHttpClient (that is the parent of DefaultHttpClient), if there is no request retry handler specified explicitly. So, if you want to get rid of it, just specify the request retry handler with smaller number of retries

Eventually I've been able to fix the issue. The problem was caused by the connection retries performed by DefaultHttpRequestRetryHandler, used by AbstractHttpClient (that is the parent of DefaultHttpClient), if there is no request retry handler specified explicitly. So, if you want to get rid of it, just specify the request retry handler with smaller number of retries

Related

okHttp client gives timeout after adding callTimeout() config to it and has moments where the request doesn't reach the host

after adding callTimeout() config to the okhttp client I started to get timeouts
Caused by: java.io.InterruptedIOException: timeout
Caused by: java.io.IOException: Canceled
OkHttpClient httpClient = new OkHttpClient.Builder()
.callTimeout(5_000L, TimeUnit.MILLISECONDS)
.connectTimeout(500L, TimeUnit.MILLISECONDS)
.readTimeout(5_000L, TimeUnit.MILLISECONDS)
.writeTimeout(5_000L, TimeUnit.MILLISECONDS)
.build();
I'm not completely sure if having callTimeout configured with the same value as write and read is correct.Is it possible if read and write takes longer to trigger callTimeout()?
Also another weird thing is that there are moments in which the request doesn't even reach the host
As after adding the configurations, you are getting this exception, I am suspecting, the requested endpoint needs more time than your configured 5 seconds.
If your requested endpoint is taking more than 5 seconds (5_000 milliseconds) to get a response, you will get a timeout here with this config.
You can use postman to get the response time of your requested endpoint. If it is more than 5 seconds, you can simply configure these values accordingly. Maybe, you can use 30 seconds, instead of 5 Seconds.
I Hope, it helps.
callTimeOut()
Sets the default timeout for complete calls. A value of 0 means no
timeout, otherwise values must be between 1 and [Integer.MAX_VALUE]
when converted to milliseconds. The call timeout spans the entire
call: resolving DNS, connecting, writing the request body, server
processing, and reading the response body. If the call requires
redirects or retries all must complete within one timeout period. The
default value is 0 which imposes no timeout.
Correct me if I'm wrong. from what I understand callTimeOut() set call timeout spans for the entire call. Eg: you set callTimeOut = 5s. if resolving DNS takes 1s, connecting 1s, write 2s, read 2s then you will get TimeOut exception. by default, callTimeOut() is set to no timeout while another default Timeouts is 10s. why do you have to set callTimeOut() to 5s? for me, I have never set callTimeOut before.

javax.websocket - timeout for delivering message

I'm using javax.websocket API in my app. I send messages from server to client like this:
Future<Void> messageFuture = session.getAsyncRemote().sendText(message);
messageFutures.add(messageFuture); // List<Future<Void>> messageFutures
I use async API because I really care about performance and cannot make server wait until each message is delivered, because server does smth like this:
for (i = 1..N) {
result = doStuff()
sendMessage(result)
}
So it is impossible to wait for message delivery each iteration.
After I send all the messages I need to wait for all the Future's to be finished (all messages are delivered). And to be safe I need to use some timeout like "if server sends message to client and client doesn't confirm receipt in 30 seconds then consider websocket connection broken" - as far as I understand it should be possible to do with websockets since they work over TCP.
There is a method session.setMaxIdleTimeout(long):
Set the non-zero number of milliseconds before this session will be
closed by the container if it is inactive, ie no messages are either
sent or received. A value that is 0 or negative indicates the session
will never timeout due to inactivity.
but I really not sure if it is what I want (is it?). So how can I set a timeout like I described using javax.websocket API?
The idle timeout could cover your case, but it is not designed to. The idle timeout applies more to the case where a client makes a connection, but is using it only infrequently.
The more precise feature for checking a timeout when sending is setAsyncSendTimeout.
Using both of these allows you to configure for the case where a client may leave a connection idle for minutes at a time, but the server expects relatively quick messages acknowledgements.
In my experience with Spring, the timeout implementation provided by Spring is not actually configurable. See How do you quickly close a nonresponsive websocket in Java Spring Tomcat? I am not sure whether this is applicable to your websocket implementation.

MQ Connection - 2009 Connection broken error on active channel

I'm upgrading our application to MQ7 (7.5.0.5) and I'm seeing some odd behavior in a small test application that I have written.
My application uses Springs CachingConnectionFactory and is configured to use only one thread.
I can see that by debugging through the code 2 tcp connections are created, one for the initial connection and one for the JMS session. Every 60 seconds, the 2 tcp connections that are used by my message sink are broken and replaced with 2 new connections.
The following error is present in the error logs on the queue manager.
05/16/2016 09:38:26 AM - Process(1609.14) User(mqm) Program(amqrmppa)
Host(xxxxxxxxx) Installation(Installation1)
VRMF(7.5.0.2) QMgr(xxxxx)
AMQ9271: Channel 'XX.XXXX.X' timed out.
EXPLANATION:
A timeout occurred while waiting to receive from the other end of channel
'XX.XXX.X'. The address of the remote end of the connection was '57.4.4.145'.
ACTION:
The return code from the (recv) [TIMEOUT] 60 seconds call was 0 (X'0').
Record these values and tell the systems administrator.
I have the following settings on my channel: DISCINT(60), SHARECNV(1), the exceptions are linked to the DISCINT time, changing that changes the frequency of the exceptions, also the
exceptions disappear with a SHARECNV value >1
Can anyone tell my why the connections are broken even when the channel is active and messages are being sent and received?
Thanks!
This sounds like APAR IV62728 which describes the symptoms you're seeing:
http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg1IV62728
Fixed in 7.5.0.6. Try upgrading to that level and see if it solves the problem.
I managed to find a solution to this issue. When using the CachingConnectionFactory with an underlying IBM connection factory, an initial connection is created in a stopped state. That connection in then used to create JMSSessions.
The issue was that the initial common connection was timing out.
I managed to keep the connection active by adjusting the HBINT value to 5. It appears that a number of heatbeats are required to keep the connection open and my initial value of 20 was too high.

Cassandra - Set write timeout with Java API

I am trying to set the write timeout in Cassandra with the Java drive. SocketOptions allows me to set a read and connect timeout but not a write timeout.
Does anyone knows the way to do this without changing the cassandra.yaml?
thanks
Altober
The name is misleading, but SocketOptions.getReadTimeoutMillis() applies to all requests from the driver to cassandra. You can think of it as a client-level timeout. If a response hasn't been returned by a cassandra node in that period of time an OperationTimeoutException will be raised and another node will be tried. Refer to the javadoc link above for more nuanced information about when the exception is raised to the client. Generally, you will want this timeout to be greater than your timeouts in cassandra.yaml, which is why 12 seconds is the default.
If you want to effectively manage timeouts at the client level, you can control this on a per query basis by using executeAsync along with a timed get on the ResultSetFuture to give up on the request after a period of time, i.e.:
ResultSet result = session.executeAsync("your query").get(300, TimeUnit.MILLISECONDS);
This will throw a TimeoutException if the request hasn't been completed in 300 ms.

Camel JMS Proxy Timeout occurred after 20000 millis waiting for reply message

I am using a Camel Proxy which returns a result from another process.
public interface DataProcessingInterface {
public List<ResponseData> processPreview(ClientData criteria, Config config);
}
And this is configured link this
<camel:proxy
id="processPreviewProxy"
serviceInterface="model.jms.DataProcessingInterface"
serviceUrl="jms:queue:processPreview"/>
But sometimes the other process takes a long time to return the results and I am having getting the timeout exception
TemporaryQueueReplyManager - Timeout occurred after 20000 millis waiting for reply message with correlationID [Camel-ID-PC01-2661-1367403764103-0-15]. Setting ExchangeTimedOutException on (MessageId: ID-PC01-2661-1367403764103-0-17 on ExchangeId: ID-PC01-2661-1367403764103-0-16) and continue routing.
How do I tell Camel to wait till the response is ready. It should take forever if that is how long it takes. The client is managed in a different thread so it the duration it takes will not affect the client.
Also is it possible to re-establish the connection if the TimeoutException is thrown so I can continue to wait?
"Forever"? No. You can't wait forever.
A (synchronous) request/reply typically have a time out value set by a reason. If you don't get a reply within a given time, then try again or skip it. In the JMS case, you set both requestTimeout and timeToLive to achieve this. Read this section. In Camel, you can achieve such things with redelivery and error handlers.
Anyway, if you would set the value to "Forever" (or at least very long, such as multiple hours) - then a server/application restart would still make the request fail.
You can set a very high request timeout on the jms endpoint.
jms:queue:processPreview?requestTimeout=xxxx

Categories

Resources