go - 如何在 http 处理程序中运行 x 秒
问题描述
我想运行我的函数InsertRecords
30 秒并测试在给定时间内可以插入多少条记录。
如何InsertRecords
在 x 秒后停止处理,然后从我的处理程序返回结果?
func benchmarkHandler(w http.ResponseWriter, r *http.Request) {
counter := InsertRecords()
w.WriteHeader(200)
io.WriteString(w, fmt.Sprintf("counter is %d", counter))
}
func InsertRecords() int {
counter := 0
// db code goes here
return counter
}
解决方案
取消和超时通常使用context.Context
.
虽然这个简单的示例可以单独使用通道完成,但使用此处的上下文使其更加灵活,并且还可以考虑客户端断开连接。
func benchmarkHandler(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second)
defer cancel()
counter := InsertRecords(ctx)
w.WriteHeader(200)
io.WriteString(w, fmt.Sprintf("counter is %d", counter))
}
func InsertRecords(ctx context.Context) int {
counter := 0
done := ctx.Done()
for {
select {
case <-done:
return counter
default:
}
// db code goes here
counter++
}
return counter
}
这将运行至少 30 秒,返回完整的数据库迭代次数。如果你想确保处理程序总是在 30 秒后立即返回,即使 DB 调用被阻塞,那么你需要将 DB 代码推送到另一个 goroutine 并让它稍后返回。最短的示例是使用与上述类似的模式,但同步访问计数器变量,因为它可以在返回时由 DB 循环写入。
func InsertRecords(ctx context.Context) int {
counter := int64(0)
done := ctx.Done()
go func() {
for {
select {
case <-done:
return
default:
}
// db code goes here
atomic.AddInt64(&counter, 1)
}
}()
<-done
return int(atomic.LoadInt64(&counter))
}
有关生产者和超时的示例,请参阅@JoshuaKolden 的答案,它也可以与现有的请求上下文结合使用。
推荐阅读
- java - 如何重置系统属性 javax.net.ssl.trustStorePassword?
- xml - Progress PRODATASET - 在 10.1C 中是否有等效的父 ID 字段?还是替代方案?
- python - 我无法使用 python 正确调整谷歌电子表格正文
- python - 如何在 ECDF 图上使用标记
- windows - 将 .ps1 转换为 .bat 不会导致 cmd.exe 达到最大字符长度 - 但为什么呢?
- javascript - 如何在更改输入字段上更改图表 JS 标题文本?
- questdb - QuestDB:如何配置内存使用?
- javascript - 数据表的搜索框长度重叠
- prism - Prism 未注册的默认区域适配器
- cucumber - 它是否支持仅根据被调用功能文件中的标签执行选定的场景?