diff --git a/dotnet-manual/modules/ROOT/pages/connect.adoc b/dotnet-manual/modules/ROOT/pages/connect.adoc index 92eff5c7..99743dcf 100644 --- a/dotnet-manual/modules/ROOT/pages/connect.adoc +++ b/dotnet-manual/modules/ROOT/pages/connect.adoc @@ -72,6 +72,54 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, csharp, test-skip] +---- +using Neo4j.Driver; + +const string dbUser = ""; +const string dbPassword = ""; + +var addresses = new ListAddressResolver( + ServerAddress.From("server01.example.com", 7687), + ServerAddress.From("server02.example.com", 7687), + ServerAddress.From("server03.example.com", 7687), + ServerAddress.From("backup.example.org", 7687) +); + +await using var driver = GraphDatabase.Driver( + "neo4j://example.com:7687", + AuthTokens.Basic(dbUser, dbPassword), + conf => conf.WithResolver(addresses) +); +await driver.VerifyConnectivityAsync(); + +class ListAddressResolver : IServerAddressResolver { + private readonly ServerAddress[] _servers; + + public ListAddressResolver(params ServerAddress[] servers) { + _servers = servers; + } + + public ISet Resolve(ServerAddress address) { + return new HashSet(_servers); + } +} +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + + == Close connections Always close `IDriver` objects to free up all allocated resources, even upon unsuccessful connection or runtime errors. diff --git a/go-manual/modules/ROOT/pages/connect-advanced.adoc b/go-manual/modules/ROOT/pages/connect-advanced.adoc index 2e30440e..fe5e500b 100644 --- a/go-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/go-manual/modules/ROOT/pages/connect-advanced.adoc @@ -177,12 +177,16 @@ if err != nil { For more information, see link:https://pkg.go.dev/github.com/neo4j/neo4j-go-driver/v6/neo4j/auth#ClientCertificateProvider[API docs -> `ClientCertificateProvider`]. +[#custom-address-resolver] == Custom address resolver When creating a `Driver` object, you can specify a _resolver_ function to resolve the connection address the driver is initialized with. -Note that addresses that the driver receives in routing tables are not resolved with the custom resolver. +Note that addresses that the driver receives in routing tables are not resolved with the custom resolver: the custom resolver is only used for the initial connection. Your resolver function is called with a link:https://pkg.go.dev/github.com/neo4j/neo4j-go-driver/v6/neo4j/config#ServerAddress[`ServerAddress`] object and should return a list of link:https://pkg.go.dev/github.com/neo4j/neo4j-go-driver/v6/neo4j/config#ServerAddress[`ServerAddress`] objects. +[NOTE] +A custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). + .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, go] ---- diff --git a/go-manual/modules/ROOT/pages/connect.adoc b/go-manual/modules/ROOT/pages/connect.adoc index 34620d2c..486e23d3 100644 --- a/go-manual/modules/ROOT/pages/connect.adoc +++ b/go-manual/modules/ROOT/pages/connect.adoc @@ -104,6 +104,41 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, go] +---- +// import "github.com/neo4j/neo4j-go-driver/v6/neo4j/config" + +addresses := []config.ServerAddress{ + neo4j.NewServerAddress("server01.example.com", "7687"), + neo4j.NewServerAddress("server02.example.com", "7687"), + neo4j.NewServerAddress("server03.example.com", "7687"), + neo4j.NewServerAddress("backup.example.org", "7687"), +} + +driver, err := neo4j.NewDriver( + "neo4j://example.com:7687", neo4j.BasicAuth(dbUser, dbPassword, ""), + func(conf *config.Config) { + conf.AddressResolver = func(address config.ServerAddress) []config.ServerAddress { + return addresses + } +}) +defer driver.Close(ctx) +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + + == Further connection parameters For more `Driver` configuration parameters and further connection settings, see xref:connect-advanced.adoc[Advanced connection information]. diff --git a/java-manual/modules/ROOT/pages/connect-advanced.adoc b/java-manual/modules/ROOT/pages/connect-advanced.adoc index f8018ac9..adf5b036 100644 --- a/java-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/java-manual/modules/ROOT/pages/connect-advanced.adoc @@ -287,13 +287,17 @@ java.util.logging.ConsoleHandler.level = FINE ---- +[#custom-address-resolver] == Custom address resolver When creating a `Driver` object, you can specify a _resolver_ function to resolve the connection address the driver is initialized with. -Note that addresses that the driver receives in routing tables are not resolved with the custom resolver. +Note that addresses that the driver receives in routing tables are not resolved with the custom resolver: the custom resolver is only used for the initial connection. You specify a resolver through the link:https://neo4j.com/docs/api/java-driver/current/org.neo4j.driver/org/neo4j/driver/Config.ConfigBuilder.html#withResolver(org.neo4j.driver.net.ServerAddressResolver)[`.withResolver()`] config method, which works with link:https://neo4j.com/docs/api/java-driver/current/org.neo4j.driver/org/neo4j/driver/net/ServerAddress.html[`ServerAddress`] objects. +[NOTE] +A custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). + .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, java] ---- diff --git a/java-manual/modules/ROOT/pages/connect.adoc b/java-manual/modules/ROOT/pages/connect.adoc index 0e49d00c..1556b6fe 100644 --- a/java-manual/modules/ROOT/pages/connect.adoc +++ b/java-manual/modules/ROOT/pages/connect.adoc @@ -90,6 +90,45 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, java, test-skip] +---- +// import java.util.Set; +// import org.neo4j.driver.AuthTokens; +// import org.neo4j.driver.Config; +// import org.neo4j.driver.GraphDatabase; +// import org.neo4j.driver.net.ServerAddress; + +var addresses = Set.of( + ServerAddress.of("server01.example.com", 7687), + ServerAddress.of("server02.example.com", 7687), + ServerAddress.of("server03.example.com", 7687), + ServerAddress.of("backup.example.org", 7687) +); +var config = Config.builder() + .withResolver(address -> addresses) + .build(); +try (var driver = GraphDatabase.driver( + "neo4j://example.com:7687", + AuthTokens.basic(dbUser, dbPassword), + config)) { + driver.verifyConnectivity(); +} +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + + == Close connections Always close `Driver` objects to free up all allocated resources, even upon unsuccessful connection or runtime errors. diff --git a/javascript-manual/modules/ROOT/pages/connect-advanced.adoc b/javascript-manual/modules/ROOT/pages/connect-advanced.adoc index 19641279..5d201492 100644 --- a/javascript-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/javascript-manual/modules/ROOT/pages/connect-advanced.adoc @@ -184,10 +184,14 @@ clientCertificateProvider.updateCertificate({ ===== +[#custom-address-resolver] == Custom address resolver When creating a `Driver` object, you can specify a _resolver_ function to resolve the connection address the driver is initialized with. -Note that addresses that the driver receives in routing tables are not resolved with the custom resolver. +Note that addresses that the driver receives in routing tables are not resolved with the custom resolver: the custom resolver is only used for the initial connection. + +[NOTE] +A custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, javascript] diff --git a/javascript-manual/modules/ROOT/pages/connect.adoc b/javascript-manual/modules/ROOT/pages/connect.adoc index 9e11988a..7ea631b4 100644 --- a/javascript-manual/modules/ROOT/pages/connect.adoc +++ b/javascript-manual/modules/ROOT/pages/connect.adoc @@ -93,6 +93,34 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, javascript] +---- +let URI = 'neo4j://example.com:7687' +let addresses = [ + 'server01.example.com:7687', + 'server02.example.com:7687', + 'server03.example.com:7687', + 'backup.example.org:7687' +] +let driver = neo4j.driver(URI, neo4j.auth.basic(USER, PASSWORD), { + resolver: address => addresses +}) +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + + == Close connections Always close `Driver` objects via `Driver.close()` to free up all allocated resources, even upon unsuccessful connection or runtime errors. diff --git a/python-manual/modules/ROOT/pages/connect-advanced.adoc b/python-manual/modules/ROOT/pages/connect-advanced.adoc index ba7ff7bf..5d9f32b7 100644 --- a/python-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/python-manual/modules/ROOT/pages/connect-advanced.adoc @@ -206,10 +206,14 @@ cert_provider.update_certificate( For more information, see link:https://neo4j.com/docs/api/python-driver/current/api.html#neo4j.auth_management.ClientCertificateProvider[API docs -> `ClientCertificateProvider`]. +[#custom-address-resolver] == Custom address resolver When creating a `Driver` object, you can specify a _resolver_ function to resolve any addresses the driver receives ahead of DNS resolution. -Your resolver function is called with an link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] object and should return an iterable of link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] objects (or values that can be used to construct `Address` objects) +Your resolver function is called with an link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] object and should return an iterable of link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] objects (or values that can be used to construct `Address` objects). + +[NOTE] +A custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, python] diff --git a/python-manual/modules/ROOT/pages/connect.adoc b/python-manual/modules/ROOT/pages/connect.adoc index f822f751..e45a4ca3 100644 --- a/python-manual/modules/ROOT/pages/connect.adoc +++ b/python-manual/modules/ROOT/pages/connect.adoc @@ -66,6 +66,37 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, python] +---- +from neo4j import GraphDatabase + + +def custom_resolver(socket_address): + yield "server01.example.com", 7687 + yield "server02.example.com", 7687 + yield "server03.example.com", 7687 + yield "backup.example.org", 7687 + + +driver = GraphDatabase.driver( + "neo4j://example.com:7687", auth=(USERNAME, PASSWORD), + resolver=custom_resolver) +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + + == Close connections Always close `Driver` objects to free up all allocated resources, even upon unsuccessful connection or runtime errors.