Goroutine 已经根据请求在 Go Web 服务器中启动,但客户端断开连接,Web 服务器是否可以关闭该特定的 goroutine?
Goroutine already started in Go web server from request but client disconnects, is it possible for a web server to close that particular goroutine?
每当来自客户端的 Web 请求传入时,它都会生成一个 goroutine 来处理每个请求。如果客户端恰好断开连接,Web 服务器是否有可能关闭该特定 goroutine,或者该 goroutine 是否会在执行完所有代码后发现客户端已经断开连接?
如果读取或写入连接出错,或者当请求或响应 headers 指示应关闭连接时,per-connection goroutine 在 return 从处理程序退出.
处理程序可以使用 Context returned from Request.Context() 检查关闭的连接。
除了在读取或写入错误时从调用的处理程序退出 return - 执行的 go 例程不会自动处理清理更长的 运行 操作,但 Go 提供了很好的方法处理这个。
首先,如果你不熟悉context package - it is a powerful and idiomatic way to synchronize go routines with cancellation behavior, I highly recommend reading the blog Go Concurrency Patterns: 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 interface of which a 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...
}
每当来自客户端的 Web 请求传入时,它都会生成一个 goroutine 来处理每个请求。如果客户端恰好断开连接,Web 服务器是否有可能关闭该特定 goroutine,或者该 goroutine 是否会在执行完所有代码后发现客户端已经断开连接?
如果读取或写入连接出错,或者当请求或响应 headers 指示应关闭连接时,per-connection goroutine 在 return 从处理程序退出.
处理程序可以使用 Context returned from Request.Context() 检查关闭的连接。
除了在读取或写入错误时从调用的处理程序退出 return - 执行的 go 例程不会自动处理清理更长的 运行 操作,但 Go 提供了很好的方法处理这个。
首先,如果你不熟悉context package - it is a powerful and idiomatic way to synchronize go routines with cancellation behavior, I highly recommend reading the blog Go Concurrency Patterns: 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 interface of which a 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...
}