-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
websocket: add reuseport support #2261
base: master
Are you sure you want to change the base?
websocket: add reuseport support #2261
Conversation
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.
Thank you for your PR! This mostly looks good, just a few comments.
You are welcome. Pushed new commits addressing your review comments. |
@marten-seemann please approve the workflows post which this can be merged. |
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.
Thank you @chaitanyaprem! The code looks good to me, but I'm a bit confused with the test case.
Unfortunately, we just switched back to the Gorilla WebSocket library (#2280). This is creating merge conflicts with this PR. Would you mind rebasing this PR on top of the current master?
Will resolve and push updated ones. |
Listen on unspecified port. Verify that client connections are distributed amongst multiple listeners.
Pushed updated changes as per review comments. |
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.
Nice PR! (commenting as an outsider)
Q: This PR adds the ability to listen on the same port by multiple parties. The TCP implementation for reuseport
will also try to use listening ports also for dialing. This is not handled in this PR, is that right?
Thanks @Maelkum for your comments. Addressed all the others. |
Wow, this is surprising that load balancing across multiple listeners is not functioning on windows as well as Mac even-though 2 sockets are allowed to listen on same address+port. Wrt Windows, i found this ref which does not guarantee the behaviour of SO_REUSEADDR. Has the TCP reuse port been tested for load balancing? Note: While going through the web searching for expected behaviour for these socket options, noticed that for FreeBSD based systems in order for load balancing to be supported an additional option has to be set SO_REUSEPORT_LB, Ref. This is something to be explored and added to the reuseport package Will update once i investigate further. |
chore: reuseport test script-Skipping connection load balancing check for architectures other than linux as it is not gauranteed.
Update on further investigation, looks like macOS also doesn't support load balancing across listeners. So, for now I have skipped checking for load balancing of connections for any platform other than linux in the test script. |
Pushed changes to reuse port in case of dailing. |
@marten-seemann @MarcoPolo All required changes and review comments have been addressed. |
@chaitanyaprem The WebSocket tests are failing on CI. Can you please take a look? |
Surprisingly the test is successful now, i ran it on a local ubuntu vm (Ubuntu 22.04.3 LTS) as well and there also tests are successful. It is hard to determine whether some other change fixed the issue or is the test just flaky. |
I reran the test suite and it's failing again. We can't introduce any flaky tests, please make sure it consistently passes (you can run the test suite with |
Ran it 1000 times and it fails sometimes. |
@sukunrt is gonna help take this over the finish line in time for the v0.31 release @chaitanyaprem |
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 have a couple of other nits, but let's get the dial side to reuse the port we are listening on first.
nl, err = reuseport.Listen(lnet, lnaddr) | ||
if err != nil { |
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.
We want to use the transport's reuseTransport
field. Otherwise this will never reuse the port we're listening on when dialing. I guess you can pass them in to newListener
.
Also add a test that we are reusing port when dialing.
dialer.NetDial = func(network, address string) (net.Conn, error) { | ||
return t.reuseTransport.DialContext(ctx, raddr) | ||
} | ||
} | ||
if isWss { | ||
sni := "" | ||
sni, err = raddr.ValueForProtocol(ma.P_SNI) |
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.
This will also need to have the reuse logic: https://github.com/libp2p/go-libp2p/blob/master/p2p/transport/websocket/websocket.go#L205
@chaitanyaprem just checking in. Let me know if you have any questions here. I'm available in filecoin slack(link in repo README). |
Got little busy with other work and hence not able to take a look at this. |
Thanks for the update @chaitanyaprem |
Hi guys! I hope this is not me being rude.. At a similar time when this PR was opened, I played around with implementing a similar thing. I rebased those changes to sync with the latest master (at the time this repo used nhooyr.io/websocket). Tested it mostly in the listen => dial scenario, compared to multiple listens. Since this PR is open for a while now, I figured I'd throw the link here. Feel free to cherry pick any piece of code out of there if it's useful. Hope this isn't bad manners! |
Thanks @Maelkum. This PR has been dormant for a while so I think it's okay. Do you want to open a new PR or take over this one? |
Thanks @Maelkum |
@sukunrt @chaitanyaprem |
Implemented reuse-port capability for websocket transport #1435 using the existing net/reuseport transport and libp2p/go-reuseport.
In order to utilize REUSEPORT, reuseport option has to be passed while creating the websocket transport.
This would allow for multiple threads/routines to listen on same IP/port combination.
Included a test that would verify reuseport by running 2 go-routines that would listen on same address and accept connections from 4 different clients.
Reran the existing test-suite for the websocket package to ensure no other tests fail.
Note: Tested the new changes in ubuntu-20.04 and windows-11 environment.