我正在使用Gin网络框架来提供Go API后台服务.在API端点的gin处理程序函数中,我正在启动Go routine 来运行一些后台任务.这些任务应该运行而不依赖于发送到客户端的响应.但是,我经常在子Go routine 中的数据库操作过程中遇到"上下文取消"错误,并且后台操作失败.
我无法创建一个新的上下文并将其作为gin上下文传递我需要的一些数据以及我需要重用的一些现有函数,预计有*gin.context
个参数.
我进行了一些调试,发现错误是由于子 routine 使用与父 routine (即处理程序本身)相同的*gin.context
而发生的.向客户端发送响应后,上下文被取消,从而导致数据库操作中出现错误.
我读到一个解决方案,其中说使用context.Background()
创建一个新的上下文并传递它.但我需要使用*gin.context
本身,否则我将不得不重写很多函数并复制一些数据.
我看到的另一个有希望的解决方案是建议使用*gin.context.Copy()
.在Copy()
的杜松子wine 文档中,它明确写道:
Copy返回当前上下文的副本,该副本可以在请求范围之外安全使用.
当上下文必须传递给goroutine时,必须使用这一点.
我原以为Copy()
个能正常工作.但即使我传递了复制的上下文,我也会得到相同的上下文取消错误.
以下是我所做的:
func SendApiResponseToClient(c *gin.Context) {
response := doSomeOperations(c)
newContext := c.Copy()
go doSomeBackGroundOperations(newContext, response)
sendResponse(response)
}
这doSomeBackGroundOperations()
个函数有一些DB操作,这就是失败的原因.
为了确认上下文以外的所有其他内容都正常,我在向客户端发送API响应以等待后台操作完成之前添加了一秒的超时.在这种情况下,我没有遇到任何错误,一切都按预期进行.
我还在gin-gonia/gin存储库中发现了一些github开放问题,如下所示:
- https://github.com/gin-gonic/gin/issues/3166
- https://github.com/gin-gonic/gin/issues/3137
- https://github.com/gin-gonic/gin/issues/3554
我相信这些问题在某种程度上与我面临的问题有关.但是,我仍然找不到明确的解决方案.
任何可能对我有帮助的建议都会非常感激. 谢谢