Thanks to visit codestin.com
Credit goes to github.com

Skip to content

bpo-33530: Implement Happy Eyeballs in asyncio, v2 #7237

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

Merged
merged 23 commits into from
May 5, 2019

Conversation

twisteroidambassador
Copy link
Contributor

@twisteroidambassador twisteroidambassador commented May 30, 2018

Added two keyword arguments, delay and interleave, to
BaseEventLoop.create_connection. Happy eyeballs is activated if
delay is specified.

We now have documentation for the new arguments. staggered_race() is in its own module, but not exported to the main asyncio package.

https://bugs.python.org/issue33530

reordered.extend(_roundrobin(*addrinfos_lists))
return reordered


Copy link
Member

Choose a reason for hiding this comment

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

base_events.py is already overly long. Would it make sense to move these two functions to staggered.py (keeping them private)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it makes sense to group all Happy Eyeballs-related functions in the same module (in that case the name staggered.py leaves something to be desired). On the other hand, if interleave is to be made meaningful without using happy eyeballs, then it feels weird to have _interleave_addrinfos somewhere else.

async def create_connection(
self, protocol_factory, host=None, port=None,
*, ssl=None, family=0,
proto=0, flags=0, sock=None,
local_addr=None, server_hostname=None,
ssl_handshake_timeout=None):
ssl_handshake_timeout=None,
delay=None, interleave=None):
Copy link
Member

Choose a reason for hiding this comment

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

I think that delay parameter doesn't clearly convey that it switches on a completely different connect behaviour. Maybe call it "happy_eyeballs_delay"?

@asvetlov what do you think? BTW, do you guys have happy eyeballs implementation in aiohttp?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, we have not (yet). We iterate over available hosts one by one.
BTW there is potentially related thing: SRV DNS records.
It can be useful for organizing load balancing and high available systems.
Rust supports it, would be nice to have it in asyncio too.

Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer happy_eyeballs: HappyEyeBallsConfig=None where HappyEyeBallsConfig is a dataclass with all required configuration parameters.

Copy link
Member

Choose a reason for hiding this comment

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

I prefer happy_eyeballs: HappyEyeBallsConfig=None where HappyEyeBallsConfig is a dataclass with all required configuration parameters.

Oh, that's a bit too heavy IMO. We don't have a precedent for such API design neither in asyncio nor in any other popular APIs. And maybe interleave isn't a happy eyeballs specific thing?

I think that interleave=True is meaningful even when happy eyeballs isn't enabled:

await loop.create_connection(proto_factory, "google.com", 80, interleave=True)
# connect to google, but shuffle the addresses that getaddrinfo resolves to

If that's the case, then we want just happy_eyeballs_delay parameter to enable happy eyeballs algorithm.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

BTW there is potentially related thing: SRV DNS records.
It can be useful for organizing load balancing and high available systems.
Rust supports it, would be nice to have it in asyncio too.

I don't know how prevalent SRV is used, but since the operating system's getaddrinfo doesn't support anything but A and AAAA queries, some other DNS library will be required to do SRV queries. (Linux has libresolv, not sure whether it's cross platform.) At that point it's probably too big to fit in asyncio.

if first_address_family_count > 1:
reordered.extend(addrinfos_lists[0][:first_address_family_count - 1])
del addrinfos_lists[0][:first_address_family_count - 1]
reordered.extend(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed _roundrobin as a standalone function and folded it into _interleave_addrinfo. Do we still want to move _interleave_addrinfo to staggered.py? Now that the interleave option works independently of happy_eyeballs_delay, it feels more natural to leave _interleave_addrinfo here.

Copy link
Member

Choose a reason for hiding this comment

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

I think it's OK to keep it here now

@1st1
Copy link
Member

1st1 commented Jun 25, 2018

@asvetlov this looks good to me now and I'm OK with merging this into 3.8. Could you please take a look too?

in RFC 8305. A sensible default value recommended by the RFC is 0.25
(250 milliseconds).

* *interleave* controls address reordering when a host name resolves to
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe it's worth naming the parameter interleave_af to make it more explicit.

@1st1
Copy link
Member

1st1 commented Jul 28, 2018

An update on this PR:

  • I like it and want to have it in 3.8.

  • I asked @asvetlov to try it in aiohttp, as he wants to add support for HE there anyways. Basically, we're awaiting for his feedback now.

@twisteroidambassador
Copy link
Contributor Author

Cool, I would love to hear feedback from real world usage. 👍

I'm also continuing to improve my Happy Eyeballs implementation in https://github.com/twisteroidambassador/async_stagger , where the goal is not strict adherence to existing asyncio behavior. I've recently added support for multiple local bind addresses, (e.g. providing both an IPv4 and an IPv6 local address, so when connecting to a remote IPv6 address the bound local address is IPv6 and vice versa). Is this feature something people will want to use? Does it make sense to add this to asyncio?

@1st1
Copy link
Member

1st1 commented Oct 1, 2018

@asvetlov I remember us discussing this PR at the sprints, and I think you told me that it's working alright in aiohttp. I think I also recall you saying that you don't like a name of some parameter or something... what was it? Let's fix and merge! :)

@asvetlov
Copy link
Contributor

asvetlov commented Oct 3, 2018

The name is Lib/asyncio/staggered.py

I still didn't backport the PR into aiohttp but can do it (and test on real users :D ) later

Do not expose .staggered submodule in __all__.

Co-Authored-By: twisteroidambassador <[email protected]>
@miss-islington
Copy link
Contributor

Sorry, I can't merge this PR. Reason: Base branch was modified. Review and try the merge again..

@miss-islington miss-islington merged commit 88f07a8 into python:master May 5, 2019
@asvetlov
Copy link
Contributor

asvetlov commented May 5, 2019

@twisteroidambassador thank you for your patience and responsibility to fix comments!

CuriousLearner added a commit to CuriousLearner/cpython that referenced this pull request May 7, 2019
* master: (1204 commits)
  bpo-31855: unittest.mock.mock_open() results now respects the argument of read([size]) (pythonGH-11521)
  Forbid creating of stream objects outside of asyncio (python#13101)
  bpo-35925: Skip SSL tests that fail due to weak external certs. (pythonGH-13124)
  Fix rst formatting for several links in ssl documentation (pythonGH-13133)
  bpo-36542: Allow to overwrite the signature for Python functions. (pythonGH-12705)
  bpo-36793: Remove unneeded __str__ definitions. (pythonGH-13081)
  bpo-36766: Typos in docs and code comments (pythonGH-13116)
  bpo-36275: enhance documentation for venv.create() (pythonGH-13114)
  Clarify the download unit in the download section (pythonGH-13122)
  bpo-30668: add missing word in license.rst (pythonGH-13115)
  Unroll import-team in CODEOWNERS (python#13118)
  bpo-36594: Fix incorrect use of %p in format strings (pythonGH-12769)
  bpo-36798: Updating f-string docs for := use case (pythonGH-13107)
  Update wsgiref.rst (python#10488)
  Doc/c-api/exceptions.rst: fix grammar (python#12091)
  bpo-36811: Fix a C compiler warning in _elementtree.c. (pythonGH-13109)
  Only count number of members once (python#12691)
  bpo-16024: Doc cleanup regarding path_fd, dir_fd, follow_symlinks (pythonGH-5505)
  bpo-36791: Safer detection of integer overflow in sum(). (pythonGH-13080)
  bpo-33530: Implement Happy Eyeballs in asyncio, v2 (pythonGH-7237)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants