Skip to content
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

Add pause/resume to protocol #36

Merged
merged 1 commit into from
Jan 4, 2022

Conversation

ibuildthecloud
Copy link
Contributor

@ibuildthecloud ibuildthecloud commented Dec 7, 2021

With a slow enough consumer it is possible to freeze the websocket server
for that connection causing the ping to timeout. pause and resume
messages are now added to the protocol to tell client to stop writing
data if the server side buffer is filling up.

For rancher/rancher#34819

With a slow enough consumer it is possible to freeze the websocket server
for that connection causing the ping to timeout.  pause and resume
messages are now added to the protocol to tell client to stop writing
data if the server side buffer is filling up.
@@ -64,6 +72,11 @@ func (r *readBuffer) Read(b []byte) (int, error) {
n, err = r.buf.Read(b)
r.cond.Broadcast()
if err != io.EOF {
if r.buf.Len() < MaxBuffer/8 {

Choose a reason for hiding this comment

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

Is there a chance when the buf always has more data than MaxBuffer/8 so that it never resume other write go routines?

Copy link

@thedadams thedadams Jan 3, 2022

Choose a reason for hiding this comment

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

I believe this question remains. Is it possible that on one read, the err == nil and r.buf.Len() >= MaxBuffer/8? Then on the next read err == io.EOF?

It would seem that in this case we would never resume.

Choose a reason for hiding this comment

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

The above comment is not relevant. The implementation of bytes.Reader will return io.EOF only if the buffer is empty on read. If the buffer is empty after the read, then a nil error is returned. So this looks correct to me.

)

const (
MaxBuffer = 1 << 20
MaxBuffer = 1 << 21

Choose a reason for hiding this comment

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

How is this number defined? Can maxBuffer be dynamically increased if it can't hold more data? same like the array size that is dynamically increased when buffer exceeded...

Choose a reason for hiding this comment

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

Talked offline, this is a flow control issue. Quote from darren:

it's a flow control issue. If the tunnel client is sending data at 1mb/s and the user is reading data at 1kb/s we will just fill up memory

defer b.cond.L.Unlock()

b.paused = false
b.cond.Broadcast()

Choose a reason for hiding this comment

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

Need an advanced sync lecture for this... 😲

Copy link
Contributor

Choose a reason for hiding this comment

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

how do you mean?

@alexellis
Copy link
Contributor

What kind of scenarios caused this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants