我想设置一个计时器来统计服务器完成请求所需的时间,并希望计时器在响应的最后一个字节发送后停止。我发现HTTP服务器只会在处理程序函数返回后才发送响应。是否有办法在响应发送后添加回调?还是有更好的方法来计算从请求的第一个字节到响应的最后一个字节所花费的时间?
更简单但不如精确的方法是使用中间件来包装您的处理程序函数。
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
包中。
大约在这里。
高亮显示的行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
中的某个地方被写入的,但是高亮显示的点是代码中可以同时获得大约开始时间和结束时间的唯一位置。