stompgem / stomp

A ruby gem for sending and receiving messages from a Stomp protocol compliant message queue. Includes: failover logic, ssl support.
http://stomp.github.com
Apache License 2.0
152 stars 80 forks source link

ipv4 and ipv6 dual homing #34

Closed ripienaar closed 12 years ago

ripienaar commented 12 years ago

hey,

When using the stomp gem in a mixed ipv6 and ipv4 setup it does the right thing for the initial connection - tries the ipv6 address first. But if the connection to the ipv6 host fails it doesn't attempt to connect to the ipv4 address as a failback, it keeps trying the ipv6 one.

This behavior makes sense but ruby TCPSocket.new doesnt do this, it might be something to detect open_tcp_socket and handle? The same might be said for hosts with many ipv4 addresses, we should try them all before moving to the next host.

% telnet stomp 6164
Trying 2001:41d0:2:xx::2...
telnet: connect to address 2001:41d0:2:xx::2: Connection timed out
Trying 178.xx.48.196...
Connected to stomp.
gmallard commented 12 years ago

Hmmm .... not sure what all you might be asking for here.

a) What does this mean: ' to detect open_tcp_socket and handle?' ???? Clarify please. How? b) Regarding 'hosts with many ipv4 addresses, we should try them all before moving to the next host' ..... are you suggesting that we call 'getaddrinfo' and loop through the results? c) Need to think about how I would be able to test any IPV6 traffic other than localhost ...... certainly not possible with my current router config.

ripienaar commented 12 years ago
gmallard commented 12 years ago

The offer of a linode machine is quite gracious, thank you. I will decline that for now, but might reopen the subject later.

I will ramble here, in no particular order ......

My concerns right now are several:

1) I am looking an the next 6-9 months personal workload, and conclude I may not have a lot of time to spend working on this gem. This gem and STOMP work in general is a 'side' job for me, certainly not part of the daily grind. 2) There are no other developers actively interested in this gem. 3) I am a little concerned that this effort is not really related to the STOMP protocol at all. However, it would not be the first time that the gem was modified to support requirements not related to STOMP.

Background here: I have 3 machines on my LAN for testing. All hardware/OSs are IPV6 capable. The router is 6 capable on the LAN, but not capable for the outside world ..... at least the way I read the docs. And it is not currently configured for 6 support. I have never used IPV6, and need to figure out .... how that all works I suppose.

So ...... if this were to be done, the MUST high level requirements (subject to change of course) are:

I am pondering SHOULD/MUST for:

My current thinking is: use information returned by Socket::getaddrinfo to accomplish this. It seems to provide the necessary information. There are certainly 1.8 versus 1.9+ challenges with that approach. Open to suggestions here.

Of course if a user enables the feature, and passes in a host "name" that is an actual address like:

that needs to be considered. This part ..... might be easy.

If you need this soon, I suggest the following:

If your participation is not possible, advise me of that. And I will look at this as I can.

Still thinking here, and let me know your thoughts please.

ripienaar commented 12 years ago

Hey

Thanks for the rambling :P

First, this ticket isnt a big deal, it's something I noticed and thought next time someone is in the guts of TCP connections this might be worth considering. What happened is my IPv6 connectivity died (its via a tunnel broker in this instance) but IPv4 was up so would be nice to have somehow gotton to a working connection in that scenario.

I think this gem is quite unique in broker gems - like the AMQP ones etc - in that it has good reliable built in connection handling that the user can just set reliable => true and forget about it, it's one of the things I love most about it :) So the semantics of the connections matters more than in the case of ones that just implement protocol stuff but leaving the connection handling up to the user

I can take a crack at it as time permits, but like I said I am happy to just have this here for a reminder note till such time that proper attention can be given to it - be that from me or you

gmallard commented 12 years ago

Cool. Having given this some more thought ...... it may not be as extensive as I first thought.

I am thinking that open_tcp_socket is not the right place to plant the hook, but that is another matter. Am thinking make a pass at the :hosts array in refine_params and add/modify entries as required. Failovers should just flow from that, I think.

ripienaar commented 12 years ago

Yeah thats actually a pretty good approach, didnt think of that!

Selection isnt hard, in both v4 and v6 setups if the name resolve to multiple addresses you should just take the first one - the underlying resolvers will take care of ordering as per dns round robin or compliance to RFC3484 etc.

Your approach should quite effective then

gmallard commented 12 years ago

To help make sure that what I am thinking will probably work, can you use use the host shown in the telnet example above, and show me the output (obfuscated as necessary) from:

irb
require 'socket'
Socket.getaddrinfo("stomp", nil, nil, Socket::SOCK_STREAM)

Thanks.

ripienaar commented 12 years ago
=> [["AF_INET6", 0, "kvm4.xx.net", "2001:xx:2:xx::1", 10, 1, 6], ["AF_INET", 0, "kvm4.xx.net", "176.xx.xx.147", 2, 1, 6]]
% host stomp
stomp.xx.net is an alias for kvm4.xx.net.
kvm4.xx.net has address 176.xx.xx.147
kvm4.xx.net has IPv6 address 2001:xx:2:xx::1
gmallard commented 12 years ago

Thanks. That is what I hoped for.

Not relevant to this discussion, but the Ruby guys have done something bizarre with those results starting in 1.9.2. You do not actually see the host name in that Array. That array element then contains the IP address, which appears twice. e.g.

irb(main):002:0> ai = Socket.getaddrinfo("localhost", nil, nil, Socket::SOCK_STREAM)
=> [["AF_INET6", 0, "::1", "::1", 10, 1, 6], ["AF_INET", 0, "127.0.0.1", "127.0.0.1", 2, 1, 6]]

At this point I have absolutely no idea what the motivation for that is .....

ripienaar commented 12 years ago
At this point I have absolutely no idea what the motivation for that is .....

A common feeling when dealing with ruby 1.8 -> 1.9 :)

gmallard commented 12 years ago

Committed on HEAD of 'dev' branch. Remarkably little actual code to accomplish this.

Active by including:

:dmh => true

in a Connect hash at login.

I have been able to minimally test this here, and it appears to work.

ripienaar commented 12 years ago

Yup, that's pretty nice and elegant. I did a quick test and it works fine

gmallard commented 12 years ago

This will go in to 1.2.3. I am closing this issue for now.