【问题标题】:Why should I make a copy of a context for goroutines inside handlers?为什么我应该为处理程序内部的 goroutines 复制上下文?
【发布时间】:2023-02-06 07:21:25
【问题描述】:

我最近开始用 Go 重写我的一些 Python 服务以加快它们的速度,并看到了 gin 文档的这一部分: https://github.com/gin-gonic/gin#goroutines-inside-a-middleware

所以我理解说明,但我试图理解为什么?制作副本的意义是什么,如果我不为处理程序中的 goroutines 制作上下文副本,会引入什么问题?

【问题讨论】:

  • 检查代码,copy 并没有包含原始上下文的所有值,而只是一些。乍一看,例如Lock 未被复制,响应作者被替换为 copy。两者都是有道理的,因为 go 例程可以随时完成,即使在处理和回答请求之后很久。原回复writer可能已经关闭,原lock已经解锁。或者相反,go 例程可能会提前完成,过早解锁 lock 或关闭响应编写器。其他跳过的字段可能会出现类似的问题。

标签: go go-gin


【解决方案1】:

Gin-gonic 本身是异步的,这使它很棒。 如果您在处理程序中使用并发,那么您很可能会遇到上下文时的情况,即结构

  • 已过时,因为它保存了每个请求的数据(参数、受互斥锁保护的密钥)

  • 空,这将导致回退到默认上下文

这是它的样子:

type Context struct {
writermem responseWriter
Request   *http.Request
Writer    ResponseWriter

Params   Params
handlers HandlersChain
index    int8
fullPath string

engine       *Engine
params       *Params
skippedNodes *[]skippedNode

// This mutex protects Keys map.
mu sync.RWMutex

// Keys is a key/value pair exclusively for the context of each request.
Keys map[string]any

// Errors is a list of errors attached to all the handlers/middlewares who used this context.
Errors errorMsgs

// Accepted defines a list of manually accepted formats for content negotiation.
Accepted []string

// queryCache caches the query result from c.Request.URL.Query().
queryCache url.Values

// formCache caches c.Request.PostForm, which contains the parsed form data from POST, PATCH,
// or PUT body parameters.
formCache url.Values

// SameSite allows a server to define a cookie attribute making it impossible for
// the browser to send this cookie along with cross-site requests.
sameSite http.SameSite

}

为了预见此类问题和竞争条件 - 只要您的处理程序使用 go concurrency,您就必须使用 Copy

这是来自 gin-gonic 存储库的引用:

// Copy returns a copy of the current context that can be safely used outside the request's scope.
// This has to be used when the context has to be passed to a goroutine.

【讨论】:

    猜你喜欢
    • 2010-09-28
    • 2015-01-16
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    相关资源
    最近更新 更多