go - 在 Echo/Go 上实现特定路线超时的最佳方法

标签 go timeout middleware go-echo

我想知道为 Echo 库上的特定路线设置超时的最佳方法。

我用context.WithTimeout实现了超时,但使用了几个函数来封装上下文,我认为这是错误的。

ctx, cancel := context.WithTimeout(ctx, 30*time.Second)

是否有任何中间件或更好的方法来实现这一点?

最佳答案

向服务器 context.Context 添加超时

在不确切知道您要做什么的情况下回答这个问题有点棘手。我将首先回答如何使用 WithTimeout 和中间件来处理上下文包装。

中间件可以添加/修改请求上下文,如下所示:

func TimeoutMiddleware(timeout time.Duration, next func(w http.ResponseWriter, req *http.Request)) func(w http.ResponseWriter, req *http.Request) {
    return func(w http.ResponseWriter, req *http.Request) {
        // Wrap the existing context from the request
        ctx, cancel := context.WithTimeout(req.Context(), timeout)
        // Always do this to clean up contexts, otherwise they'll hang out
        // and gather since they are blocked go rountines
        defer cancel()

        // Put the new context into the request
        req = req.WithContext(ctx)

        // Pass the modified request forward
        next(w, req)

        // Handle any ctx timeout issues in the general middleware
        if err := ctx.Err(); err != nil {
            if errors.Is(err, context.DeadlineExceeded) {
                log.Println("HTTP Request timed out")
                w.Write([]byte("Timed out"))
            }
        }
    }
}

问题是 next(w, req) 需要您的 http 处理程序来处理上下文超时。如果 http 处理程序忽略上下文,则不会超时。比如这样:

func endless(w http.ResponseWriter, req *http.Request) {
    ctx := req.Context()
    // Just a busy loop....
    for {
        select {
        case <-ctx.Done():
            // Exit the handler if the context is Done(), even if our function is not.
            return
        default:
            fmt.Println("wait")
            time.Sleep(1 * time.Second)
        }
    }
}

如果您正在进行数据库调用或需要在处理程序中花费时间的操作,通常数据库 API 会接受 context.Context 以便在上下文被取消时提前中止。

因此,此解决方案为进入处理程序的请求上下文添加了超时,您仍然需要管理该处理程序。


客户端超时

您始终可以将超时添加到您的请求中:

    client := http.Client{
        Timeout: time.Second,
    }
    client.Do(...)

关于go - 在 Echo/Go 上实现特定路线超时的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65972668/

相关文章:

c# - 使用 ASP.Net Core 中间件启动后台任务

javascript - Redux:打开和关闭中间件

arrays - 自己结构数组的JSON编码

Go 中的 MongoDB 聚合查找 (mgo.v2)

go - 将 RSA PrivateKey PEM 写入 golang 文件

php - Laravel 队列进程超时错误

json - 在golang中的json unmarshal上获取可为空的对象

python twisted - 发送的消息超时但没有得到响应

JAVA Apache HttpClient SSL 超时

ruby-on-rails - 在 Rails XML 请求中将方法设置为 PUT