上下文
Overview
Go驾驶员使用Go标准库中的 上下文包 ,允许应用程序为任何阻塞方法调用发出超时和取消信号。阻塞方法依赖于外部事件(例如网络输入或输出)来执行其任务。
阻塞方法的一个示例是 InsertOne()
方法。如果要在 10 秒内对 Collection
执行插入操作,可以使用带超时的上下文。如果操作未在超时时间内完成,该方法将返回错误。
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() client.Database("db").Collection("items").InsertOne(ctx, bson.D{{"x",1}})
如果传递到操作中的上下文没有截止时间,您可以在Timeout
上设立Client
选项,操作会从此设置中获取超时规范。要学习;了解有关使用单一超时设置的更多信息,请参阅《连接选项》指南中的 单一超时设置。
到期
当操作超过超时时间或被取消时,驱动程序会认为上下文已过期。驱动程序使用 Done()
方法检查上下文过期情况。
以下各部分介绍了驱动程序检查过期的时间和方式。
服务器选择
如果驱动程序无法为操作选择服务器,则可能会阻止方法调用。
在这种情况下,驱动程序会循环运行,直到找到可用于该操作的服务器为止。每次迭代后,如果上下文已过期或选择进程花费的时间超过 serverSelectionTimeoutMS
设置,则驱动程序会返回服务器选择超时错误。
如要进一步了解驱动程序如何选择服务器,请参阅服务器选择算法。
连接签出
如果没有可用的连接可供检出,驱动程序可能会阻止方法调用。
选择服务器后,驱动程序会尝试从服务器的连接池中获取连接。如果 Context 在获取连接时过期,则该方法将返回超时错误。
连接建立
如果必须创建新连接,驱动程序可能会阻塞方法调用。
当驱动程序创建新连接以执行操作时,“上下文”会为建立过程设置超时时间。驱动程序会将超时时间设置为“上下文”过期时间或连接超时时间(以较短者为准)。
以下示例将连接超时设置为 1 秒,将 Context 截止时间设置为 2 秒。由于连接超时时间较短,所以建立过程在 1 秒后就会过期。
opts := options.Client() opts.SetConnectTimeout(1*time.Second) client, err := mongo.Connect(opts) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() client.Database("<db>").Collection("<collection>").InsertOne(ctx, bson.D{{"x",1}})
套接字读写
当驱动程序检索操作的连接时,会将套接字的读取或写入截止时间设置为“上下文”截止时间,或套接字超时时间(以较短者为准)。
如果在执行 Read()
或 Write()
方法后、截止日期前取消“上下文”,驱动程序的行为会因版本而异。
当 Read()
或 Write()
方法正在进行时,驱动程序会生成一个单独的 goroutine 来侦听上下文取消。如果 goroutine 检测到取消,则会关闭连接。待处理的 Read()
或 Write()
方法返回一个错误,驱动程序将用 context.Canceled
错误重写该错误。
重要
在 1.5.0 之前的版本中,驱动程序不会检测上下文取消,而是等待 Read()
或 Write()
方法返回。