在ASP.NET响应中,我该如何显式或隐式地设置传输编码为分块传输编码?

15

2
在Java Servlet中,如果在写入/刷新流之前设置Content-Length头,则它将被隐式设置为Transfer-Encoding: chunked,并且数据将以块的形式发送。请查看ASP.NET是否存在类似的行为。 - BalusC
1
在ASP.NET中,它会隐式地缓存输出,我想是这样的。HttpResponse上有一个BufferOutput属性。但是该属性的文档完全不足。http://msdn.microsoft.com/en-us/library/system.web.httpresponse.bufferoutput.aspx 它没有说明该属性如何影响Transfer-Encoding或任何其他有趣的问题。 - Cheeso
4个回答

23
TL;DR: 指定content-length是实现快速首字节的最佳方式;这样可以允许在TCP层而非HTTP层进行分块。如果不知道content-length,将context.Response.BufferOutput设置为false将使用分块传输编码将输出随着写入输出流而发送。
为什么要设置Transfer-Encoding: chunked?分块传输本质上是一种解决方案,允许发送内容长度未知的文档。然而,默认情况下,ASP.NET会缓冲整个输出,因此确实知道总体内容长度。
当然,HTTP是建立在TCP之上的,背后的TCP会将即使是单一的HTTP响应拆分成数据包进行“分块”传输——这意味着如果您事先指定了content-length并禁用了输出缓冲,就可以获得最佳的延迟时间,而无需使用HTTP级别的分块。因此,当您知道content-length时,不需要HTTP级别的分块即可提供快速的首字节。
虽然我不是HTTP专家,但我已经实现了一个简单的流媒体服务器,支持查找、动态压缩、缓存等,并且我对快速首字节的相关性有相当的了解——如果您知道content-length,则分块通常是次优选项,这几乎肯定是为什么ASP.NET不允许您手动设置它的原因——这是不必要的。
但是,如果在传输前不知道HTTP内容长度且缓冲太昂贵,则关闭输出缓冲,并且服务器将出于必要而使用分块传输编码。

服务器何时使用分块传输编码? 我刚刚进行了测试,发现如果将context.Response.BufferOutput设置为false且未设置内容长度,则响应会以分块方式进行;在我进行的一个完全非科学的快速测试中,一个1.7MB的gzip xml文档的响应会比不使用分块编码时大1-2%。由于gzip依赖于上下文来减少冗余,我原本预计压缩比率会更低,但似乎分块并不一定会极大地降低压缩比率。

如果你查看反编译的框架代码,似乎传输编码确实会根据需要自动设置 - 即如果关闭缓冲且不知道内容长度且响应是HTTP/1.1请求,则使用分块传输编码。但是,如果服务器是IIS7且这是一个工作线程请求(?集成模式?),则代码将分支到一个本机方法 - 可能具有相同的行为,但我无法验证。


8
@Eamon,分块传输不是一种变通方法,它是一种功能。我认为你知道这一点,但当第一个响应字节被写入时,如果内容的大小未知且可能很大,则尝试在发送整个响应之前缓存整个响应将是不正确、潜在危险且性能非常差的。关于使用BufferOutput-您可以引用您“刚刚检查”的来源吗?您是指您测试了吗?我也观察到了那种行为。我正在寻找的是有文档描述的信息。Response.Flush()做到了吗?等等。 - Cheeso
1
@Eamon - 你似乎认为应用程序永远不应该关心缓冲或分块传输的发生。但这并不是真的。假设要传输的数据很大,而且大小已知。假设应用程序知道响应将恰好为1GB。对于应用程序来说,明确确保没有缓冲发生是有意义的,这意味着使用分块编码。你似乎忽略了这种可能性。或者考虑到首字节时间,使用分块传输比不使用分块传输更小。这只是两个例子。重点是,有很好的理由明确地利用HTTP的这个特性。 - Cheeso
1
不,这不是真的——一个应用程序可能会关心它是否已缓冲,但分块传输编码只是应用程序变为“未缓冲”状态的一种方式而已。如果您明确设置了内容长度并关闭了缓冲,则仍然不会有分块传输,但将具有低延迟——事实上,它将比分块传输编码略快,因为总响应大小将更小。因此,我并不是说应用程序不应关心变成未缓冲状态,我是说应用程序不应关心如何实现未缓冲状态——对于低延迟,不需要使用分块传输编码! - Eamon Nerbonne
因此,您不一定需要HTTP级别的分块来提供快速的第一个字节。这很愚蠢。我需要它用于特定场景,要么回答问题,要么不要浪费时间! - DATEx2
关于您粗体字的第一行...如果您在TCP层面上依赖分块,那么您的客户端将无法快速获取第一个字节,因为客户端也在与服务器进行HTTP通信。在这种情况下,客户端的TCP将等待完整响应,然后将其封装为HTTP响应发送给客户端。 - mickeymoon
显示剩余7条评论

0
似乎你需要设置IIS。在元数据中,IIS 6有一个名为AspEnableChunkedEncoding的属性,你可以在MSDN上查看IIS 7的映射,链接为http://msdn.microsoft.com/en-us/library/aa965021(VS.90).aspx。 这将使你能够在头文件中设置TRANSFER-ENCODING: chunked。我希望这可以帮到你。

谢谢。但是AspEnableChunkedEncoding默认为true,所以这不是问题。此外,这并没有回答关于在ASPNET中使用分块编码的具体问题。 - Cheeso

0

Response.Buffer = False

这将设置HTTP头“Tranfer-Encoding: Chuncked”,并在每次调用response.write时发送响应。


0

尽管您将缓冲区设置为false并留空内容长度,但需要确保已禁用IIS7的“动态内容压缩”功能以使分块响应正常工作。此外,客户端浏览器应至少具有HTTP 1.1 .. 对于HTTP 1.0,分块模式将无法工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接