blob: c31e04b0938e33ea1d0d62af8901f1911c429603 [file] [log] [blame] [view]
## Socket options
[SocketOptions] controls various low-level parameters related to TCP connections between the driver and Cassandra.
You can provide these when initializing the cluster:
```java
Cluster cluster = Cluster.builder()
.addContactPoint("127.0.0.1")
.withSocketOptions(
new SocketOptions()
.setConnectTimeoutMillis(2000))
.build();
```
If you don't, the driver uses a default configuration (see the javadocs of the setter methods of [SocketOptions] for the
default values).
You can retrieve and change the options at runtime:
```java
SocketOptions socketOptions = cluster.getConfiguration().getSocketOptions();
socketOptions.setConnectTimeoutMillis(3000);
```
* changes to the [read timeout](#driver-read-timeout) will be taken into account for future request executions;
* changes to any other option will be taken into account for future connections (connections that were already opened at
the time of the change are unaffected, they keep the old values).
### TCP options
[setConnectTimeoutMillis] defines how long the driver waits to establish a new connection to a Cassandra node before
giving up.
Other options control the usual low-level TCP parameters (refer to their individual javadoc for details):
[setKeepAlive], [setReceiveBufferSize], [setReuseAddress], [setSendBufferSize], [setSoLinger], [setTcpNoDelay]. Most of
these options are not set explicitly by the driver, so they get the default value from the underlying TCP transport.
One exception is `setTcpNoDelay`, which is forced to `true` (meaning that Nagle's algorithm is *disabled* for driver
connections).
### Driver read timeout
[setReadTimeoutMillis] controls how long the driver waits for a response *from a given Cassandra node* before
considering it unresponsive.
Cassandra normally provides a guaranteed response time for each type of query, as shown by these parameters in
`cassandra.yaml` (here with their default values):
```yaml
counter_write_request_timeout_in_ms: 5000
range_request_timeout_in_ms: 10000
read_request_timeout_in_ms: 5000
request_timeout_in_ms: 10000
truncate_request_timeout_in_ms: 60000
write_request_timeout_in_ms: 2000
```
The goal of `setReadTimeoutMillis` is to give up on a node if it took longer than these thresholds to reply, on the
assumption that there's probably something wrong with it. Therefore it should be set **higher than the server-side
timeouts**. The default value is **12 seconds** (lower than `truncate_request_timeout_in_ms`, but we consider `TRUNCATE`
queries as maintenance operations that shouldn't be run from your application). Do not set it too low, or the driver
might give up on requests that had a chance of succeeding.
If the timeout is reached, the driver will receive an `OperationTimedOutException` and retry the query on the next node
in the [query plan](../load_balancing/#query-plan).
#### Limiting overall query time
It should be clear by now that `setReadTimeoutMillis` is *per node*, not per query. If the driver retries on 4 different
nodes, the overall execution time could theoretically be up to 4 times the read timeout. If you want a per query timeout,
use the following pattern:
```java
import com.google.common.base.Throwables;
ResultSet execute(Statement statement, long timeout, TimeUnit unit)
throws InterruptedException, TimeoutException {
ResultSetFuture future = session.executeAsync(statement);
try {
return future.get(timeout, unit);
} catch (ExecutionException e) {
throw Throwables.propagate(e.getCause());
} catch (TimeoutException e) {
future.cancel(true);
throw e;
}
}
```
A complementary approach is to enable [speculative executions](../speculative_execution/), to have the driver query
multiple nodes in parallel. This way you won't have to wait for the full timeout if the first node is unresponsive.
#### Driver read timeout vs. server read timeout
Unfortunately, the term "read timeout" clashes with another concept that is not directly related: a Cassandra node may
reply with a [READ_TIMEOUT](../retries/#on-read-timeout) error when it didn't hear back from enough replicas during a
read query.
To clarify:
* **driver read timeout:** the driver did not receive any response from the current coordinator within
`SocketOptions.setReadTimeoutMillis`. It retries the query on the next node.
* **server read timeout:** the driver *did* receive a response, but that response indicates that the coordinator timed
out while waiting for other replicas. It invokes [onReadTimeout] on the [retry policy](../retries/) to decide what to
do.
We might rename `SocketOptions.setReadTimeoutMillis` in a future version to clear up any confusion.
[SocketOptions]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html
[setReadTimeoutMillis]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setReadTimeoutMillis-int-
[setConnectTimeoutMillis]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setConnectTimeoutMillis-int-
[setKeepAlive]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setKeepAlive-boolean-
[setReceiveBufferSize]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setReceiveBufferSize-int-
[setReuseAddress]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setReuseAddress-boolean-
[setSendBufferSize]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setSendBufferSize-int-
[setSoLinger]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setSoLinger-int-
[setTcpNoDelay]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setTcpNoDelay-boolean-
[onReadTimeout]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/policies/RetryPolicy.html#onReadTimeout-com.datastax.driver.core.Statement-com.datastax.driver.core.ConsistencyLevel-int-int-boolean-int-