|
| 1 | +## Socket options |
| 2 | + |
| 3 | +[SocketOptions] controls various low-level parameters related to TCP connections between the driver and Cassandra. |
| 4 | + |
| 5 | +You can provide these when initializing the cluster: |
| 6 | + |
| 7 | +```java |
| 8 | +Cluster cluster = Cluster.builder() |
| 9 | + .addContactPoint("127.0.0.1") |
| 10 | + .withSocketOptions( |
| 11 | + new SocketOptions() |
| 12 | + .setConnectTimeoutMillis(2000)) |
| 13 | + .build(); |
| 14 | +``` |
| 15 | + |
| 16 | +If you don't, the driver uses a default configuration (see the javadocs of the setter methods of [SocketOptions] for the |
| 17 | +default values). |
| 18 | + |
| 19 | +You can retrieve and change the options at runtime: |
| 20 | + |
| 21 | +```java |
| 22 | +SocketOptions socketOptions = cluster.getConfiguration().getSocketOptions(); |
| 23 | +socketOptions.setConnectTimeoutMillis(3000); |
| 24 | +``` |
| 25 | + |
| 26 | +* changes to the [read timeout](#driver-read-timeout) will be taken into account for future request executions; |
| 27 | +* changes to any other option will be taken into account for future connections (connections that were already opened at |
| 28 | + the time of the change are unaffected, they keep the old values). |
| 29 | + |
| 30 | +### TCP options |
| 31 | + |
| 32 | +[setConnectTimeoutMillis] defines how long the driver waits to establish a new connection to a Cassandra node before |
| 33 | +giving up. |
| 34 | + |
| 35 | +Other options control the usual low-level TCP parameters (refer to their individual javadoc for details): |
| 36 | +[setKeepAlive], [setReceiveBufferSize], [setReuseAddress], [setSendBufferSize], [setSoLinger], [setTcpNoDelay]. Most of |
| 37 | +these options are not set explicitly by the driver, so they get the default value from the underlying TCP transport. |
| 38 | +One exception is `setTcpNoDelay`, which is forced to `true` (meaning that Nagle's algorithm is *disabled* for driver |
| 39 | +connections). |
| 40 | + |
| 41 | +### Driver read timeout |
| 42 | + |
| 43 | +[setReadTimeoutMillis] controls how long the driver waits for a response *from a given Cassandra node* before |
| 44 | +considering it unresponsive. |
| 45 | + |
| 46 | +Cassandra normally provides a guaranteed response time for each type of query, as shown by these parameters in |
| 47 | +`cassandra.yaml` (here with their default values): |
| 48 | + |
| 49 | +```yaml |
| 50 | +counter_write_request_timeout_in_ms: 5000 |
| 51 | +range_request_timeout_in_ms: 10000 |
| 52 | +read_request_timeout_in_ms: 5000 |
| 53 | +request_timeout_in_ms: 10000 |
| 54 | +truncate_request_timeout_in_ms: 60000 |
| 55 | +write_request_timeout_in_ms: 2000 |
| 56 | +``` |
| 57 | +
|
| 58 | +The goal of `setReadTimeoutMillis` is to give up on a node if it took longer than these thresholds to reply, on the |
| 59 | +assumption that there's probably something wrong with it. Therefore it should be set **higher than the server-side |
| 60 | +timeouts**. The default value is **12 seconds** (lower than `truncate_request_timeout_in_ms`, but we consider `TRUNCATE` |
| 61 | +queries as maintenance operations that shouldn't be run from your application). Do not set it too low, or the driver |
| 62 | +might give up on requests that had a chance of succeeding. |
| 63 | + |
| 64 | +If the timeout is reached, the driver will receive an `OperationTimedOutException` and retry the query on the next node |
| 65 | +in the [query plan](../load_balancing/#query-plan). |
| 66 | + |
| 67 | +#### Limiting overall query time |
| 68 | + |
| 69 | +It should be clear by now that `setReadTimeoutMillis` is *per node*, not per query. If the driver retries on 4 different |
| 70 | +nodes, the overall execution time could theoretically be up to 4 times the read timeout. If you want a per query timeout, |
| 71 | +use the following pattern: |
| 72 | + |
| 73 | +```java |
| 74 | +import com.google.common.base.Throwables; |
| 75 | +
|
| 76 | +ResultSet execute(Statement statement, long timeout, TimeUnit unit) |
| 77 | + throws InterruptedException, TimeoutException { |
| 78 | + ResultSetFuture future = session.executeAsync(statement); |
| 79 | + try { |
| 80 | + return future.get(timeout, unit); |
| 81 | + } catch (ExecutionException e) { |
| 82 | + throw Throwables.propagate(e.getCause()); |
| 83 | + } catch (TimeoutException e) { |
| 84 | + future.cancel(true); |
| 85 | + throw e; |
| 86 | + } |
| 87 | +} |
| 88 | +``` |
| 89 | + |
| 90 | +A complementary approach is to enable [speculative executions](../speculative_execution/), to have the driver query |
| 91 | +multiple nodes in parallel. This way you won't have to wait for the full timeout if the first node is unresponsive. |
| 92 | + |
| 93 | +#### Driver read timeout vs. server read timeout |
| 94 | + |
| 95 | +Unfortunately, the term "read timeout" clashes with another concept that is not directly related: a Cassandra node may |
| 96 | +reply with a `Read_timeout` error when it didn't hear back from enough replicas during a read query. |
| 97 | + |
| 98 | +To clarify: |
| 99 | + |
| 100 | +* **driver read timeout:** the driver did not receive any response from the current coordinator within |
| 101 | + `SocketOptions.setReadTimeoutMillis`. It retries the query on the next node. |
| 102 | +* **server read timeout:** the driver *did* receive a response, but that response indicates that the coordinator timed |
| 103 | + out while waiting for other replicas. It invokes [onReadTimeout] on the [retry policy](../retries/) to decide what to |
| 104 | + do. |
| 105 | + |
| 106 | +We might rename `SocketOptions.setReadTimeoutMillis` in a future version to clear up any confusion. |
| 107 | + |
| 108 | +[SocketOptions]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html |
| 109 | +[setReadTimeoutMillis]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setReadTimeoutMillis-int- |
| 110 | +[setConnectTimeoutMillis]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setConnectTimeoutMillis-int- |
| 111 | +[setKeepAlive]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setKeepAlive-boolean- |
| 112 | +[setReceiveBufferSize]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setReceiveBufferSize-int- |
| 113 | +[setReuseAddress]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setReuseAddress-boolean- |
| 114 | +[setSendBufferSize]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setSendBufferSize-int- |
| 115 | +[setSoLinger]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setSoLinger-int- |
| 116 | +[setTcpNoDelay]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setTcpNoDelay-boolean- |
| 117 | +[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- |
0 commit comments