【发布时间】:2021-08-24 03:22:22
【问题描述】:
希望您收到这条消息时身体健康。
所以在我正在研究的 golang 程序中存在这个错误,代码库中的这种阻塞方法 stdCopy.StdCopy() 会导致一切挂起。出现这个问题是因为 Docker 不断地向 Stdcopy 阻塞方法发送信息,而阻塞方法只有在发送 EOF 时才能停止运行。 StdCopy 接受 ReadCloser 类型参数,这是阻塞方法从 Docker 读取信息的方式。在程序进入阻塞方法之前,也会使用 Goroutines。换句话说,StdCopy 阻塞方法在一个新线程中运行,而主线程与它并行运行。但是,阻塞方法现在阻塞了新线程,并不能解决问题。
我试图防止这个问题是在主线程中显式关闭这个 ReadCloser,然后发送一个 EOF 到持有 StdCopy 阻塞方法的新线程,以通过超时错误强制停止它。这应该阻止整个程序挂起,因为阻塞方法是它挂起的原因。我通过存储我打开的每个 ReadCloser 的映射来做到这一点,然后以特定方法手动将它们全部关闭,该方法旨在在我们的程序停止时运行。我不确定关闭 ReadCloser 接口是否会自动发送 EOF(我检查了 golang 文档,但找不到任何信息:https://golang.org/pkg/io/#ReadCloser)。
我决定要明确地向 ReadCloser 发送 EOF 以防万一。但是,我该怎么做呢?我正在考虑使用我的通道知识并通过通道将 io.EOF 传递到运行阻塞方法的 go-routine 中。但是 io.ReadCloser 不是通道类型,所以我不能这样做。
关闭 io.ReadCloser 会自动发送 EOF 吗?如果没有,您将如何将 EOF 发送到 io.ReadCloser 以便阻止方法停止运行?
如果我的解释中有任何不合理之处,请告诉我,您希望我澄清一下。由于我对 golang 还比较陌生,因此在您认为我有错误的地方也可以随时纠正我。
非常感谢您抽出宝贵时间,如有任何想法请告诉我!
----- 编辑-----
以下是我迄今为止编写的一些代码,以便更好地理解:
//Closing all of the ReadClosers opened to prevent blocking
for k := range streamer.inputReadClosers {
(*k).Close()
//(*k) <- io.EOF //does not work since io.ReadCloser is not of channel type
}
所以在某些情况下,streamer 只是一个结构,它包含一个属性调用 inputReadClosers,它是所有打开的 ReadClosers 的指针映射。然后我显式关闭 ReadCloser,然后目标是手动向该 ReadCloser 发送 EOF。
一些关于 ReadCloser 是如何初始化的信息:
所以我有一个文件,该文件的方法具有以下方法标头func (streamer *LogStreamer) StartStreamingFromDockerLogs(input io.ReadCloser) error。当我检查 StartStreamingFromDockerLogs(...) 在其他文件中使用的实例时,我发现传递了一个 readcloser 变量,并且 readcloser 变量以下列方式初始化:readCloser, err := dockerManager.GetContainerLogs(.....three parameters here…..)。
【问题讨论】:
-
所以 io.ReadCloser 是一个包含 Reader 接口和 Closer 接口的接口。 Reader 和 Closer 接口分别持有 Read 和 Close 方法。我在我的 C 系统编程课程中了解了管道,我认为规则是,如果在管道的写入端关闭并且已从管道读取所有数据时,读取调用返回 0。但我认为我不能在这里做到这一点,因为 io.ReadCloser 至少从我对文档的理解来看不是管道:golang.org/pkg/io/#ReadCloser
-
@Penelope Stevens 很抱歉没有澄清我上面的评论是针对哪个用户的(它是针对 Cerise 的,感谢 Cerise 的评论!)。但是,感谢@Penelope Stevens 关于如何确定具体类型的评论!我尝试了您在上面发送的 fmt.Printf() 语句,并得到以下信息:
my io.ReadCloser is a *http.bodyEOFSignal -
@Penelope Stevens 我在上面的问题中添加了一些代码,以尝试更好地理解我的问题。你是对的,我认识到我的问题看起来像 XY 问题。感谢您指出这一点,让我试着澄清一下,以便我试图理解问题,而不是仅仅找到问题的解决方案。
-
@Penelope Stevens 所以我有一个文件,该文件有一个方法,其方法标题为
func (streamer *LogStreamer) StartStreamingFromDockerLogs(input io.ReadCloser) error。当我检查在其他文件中使用StartStreamingFromDockerLogs(...)的实例时,我发现传递了一个 readcloser 变量,并且 readcloser 变量以下列方式初始化:readCloser, err := dockerManager.GetContainerLogs(.....three parameters here…..)。也许GetContainerLogs(....)引起了问题?我会调查并随时通知您。
标签: docker go eof blocking reader