【发布时间】:2017-09-14 16:39:19
【问题描述】:
我有一个客户端应用程序,它将 http 响应的全部内容读入缓冲区并对其执行一些处理:
body, _ = ioutil.ReadAll(containerObject.Resp.Body)
问题在于该应用程序在嵌入式设备上运行,因此太大的响应会填满设备 RAM,导致 Ubuntu 终止该进程。
为了避免这种情况,如果文档太大,我会检查 content-length 标头并绕过处理。然而,一些服务器(我在看你,微软)在没有设置内容长度的情况下发送非常大的 html 响应并导致设备崩溃。
我能看到解决此问题的唯一方法是将响应正文读取到一定长度。如果达到此限制,则可以创建一个新的读取器,它首先流式传输内存缓冲区,然后继续从原始 Resp.Body 读取。理想情况下,我会将这个新读取器分配给 containerObject.Resp.Body,这样调用者就不会知道其中的区别。
我是 GoLang 的新手,不知道如何编写此代码。任何建议或替代解决方案将不胜感激。
编辑 1:调用者需要一个 Resp.Body 对象,因此解决方案需要与该接口兼容。
编辑 2:我无法解析文档的小块。要么处理整个文档,要么将其原封不动地传递给调用者,而不将其加载到内存中。
【问题讨论】:
-
不设置
Content-Length是相当标准的,因为大多数大型响应将使用分块编码。 -
为什么要尝试有条件地缓冲部分响应,而不是始终使用
io.Reader接口? -
为了进一步推荐@JimB,我会开始看这个:stackoverflow.com/questions/31857891/…这也可能有用:tip.golang.org/pkg/encoding/json/#Decoder.Token
-
从 Resp.Body 读取任何内容后,您必须将其缓冲在内存中(如果您想对它做任何事情,那就是),因为您正在从网络流中读取。这意味着大响应被完全读入内存并使设备崩溃。现在另一部分是这个函数的调用者期望 Resp.Body 是完整的——就像它是直接从 http 对象中读取的一样。所以我需要向它发送一些与该对象一样的东西,但不会尝试将大型文档完全读入 RAM。
-
感谢克里斯蒂安的建议。不幸的是,我不能一次处理小批量的文档。这是一个全有或全无的事情。如果我看不到整个文档,那么我想原封不动地传递它。我将编辑问题以反映这一点。
标签: go