Closed letniy71 closed 3 weeks ago
Following your code, no errors show up in the latest version. Could you provide the full example code?
package main
import (
"context"
"errors"
"fmt"
"time"
"github.com/valyala/fasthttp"
)
var (
client = &fasthttp.Client{}
)
func test(ctx context.Context, url string, timeout time.Duration) ([]byte, error) {
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
req.SetRequestURI(url)
resp := fasthttp.AcquireResponse()
if err := client.DoTimeout(req, resp, timeout); err != nil {
if errors.Is(err, fasthttp.ErrTimeout) {
err = fmt.Errorf("askerErrors.ErrTimeout: %w", err)
}
return nil, err
}
return []byte{}, nil
}
func main() {
fmt.Println(test(&fasthttp.RequestCtx{}, "https://www.google.com", time.Second))
}
output:
[] <nil>
1.39
is more than 2 years old, please let me know if you can reproduce this in the latest version.
The problem arises if you set a timeout of around 150 milliseconds (150 * time.Millisecond). Is it possible that, starting from version 1.39, this timeout is also applied to the establishment of the TCP session? I'm testing on version v1.56.0
You are right, I got an error when setting the timeout to less than 300ms.
func main() {
fmt.Println(test(&fasthttp.RequestCtx{}, "https://www.google.com",time.Millisecond*300))
}
[] askerErrors.ErrTimeout: timeout
However, when setting about 350ms. There is no error.
func main() {
fmt.Println(test(&fasthttp.RequestCtx{}, "https://www.google.com",time.Millisecond*350))
}
[] <nil>
This error might be due to an issue with the timer. We can discuss and see which part went wrong. 🤔
Is it possible to set a timeout separately for TCP? (If I use DotimeOut)
In version 1.38, the timeout is managed using a time.Timer
.
timeout := -time.Since(deadline)
// ...
go func(){
// process request
}
// tc is time.Timer
tc := AcquireTimer(timeout)
var err error
select {
case err = <-ch:
case <-tc.C:
mu.Lock()
{
if responded {
err = <-ch
} else {
timedout = true
err = ErrTimeout
}
}
mu.Unlock()
}
In version 1.56, however, a timeout check is performed each step a request is processed, and an error is returned if it has timed out.
deadline := time.Time{}
timeout := req.timeout
if timeout > 0 {
deadline = time.Now().Add(timeout)
}
// ...
for {
// check if timeout
// do request
// check if timeout or exceed the maximum retry times
}
My tests in version 1.38 showed that 250ms almost always timed out, while 300ms succeeded occasionally. In version 1.56, it required 350ms. In terms of implementation, I believe the timeout mechanism in the new version is more accurate since, in the old version, the timer could cause the request to return within the timeout limit due to goroutine scheduling but still be considered as not timed out.
Nevertheless, it’s also possible that, in the new version, the delay is caused by repeatedly checking the time.
Hello. Errors appear dialing to the given TCP address timed out on version 1.39 and later. On version 1.38 the error did not appear