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

Fix ipv6 issue #158 #204

Merged
merged 5 commits into from
Jul 1, 2022
Merged

Fix ipv6 issue #158 #204

merged 5 commits into from
Jul 1, 2022

Conversation

peczenyj
Copy link
Contributor

@peczenyj peczenyj commented May 8, 2022

Hello

this pull request fixes issue #158

the root cause of this bug is this line

newAdd := fmt.Sprintf("%s:%d", ip, port)

In most of the cases, we can just concatenate the host with port using : as separator, however the ipv6 format uses the : to separate each segment. To be possible to use ipv6 in such cases (network host +port, or urls domain + port) the convention is to add [] around the ip.

Go standard lib give us a function net.JoinHostPort that can handle such cases.

https://pkg.go.dev/net#JoinHostPort

You may note that this function receive two strings, host and port. Port can be a string in some cases:

  1. when we decide to omit the port (and there is a default to use like in http/80 and https/443 ports)
  2. when de use a registered port (on linux it is defined on /etc/services file) like :ssh or :http-alt. Some ports are defined by IANA and others are free to assing AFAIK.

This bug shows something more complex to discuss: to create a connection pool (via NewConnectionPool) I need to define an slice of HostAddress, defined as

type HostAddress struct {
	Host string
	Port int
}

This format forces me to define the host by creating a structure and I must follow this format of split host and port.

Doing this I can't use a registered (string) port and I must know the port (there is no way to use a "default port"). In other words this is not an easy way to create a connection to a database IMHO.

If we check how can we connect to other databases such as mysql or couchbase, they offer a simple connection string with a uri-like format. For instance mysql://username:password@host:port/database?driver-parameters

The biggest advantage of such format is: I just need to use one string. Strings are easy to read from command line or configuration files. Sometimes we can define several connection strings split by , - and this is very helpful in some situations.

I also note that the connection pool performs a round-robin on each available server, and this is done by converting the each host in the first ip (the ipv4) returned by net.LookupIP inside the function DomainToIP. Perhaps this allow to save some time by performing the lookup just once, but I can see some side effects:

  1. If I decide to use a several instances of nebula db with a dns solution like Consul, I may end with the ip of one instance and never connect in the others.
  2. If I do the lookup in the begin of the program and I have one situation with few nodes of nebula db, if I need to replace one node for any reason the client must be restarted to see the new node and perhaps may try to connect to the old one.

I can't see if there is a problem on such side effects of it is by design.

I had such issues with a grpc service: since it uses HTTP2 persistent requests, the client never connect to a second server and the solution can't scale well. What grpc (and other databases) offer is some load balancer options via dns. This is not by default, but it perform lookups at some interval to be sure it can spread the connection to all nodes.

I think this go client can use something like this:

  1. be possible access via a simple connection string (uri-like or not, but I can propose something like mysql, with default port 9669 if not present and be possible to define the attributes of PoolConfig in the query string like nebuladb://localhost/some-graph-space-name?timeout=10s&maxconnpoolsize=99)
  2. be possible to use client load balance via dns actively (instead the current one)
  3. perhaps use the dns SRV records to load balance
  4. be possible to not use the client load balancer
  5. perhaps offer a way to be possible define a custom load balancer (implemented by the user, via a common interface)

BTW, is it possible access nebula db using Unix Domain Sockets?

however... this may be something toadd on nebula db itself and replicate on all other libraries, and since we have working code that depends on the existing logic it is not easy do change it.

However expose a constant DefaultPort = 9669 is something easy to do IMHO. Can be a good start.

tips from:
https://neo4j.com/docs/go-manual/current/client-applications/
https://dev.mysql.com/doc/refman/8.0/en/connecting-using-dns-srv.html

Regards,

peczenyj and others added 3 commits May 8, 2022 14:45
… as a nebula driver (vesoft-inc#200)

* remove remote services, the code is not necessary to use this project as a nebula driver

* Create integration tests (vesoft-inc#201)

* add build tag for integration tests

* add unit rule to run unit tests

* add unit as phony

* improve formatting of each _test file, enable coverate on functional tests

* add badge for test results

Co-authored-by: Yichen Wang <18348405+Aiee@users.noreply.github.com>
Copy link
Contributor

@veezhang veezhang left a comment

Choose a reason for hiding this comment

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

LGTM

@Aiee Aiee merged commit 4e1c4a4 into vesoft-inc:master Jul 1, 2022
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.

3 participants