sabnzbd / sabnzbd

SABnzbd - The automated Usenet download tool
http://sabnzbd.org
Other
2.31k stars 339 forks source link

Feature: Happy Eyeballs (RFC6555) #264

Closed sanderjo closed 8 years ago

sanderjo commented 9 years ago

Triggered by https://forums.sabnzbd.org/viewtopic.php?f=2&t=19193, I wanted to implement "Happy Eyeballs" (RFC6555) for NNTP(S) connections in SABnzbd. Wikipedia tells: "Happy Eyeballs (also called Fast Fallback) is an algorithm published by the IETF which can make dual-stack applications (those that understand both IPv4 and IPv6) more responsive to users, avoiding the usual problems faced by users with imperfect IPv6 connections or setups."

First I created a python module 'happyeyeballs'. That code finds the quickest IP address for a (news)server, no matter if it's IPv4 or IPv6. It does this by checking the connect() to each IP address. (My implementation is not pure HappyEyeballs as my implementation does not give a time advantage to IPv6, and does checking of all IP addresses.)

The hook into SABnzbd.py was easy: sabnzbd/downloader.py has this function:

    @property
    def hostip(self):
        """ Return a random entry from the possible IPs
        """
        if cfg.randomize_server_ip() and self.info and len(self.info) > 1:
            rnd = random.randint(0, len(self.info)-1)
            ip = self.info[rnd][4][0]
            logging.debug('For server %s, using IP %s' % (self.host, ip))
        else:
            ip = self.host
        return ip

So, in my SAB code, with cfg.randomize_server_ip()==2, the HappyEyeballs / fastest IP is chosen.

I will send a pull request so this can be included in 0.8.0 Alpha.

Example output of code of the bare happyeyeballs code:

$ ./test-nntp-server.py newszilla.xs4all.nl
Checking newszilla.xs4all.nl 119 SSL: False DEBUG: True
Address is  2001:888:0:18::119
Connecting took: 0.995 msec
Address is  194.109.6.166
Connecting took: 0.95 msec
Fastest server is 194.109.6.166
194.109.6.166
Checking block.cheapnews.eu 443 SSL: True DEBUG: True

Address is  2a02:d28:10:1b:0:431:ff02:165
Connecting took: 3.461 msec

Address is  78.152.55.165
Connecting took: 2.381 msec

Fastest server is 78.152.55.165
78.152.55.165
$ ./test-nntp-server.py sslreader.eweka.nl
Checking sslreader.eweka.nl 119 SSL: False DEBUG: True
Address is  81.171.92.219
Connecting took: 1.004 msec
Address is  81.171.92.233
Connecting took: 0.894 msec
Address is  81.171.92.205
Connecting took: 0.615 msec
Fastest server is 81.171.92.205
81.171.92.205
thezoggy commented 9 years ago

guess your just doing nslookup on a hostname and getting the ips from that method..

Name:    block.cheapnews.eu
Addresses:  2a02:d28:10:1b:0:431:ff02:165
          78.152.55.165
Name:    sslreader.eweka.nl
Addresses:  81.171.92.219
          81.171.92.233
          81.171.92.205
sanderjo commented 9 years ago

That is the first step indeed, and then a socket connect() & close() per IP address, measuring the time that that takes.

sanderjo commented 9 years ago

Notes:

Example of SAB logging output

2015-07-30 06:37:04,450::DEBUG::[downloader:111] For server sslreader.eweka.nl, using IP 81.171.92.233 as fastest server
2015-07-30 06:37:04,898::DEBUG::[downloader:111] For server sslreader.eweka.nl, using IP 81.171.92.233 as fastest server
2015-07-30 06:37:05,325::DEBUG::[downloader:111] For server sslreader.eweka.nl, using IP 81.171.92.233 as fastest server
2015-07-30 06:37:05,708::DEBUG::[downloader:111] For server sslreader.eweka.nl, using IP 81.171.92.219 as fastest server
2015-07-30 06:37:05,773::DEBUG::[downloader:111] For server newszilla.xs4all.nl, using IP 194.109.6.166 as fastest server
2015-07-30 06:37:05,845::DEBUG::[downloader:111] For server newszilla.xs4all.nl, using IP 2001:888:0:18::119 as fastest server
2015-07-30 06:37:05,913::DEBUG::[downloader:111] For server newszilla.xs4all.nl, using IP 2001:888:0:18::119 as fastest server
2015-07-30 06:37:05,982::DEBUG::[downloader:111] For server newszilla.xs4all.nl, using IP 2001:888:0:18::119 as fastest server
2015-07-30 06:37:06,200::DEBUG::[downloader:111] For server block.cheapnews.eu, using IP 2a02:d28:10:1b:0:431:ff02:165 as fastest server
sanderjo commented 9 years ago

@shypike

In the WebGUI, "randomize_server_ip" is now a check box in Config -> Special I want to make it a dropdown: Standard, Random, Fastest Server / Happy Eyeballs. Do you agree? If so, where? My suggestion: Config -> Swicthes, under Server

(I could leave it under Config -> Special, but it would be the first non-checkbox feature on that page...)

thezoggy commented 9 years ago

Fastest is misleading... Lots of people associate fast with throughout not latency...

-----Original Message----- From: "sanderjo" notifications@github.com Sent: ‎7/‎30/‎2015 3:24 PM To: "sabnzbd/sabnzbd" sabnzbd@noreply.github.com Cc: "thezoggy" thezoggy@gmail.com Subject: Re: [sabnzbd] Feature: Happy Eyeballs (RFC6555) and Fastest Server/IP (#264)

@shypike

In the WebGUI, "randomize_server_ip" is now a check box in Config -> Special I want to make it a dropdown: Standard, Random, Fastest Server / Happy Eyeballs. Do you agree? If so, where? My suggestion: Config -> Swicthes, under Server

(I could leave it under Config -> Special, but it would be the first non-checkbox feature on that page...)


Reply to this email directly or view it on GitHub: https://github.com/sabnzbd/sabnzbd/issues/264#issuecomment-126471685

sanderjo commented 9 years ago

Good point. So "Lowest latency"?

thezoggy commented 9 years ago

Quickest Response? First Response? might be better since not everyone probably knows latency.. and also for translation support

sanderjo commented 9 years ago

Based on the thread above (thanks @thezoggy ) and my mail exchange with @shypike , I have removed "fastest" references.

sanderjo commented 9 years ago

FWIW: example of newsservers with both an IPv4 and an IPv6 address, so useful for the happy eyeballs feature:

$ lynx --dump http://download.jbjb.nl/usenetservers.xml | awk '{ print "host " $1 }' | sort -u | /bin/sh | grep -B1 IPv6

block.cheapnews.eu has address 78.152.55.165
block.cheapnews.eu has IPv6 address 2a02:d28:10:1b:0:431:ff02:165
--
news.cheapnews.eu has address 78.152.55.164
news.cheapnews.eu has IPv6 address 2a02:d28:10:1b:0:431:ff02:164
--
newszilla.xs4all.nl has address 194.109.6.166
newszilla.xs4all.nl has IPv6 address 2001:888:0:18::119

There are more IPv6 enabled newsservers but they have separate IPv4-only and IPv6-only FQDN's. Example:

reader.xsnews.nl: IPv4-only
readeripv6.xsnews.nl: IPv6-only

More on http://ipv6-or-no-ipv6.blogspot.nl/2015/05/ipv6-newsservers.html

sanderjo commented 9 years ago

I've implemented the GUI under Config -> Switches.

sabnzbd gui for happyeyeballs

Safihre commented 9 years ago

To be honest for non-super-technical users this looks confusing, even for me. Why would I want to "randomize" my server? Even with the label 'Randomize server hostname' and looking directly at the code, I still don't understand why I should turn randomization on?

HappyEyeballs sounds also like quite a weird term, what about:

shypike commented 9 years ago

For most servers whose DNS returns multiple IP addresses, it is best to pick a random one so that load balancing is used. With some servers this is not a good solution, which is why the "Special" was created. Explaining the usefulness in a few words is a challenge. This is what our Wiki says:

Some Usenet providers have multiple IP addresses for a single server name. For such a server, SABnzbd will pick a random IP from the list for each connection. If your server has problems with this (e.g. it also lists invalid IPs), you can set this option to 0

The purpose is load balancing. So maybe these should be the choices:

Now that I think of it: maybe it should be a per-server choice :(

Safihre commented 9 years ago

That makes much more sense when using that explanation. Let's do per-server for 0.9 ;-)

Safihre commented 9 years ago

Also, will we just turn this on by default for new installs? Seems like logical thing to do with more and more IPv6 servers joining in the near future.

shypike commented 9 years ago

"on" (without Happy Eyeballs) was already the default.

Safihre commented 9 years ago

Indeed, so make it with happy eyeballs default?

shypike commented 9 years ago

That's for Sander to decide, but It shouldn't backfire to people without IPv6, which is most of us. @sanderjo

sanderjo commented 9 years ago

Eventually happy eyeballs ("HE") should be the default. That's how it works in Chrome and FIrefox. But before that, I want 1) get feedback from users 2) improve the implementation

sanderjo commented 9 years ago

About naming: this is what we want:

Server load-balancing

Correct?

Then about default: the code (up to my change) said:

randomize_server_ip = OptionBool('misc', 'randomize_server_ip', False)

... so that means default was No Randomizing, right?

shypike commented 9 years ago

@sanderjo OK, I was convinced that the current default was True, but it isn't. I don't remember why we chose this. Too many servers having unusable IPs in their DNS record? So for now, maybe we should keep the default as is, The names you proposed are OK. Maybe "HappyEyeballs" in the explanatory text?

Safihre commented 9 years ago

But if you make HappyEyeballs default, it will check if the IP's actually work (and chose the fastest), right? So that would be the best default-option.

sanderjo commented 9 years ago

Yes, HE checks which IPs work, and chooses the IP with the quickest response.

Yes, as said, I think HE should be default some time after now (in half a year?); first some experience and improvements.

shypike commented 9 years ago

OK, set the new default to HE. One practical issue: once an option is there, changing its default won't change anything for existing users. The solution would be to create a new option name: "load_balancing". That would also get rid of the odd name "randomize_server_ip". I can change that, if you like.

BTW: if HE is the most sensible choice, why not move it back to the "Special" section?

sanderjo commented 9 years ago

Done: Renaming of the load balancing options

sabnzbd happyeyeballs gui 2

sabnzb happyeyeballs dropdown

thezoggy commented 9 years ago

instead of 'with optimization for' why not just say 'preference' or 'priority' for IPv6?

sanderjo commented 9 years ago

Because the text was agreed on above Because I have not (yet) implemented priority for IPv6 ...

That's on my to-do list. According to Happy Eyeballs, IPv6 should be preferred and should therefor be given a headstart of 0.3 second. I started coding that, but the code got ugly quickly ... so work to do.

thezoggy commented 9 years ago

is your implementation stateful? (aka does it know v6 did or didnt work for the instance sab is running? does it just blindly test each time? is there a delay/cache?)

i personally vote to do the HE logic test on nzb start.. that way you dont have connection thrashing and wasted sockets/handles continuously happening for each article attempt..

i recently setup a 6in4 tunnel.. which caused most things to break randomly.. thus i had to go back to just disabling v6 to make everything happy :/

sanderjo commented 9 years ago

Implementation is kind-of stateful; as long as SAB is downloading from a server. See details in my post https://github.com/sabnzbd/sabnzbd/issues/264#issuecomment-126180512

thezoggy commented 9 years ago

@sanderjo okay good.