Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relax connection termination policy in routing driver #424

Merged
merged 7 commits into from
Nov 13, 2017

Conversation

lutovich
Copy link
Contributor

@lutovich lutovich commented Oct 26, 2017

Previously routing driver terminated all connections towards a particular address when one of active connections had a network error. Connections were also terminated when new routing table did not contain some address that was present in the previous routing table. Such behaviour might be problematic because it results in terminated queries. Network errors might have been temporary but always resulted in termination of active queries.

This commit makes driver keep existing connections and terminate only idle ones on network error. Address will still be excluded from the routing table and subsequent queries will not be pointed on it. Corresponding connection pool is transferred into a "passive" state where it does not serve new connections and disposes returned connections immediately. Pool is transferred back to "active" state during next rediscovery only if corresponding address is present in the new routing table.

Old behaviour still remains and can be activated using -DpurgeOnError=true system property. It exists as a fallback only for exceptional cases and will most likely be silently removed in future.

Previously routing driver terminated all connections towards a particular
address when one of active connections had a network error. Connections
were also terminated when new routing table did not contain some address
that was present in the previous routing table. Such behaviour might be
problematic because it results in terminated queries. Network errors
might have been temporary but always resulted in termination of active
queries.

This commit makes driver keep existing connections and terminate only
idle ones on network error. Address will still be excluded from the
routing table and subsequent queries will not be pointed on it.
Corresponding connection pool is transferred into a "passive" state where
it does not serve new connections and disposes returned connections
immediately. Pool is transferred back to "active" state during next
rediscovery only if corresponding address is present in the new
routing table.

Old behaviour still remains and can be activated using
`-DpurgeOnError=true` system property. It exists as a fallback only for
exceptional cases and will most likely be silently removed in future.
* `ConnectionPools` which is a map from addresses to connection pools
* `RoutingTable` which contains addresses for routers, writers, and readers

For a routing driver, once an address is removed from the current `RoutingTable`, the address is no longer accessable. a.k.a. no new connection will be created in the corresponding connection pool.

When updating routing table, we also need to signal the addresses in `ConnectionPools` to be active if they are newly added into the current routing table or passive if they have already been removed from the routing table. For the pools connected to addresses that have been removed, when a connection is free, the connection should be terminated rather than reused. When there is no connection in the pool, the pool could be safely removed from `ConnectionPools`.

So the logic that need to be changed:
* When a new `RoutingTable` is available, compute
`added_addr = distinct_addr_in(new_routingTable) - distinct_addr_in(pre_routingTable)`
`removed_addr = distinct_addr_in(pre_routingTable) - distinct_addr_in(new_routingTable)`
* Mark all addresses in set `added_addr` in `ConnectionPools` to be `active` connection pools
* Mark all addresses in set `removed_addr` in `ConnectionPools` to be `passive` connection pools
* Remove `passive` connection pools if no connection is `inUse` (all connections are idle)
* When returning a connection to a `passive` connection pool, terminate the connection directly, [and remove the connection pool if no connections is `InUse`]
Copy link
Contributor

@zhenlineo zhenlineo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got you this PR lutovich#1 to simplify some logic

{
expirationTimeout = cluster.expirationTimestamp();
// todo: what if server is added as reader and removed as writer? we should not treat it as removed
Copy link
Contributor

@zhenlineo zhenlineo Nov 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To answer your todo, there is no need to know if the status of an address in RoutingTable, we only care about the whole distinct addresses in the RoutingTable. The ConnectionPools only need to know if an address is active (can reuse connections) or passive (can be terminated once no inUse connections in the pool)

See more explanation in lutovich#1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

Simplify the logic of compute added and removed addresses in routing table
That tried to count inserted nodes in the cluster using
read transaction and no bookmarks.
Use transaction function to write and receive bookmark. Previously
`Session#run()` was used and it does not produce a bookmark.
@lutovich lutovich merged commit 8cc7b03 into neo4j:1.4 Nov 13, 2017
@lutovich lutovich deleted the 1.4-no-purge branch November 13, 2017 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants