【发布时间】:2019-04-27 19:19:24
【问题描述】:
假设客户端通过http上传大量图像,互联网连接速度很慢,他打开与服务器的连接,开始写入数据,但由于网络问题突然失去了这个连接。如果尚未调用处理程序函数,我如何在服务器上检测到这一点。我找到的解决方案是检查连接状态。但问题是它不可扩展,因为很多 goroutine 会与全局变量交互。还有更优雅的解决方案吗?
package main
import (
"fmt"
"log"
"net"
"net/http"
)
// current state of connections
var connStates = make(map[string]http.ConnState)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Println("got new request")
fmt.Println(connStates)
})
srv := &http.Server{
Addr: ":8080",
ConnState: func(conn net.Conn, event http.ConnState) {
if event != http.StateClosed {
connStates[conn.RemoteAddr().String()] = event
} else {
if connStates[conn.RemoteAddr().String()] == http.StateActive {
fmt.Println("client cancelled request")
}
delete(connStates, conn.RemoteAddr().String())
}
},
}
log.Fatal(srv.ListenAndServe())
}
【问题讨论】:
-
您希望对连接状态做什么?也许如果我们对您想用它做什么有更好的想法,我们可能会有一些更好的想法。至于你有什么,我要做的唯一改进是实现
sync.Map(golang.org/pkg/sync/#Map) 而不是常规的map。 -
我对连接状态做了什么?如您所见,我有一个全局地图来跟踪所有连接,远程地址作为键(因为它对于每个连接都是唯一的)和连接状态作为值。所以我向服务器添加了
ConnState回调,每次连接状态改变时都会调用它,使用它我支持这个连接映射。最重要的是,检测失败的连接。如您所见,我检查当前状态是否已关闭并且前一个状态是否已打开-http 连接失败,因为没有http.StateActive状态。 -
我要问的是你最终想用这些信息做什么?你只是记录它吗?您是否想根据状态执行时间敏感操作,或者您想要做的事情可以延迟一点?我可以看到您目前只是在登录。
-
是的,我只是想记录这样的事件。