-
-
Notifications
You must be signed in to change notification settings - Fork 131
Connections & Pooling
The C# driver supports two types of connections.
- A single connection to a RethinkDB server.
- A set of pooled connections to a RethinkDB cluster.
The advantage of connection pooling is two fold: redundancy and load balancing. When a connection to a node is interrupted, subsequent queries are routed to different nodes in the cluster. Additionally, different pooling strategies can be used to distribute workloads among nodes in a cluster.
While connection pools offer redundancy and load balancing, the driver will not retry a failed query. A failed query can occur when a node goes down:
- Incident threads waiting to write a query to the network stream of a down node will fail. An exception is thrown.
- Threads awaiting responses from a down node will be notified via exception (faulted task). This applies to cursors and change feeds.
In each failure case, when a node goes down, the (incident and awaiting) callers associated with the failed node are notified via exception that a failure has occurred. It is the responsibility of the developer to retry a query if needed. The connection pool should detect these failures immediately. However, as a best practice, when a faulted query occurs, please wait at least 1.5 seconds before retrying the query. This ensures a higher probability of success on the next retry and allows time for the supervisor to mark other dead nodes. When a node is marked dead, the dead node will be skipped from selection until the connection can be re-established. In the case when all nodes are down, every query will fail.
Tip: Polly is a helpful .NET utility can help write Circuit Breaker and Wait/Retry code.
Each .connect() method has an associated .connectAsync() for asynchronous establishment of a connection.
To create one connection to a RethinkDB server (without connection pooling):
var conn = r.connection()
.hostname(AppSettings.TestHost)
.port(AppSettings.TestPort)
.timeout(60)
.connect();
int result = r.now().run<DateTimeOffset>(conn);
The connection can be shared by multiple threads. The returned connection is ready to be used.
Note: Currently, the Java driver does not support connection pooling. The following APIs are subject to change.
To create a connection pool using a round-robin node selection strategy:
var conn = r.connectionPool()
.seed(new[] {"192.168.0.11:28015", "192.168.0.12:28015"})
.poolingStrategy(new RoundRobinHostPool())
.discover(true)
.connect();
int result = r.now().run<DateTimeOffset>(conn);
The connection can be used by multiple threads. The .connect() method returns when at least one connection to a node has been successfully established.
The .seed() method seeds the driver with IP addresses well-known cluster nodes. If .discover(true), the driver attempts to discover new hosts when they are added to the RethinkDB cluster. The driver does this by setting up a change feed on a system table and listens for changes. Additionally, pre-existing nodes (not originally part of the seed list), will be discovered.
The .poolingStrategy(new RoundRobinHostPool()) provides a round-robin node selection strategy.
There are two construction arguments for RoundRobinHostPool that control reconnection intervals. Initially, when a host goes down the pool supervisor will wait a time span of retryDelayInitial before reconnecting to the node. If the reconnect fails, the retry delay is doubled. Doubling of the retry delay reaches a maximum when the retry delay is greater than retryDelayMax; thereafter, every subsequent retry is retryDelayMax.
-
retryDelayInitial- The initial retry delay when a host goes down. How long to wait before immediately retrying the connection. Default is 30 seconds. -
retryDelayMax- The maximum retry delay. Default is 15 minutes.
Another connection pooling strategy is Epsilon Greedy. Epsilon Greedy is an algorithm that allows the pool to not only to track failure state, but also to learn about "better" options in terms of speed, and to pick from available hosts based on how well they perform. This gives a weighted request rate to better performing hosts, while still distributing requests to all hosts (proportionate to their performance).
A good overview of Epsilon Greedy is here http://stevehanov.ca/blog/index.php?id=132
To setup an epsilon greedy host pool:
var conn = r.connectionPool()
.seed(new[] { "192.168.0.11:28015" })
.poolingStrategy(
new EpsilonGreedyHostPool(decayDuration, EpsilonCalculator.Linear())
)
.discover(true)
.connect();
-
decayDuration- The amount of time to cycle through allEpsilonBuckets(0...120). This decay duration is divided byEpsilonBuckets(default: 5 min / 120 buckets = 2.5 seconds per bucket). IE: The average will be taken everydecayDuration/EpsilonBucketsseconds. To use the defaultdecayDurationpass null for this argument. -
EpsilonCalculator- Given the weighted average amongEpsilonBucketsslot measurements, calculate the host'sEpsilonValueusingEpsilonCalculator.Linear/Logarithmic/Polynomial(exponent).
- Home
- Query Examples
- Logging
- Connections & Pooling
- Extra C# Features
- GOTCHA Goblins!
- LINQ to ReQL Provider
- Differences
- Java ReQL API Documentation