我正在尝试设置一个计时器来计算我的服务器完成请求所需的时间,我希望计时器在响应的最后一个字节发送后停止。
我发现http服务器只会在处理函数返回后发送响应。
有没有办法在发送响应后添加回调?
或者是否有更好的方法来计算从请求的第一个字节进入到响应的最后一个字节字节所需的时间?
答案 0 :(得分:5)
更简单但不那么准确的方法是使用中间件来包装你的处理函数。
func timer(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
h.ServeHTTP(w, r)
duration := time.Now().Sub(startTime)
})
}
然后
http.Handle("/route",timer(yourHandler))
这更准确地说是处理请求和形成响应所花费的时间,而不是写入之间的时间。
如果您确实需要更准确的持续时间,那么您希望更改的代码部分位于net/http
包中。
它将在here附近。
突出显示的行go c.serve(ctx)
是生成提供请求的go例程的地方。
for {
rw, e := l.Accept()
if e != nil {
if ne, ok := e.(net.Error); ok && ne.Temporary() {
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay)
time.Sleep(tempDelay)
continue
}
return e
}
tempDelay = 0
c := srv.newConn(rw)
c.setState(c.rwc, StateNew) // before Serve can return
go func(){ startTime := time.Now() c.serve(ctx) duration := time.Now().Sub(startTime) }()
}
注意:请求实际上是在net.Conn
l.Accept()
内的某个地方写的,但突出显示的点是我们可以在代码中的相同范围内获得大致开始时间和结束时间的唯一地方。