-
Notifications
You must be signed in to change notification settings - Fork 41
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
Replaying requests for large files #217
Replaying requests for large files #217
Conversation
Every packet which had 4 bytes of data or less was causing a panic - slice bounds out of range. Closes #215
This makes sure replaying with big responses work well. Without reading the whole response the server under test was behaving differently from the one which traffic is mirrored.
The --output-http-timeout option mieaning is changed. Previously it was a hard limit for which the whole body should have been read. But most of the time this does not work for large bodies. Tho timeout is now set before every Read operation effectively meaning the body will continue to be read as long as there is any data flowing. The timeout will be triggered only after an period of inactivity is reached.
} | ||
toConn.readTimeout = c.config.Timeout | ||
|
||
var readBytes int64 = 0 |
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.
should drop = 0 from declaration of var readBytes; it is the zero value
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.
You're right. Forgot to run go vet
against it.
The tests failed. This happened for me too few times. But other times they all pass. Should I look into the tests as well? |
Unreachable code and default value for the int64 type.
Thanks for doing it! Can you clarify how you use response from http client? |
Well, the set up is this: A production machine which serves big files has an
An other machine, the replayer, is running
As far as I can tell it works great with more than 5 Gbps of traffic and the replayer is not struggling at all. UPDATE: |
Well its not really about number of requests, but their consistency. Payloads larger then 200kb (or those who have more then 3 packets (64kb each), have big chances for corruption. See #167 |
Unfortunatelly our users do not do POST requests. Pretty much all of the requests are GETs and HEADs which do not have a body. So far I haven't noticed any broken requests, in HTTP return code 400 sense. Maybe we can devise some test for consistency? And try it this way? |
Then i do not really get what reading of whole response gives to you. Can you clarify? |
The |
So main problem for you that it closes connection, and not properly emulate user behavior, right? Sorry if i'm too pedantic :) |
Yes, this is my problem which I am trying to solve with this pull request. This is not a small change in the behaviour of the software. You are right in your effort to understand it completely. |
I'm not sure if custom conn timeout implementation needed here, few lines above it sets timeout |
The custom timeout is required. The documentation of net.Conn about deadlines read this:
An absolute time deadline is set for all I/O no matter how many times Read is called (io.CopyN uses the connection's Read method). This means that if now is 15:30:05 and the deadline is set to 15:30:10 any Reads after 15:30:10 will result in a timeout error. If reading the whole body takes more than 5 seconds, then the first read after 15:30:10 will timeout. |
I see, but you can just call |
Yes, the Read again the second bullet in the pull request description and my last comment. Or maybe you think this approach is not enough? Or does not work as intended? |
I see what you mean, but in my view inlining it in for loop will make things easier, like this: for {
if n, err := io.CopyN(ioutil.Discard, c.conn, readChunkSize); err == io.EOF {
break
} else if err != nil {
Debug("[HTTPClient] Read the whole body error:", err, c.baseURL)
break
} else {
readBytes += n
// Setting new timeout for next chunk
timeout = time.Now().Add(c.config.Timeout)
c.conn.SetReadDeadline(timeout)
}
if readBytes >= maxResponseSize {
Debug("[HTTPClient] Body is more than the max size", maxSizeFromBody,
c.baseURL)
break
}
} |
@@ -184,6 +184,12 @@ func (o *HTTPOutput) Read(data []byte) (int, error) { | |||
|
|||
func (o *HTTPOutput) sendRequest(client *HTTPClient, request []byte) { | |||
meta := payloadMeta(request) | |||
|
|||
if len(meta) < 2 { |
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.
Meta is constructed manually, and always should be (type, uuid, time), do you know a repeatable case when meta gets corrupted (because it never should) ?
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.
It does happen fairly often my setup. Normally it takes from few minutes to few hours to happen. I was not able to reproduce it in an automatic test.
But I have stack traces from crashes and can reproduce it easily.
Ah, I see. I didn't understand you before. Yes, it does make it a lot easier to read. Will amend the pull request shortly. |
@ironsmile ping?:) |
any update on this ? |
Fixed in #277 |
I wanted to use
gor
for testing a HTTP server while mirroring real traffic. Unfortunately the traffic was for relatively big media files (from 100MB up to few GBs). In that case the buffer for reading the response body was too small andgor
replayer was failing to replicate the load which real users are generating on the mirrored server.An other limitation was the fixed deadline for reading the response body. With very large files a timeout of 5s, 30s or whatever is not practical as very big files can take some time to be downloaded. On the other hand a relatively small timeout is required to stop stalled connections which do not move any data around anymore. Maybe because of a faulty HTTP server under test, network problems or something else.
This pull request aims to remedy both of the problems. It does it by