-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
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
bpo-33530: Implement Happy Eyeballs in asyncio, v2 #7237
Conversation
Added two keyword arguments, `delay` and `interleave`, to `BaseEventLoop.create_connection`. Happy eyeballs is activated if `delay` is specified.
Added two keyword arguments, `delay` and `interleave`, to `BaseEventLoop.create_connection`. Happy eyeballs is activated if `delay` is specified.
reordered.extend(_roundrobin(*addrinfos_lists)) | ||
return reordered | ||
|
||
|
There was a problem hiding this comment.
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)?
There was a problem hiding this comment.
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.
Lib/asyncio/base_events.py
Outdated
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): |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
A simpler version is now folded into _interleave_addrinfos.
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( |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
@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 |
There was a problem hiding this comment.
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.
An update on this PR:
|
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 |
@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! :) |
The name is 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]>
Sorry, I can't merge this PR. Reason: |
@twisteroidambassador thank you for your patience and responsibility to fix comments! |
* 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) ...
Added two keyword arguments,
delay
andinterleave
, toBaseEventLoop.create_connection
. Happy eyeballs is activated ifdelay
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