Goroutine 已在 Go Web 服务器中根据请求启动,但客户端断开连接,Web 服务器是否可以关闭该特定 Goroutine?

问题描述 投票:0回答:2

每当客户端发出 Web 请求时,它都会生成一个 goroutine 来处理每个请求。如果客户端恰好断开连接,Web 服务器是否有可能关闭该特定 Goroutine,或者该 Goroutine 在执行完所有代码后是否会发现客户端已经断开连接?

rest web-services go webserver goroutine
2个回答
6
投票

除了在读取或写入错误时从被调用的处理程序返回时退出之外 - 正在执行的 go 例程不会自动处理清理较长运行时间的操作,但 Go 提供了处理此问题的好方法。

首先,如果您不熟悉 context 包 - 这是一种将 Go 例程与取消行为同步的强大且惯用的方法,我强烈建议您阅读博客 Go 并发模式:Context

类似以下内容:

func MyServiceFunc(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            break
        default:
            //do work
        }
    }
}

func MyRequestHandler(res http.ResponseWriter, req *http.Request) {
    MyServiceFunc(req.Context())       
   //write response...
}

或者您可以使用 CloseNotifier 接口,其中 http.ResponseWriter 也实现了,您可以执行类似于以下简单示例的操作:

func MyServiceFunc(notifier <-chan bool) {
    for {
        select {
        case <-notifier:
            break
        default:
            //do work
        }
    }
}


func MyRequestHandler(res http.ResponseWriter, req *http.Request) {
    notifier := res.(http.CloseNotifier).CloseNotify()
    MyServiceFunc(notifier)
    //write response...
}

最后,结合这两种方法的示例:

func MyRequestHandler(res http.ResponseWriter, req *http.Request) {

    notifier := res.(http.CloseNotifier).CloseNotify()
    ctx, cancel := context.WithCancel(req.Context())

    go func(closer <-chan bool) {
        <-closer //the notifer blocks until the send
        cancel() //explicitly cancel all go routines
    }(notifier)

    go MyServiceFunc(ctx)
    MyOtherServiceFunc(ctx)
    //write response...
}

1
投票

如果读取或写入连接时出现错误,或者当请求或响应标头指示应关闭连接时,每个连接的 Goroutine 将在从处理程序返回时退出。

处理程序可以使用从 Request.Context() 返回的 Context 检查关闭的连接。

© www.soinside.com 2019 - 2024. All rights reserved.