http HEAD与GET性能比较

159

我正在搭建一个REST Web服务,只需要尽快回答YES或NO。

设计一个HEAD服务似乎是最好的方法,但我想知道是否真的比进行GET请求节省时间。

我认为我可以通过不在我的服务器上打开/关闭正文流来节省大约1毫秒的时间。由于要返回的字节数非常少,那么在传输中,IP包数量上我能获得任何时间吗?

编辑:

进一步解释情况:

  • 当REST服务处于活动状态时,我有一组执行某些过程的REST服务。
  • 我还有另一个REST服务指示所有这些第一服务的状态。

由于最后一个服务将被很多客户端频繁调用(每5毫秒预计调用一次),我想知道使用HEAD方法是否可以作为一种有价值的优化方式?响应正文中返回了约250个字符。至少,HEAD方法可以节省这250个字符的传输,但会有什么影响呢?

我尝试对两种方法(HEAD vs GET)之间的差异进行基准测试,运行1000次调用,但没有看到任何收益(< 1ms)...


3
这也取决于您在服务器端使用的方法。通常情况下,处理GET请求或HEAD请求可能需要相同的服务器时间,因为服务器可能需要知道最终正文来计算“Content-Length”头值,这是HEAD请求响应中的重要信息。 除非有其他更优化的服务器端方法,否则唯一的好处就是节省带宽,客户端不必解析响应正文。因此,基本上优化收益取决于服务器和客户端实现。 - itsjavi
8个回答

225

一个符合REST标准的URI应该代表服务器上的一种"资源"。这些资源通常被存储为数据库中的记录或文件系统上的文件。除非资源很大或在服务器上检索资源很慢,否则使用GET而不是HEAD可能不会带来明显的性能提升。这是因为检索元数据与检索整个资源所需的时间可能相同。

虽然您可以同时实现这两个选项并进行基准测试以查看哪个更快,但是与其微观优化,不如专注于设计理想的REST接口。干净的REST API通常比可能快或可能不快的API更有价值。我并不反对使用HEAD,只建议在正确的设计情况下使用它。

如果您需要的信息确实是关于资源的元数据,并且可以在HTTP头中表示清楚,或者想要检查资源是否存在,那么HEAD可能是一个不错的选择。

例如,假设您要检查资源123是否存在。 200表示"是",404表示"否":

HEAD /resources/123 HTTP/1.1
[...]

HTTP/1.1 404 Not Found
[...]

然而,如果您从REST服务中需要的“yes”或“no”是资源本身的一部分,而不是元数据,您应该使用GET


很棒的答案!我有一个问题:如果我想将它用作“touch”命令,在服务器上更新帖子的查看次数,该怎么办呢?帖子数据已经通过普通的/posts调用进行了检索,因此我只想在用户以某种方式与帖子交互后更新查看次数。 - aalaap
1
@aalaap 如果您要更新“HEAD”请求的视图计数器,则也应该为“GET”请求这样做。使用“GET”或“HEAD”的决定最终取决于HTTP客户端。您的服务器应该对两种请求类型采取相同的行为,除非在响应“HEAD”时没有响应正文。至于是否将此视为实现视图计数器之类的东西的好方法,我不确定。 - Andre D
@AndreD - 通过head返回资源的标题并不是“kludgey”,“unclean”或“stuffing data” - 在OPs问题中,他们想知道有关活动状态的信息 - 因此,例如 - 返回“404”表示未找到或“200”表示已找到可能是完全可以接受的,还可以使用“304” Not Modified以及Etag请求头,这可能是一个很好的解决方案 - 允许客户端仅检查自上次客户端检查以来是否更改了活动状态。所有这些都清楚地说明了HTTP协议的设计。 - Fraser
2
@Siddhartha,这通常是正确的,但并非总是如此。当使用“Transfer-Encoding:chunked”时,可以省略Content-Length。即使有Content-Length,服务器也可以获取用于标头的资源大小和其他元数据而不必检索实际资源。也许这些元数据甚至在内存中缓存以便快速访问。这都是非常具体实现的事情。 - Andre D
1
@AndreD 无法要求更详细的答案了,谢谢! - Siddhartha
显示剩余6条评论

54
当我在查找与请求者提出的相同问题时,我发现了这个回复。我也在http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html上找到了这个回复:
块引用: HEAD方法与GET方法相同,只是服务器在响应中不能返回消息正文。响应HEAD请求的HTTP头中包含的元信息应与响应GET请求发送的信息相同。此方法可用于获取有关所请求实体的元信息,而无需传输实体正文本身。此方法通常用于测试超文本链接的有效性、可访问性和最近修改。
对于请求者的问题,正确答案似乎取决于REST协议所代表的内容。例如,在我的特定情况下,我的REST协议用于检索相当大(超过10K)的图像。如果我有大量这样的资源正在不断检查,并且考虑到我使用请求标头,则使用HEAD请求是符合w3.org建议的。

35

GET获取头部和正文,HEAD仅获取头部。哪个更快不应该是一个观点问题。我不理解上面得到赞同的答案。如果您正在寻找META信息,请选择HEAD,这是为此目的而设计的。


好的,当我使用 HEAD 方法时,我的服务器会发送 404 错误码,当我使用 GET 方法时,我会收到 200 状态码。所以你描述的这种差异是不正确的,这也可能取决于应用程序。 - Rohlik
6
@Rohlik 你的服务器肯定有问题。 - Peter Moses
@Rohlik:如果您的服务器没有响应HEAD请求,也就是说,在您拥有GET请求的特定URL上没有HEAD端点,则它将为HEAD返回$)$,并为GET返回200。 - Ricardo
@Viktor,从简单的性能角度来看,你是正确的。然而,你可能忽略了讨论非常迅速地进入了语义和“应该 vs 可以”的范围。忽略语义会导致 PUT 和 POST 之间不断混淆,或者更深入的 GET body 讨论。良好的语义会得到赞同。唯一关注性能,就不那么重要了。 - Ricardo

24
我强烈反对这种方法。

RESTful服务应该尊重HTTP动词语义。GET动词用于检索资源的内容,而HEAD动词不会返回任何内容,可以用来检查资源是否更改、了解其大小或类型、检查其是否存在等等。

请记住:过早优化是万恶之源。


13

HEAD 请求与 GET 请求非常相似,只是响应的正文为空。当您只需要有关文件的元数据但不需要传输所有文件数据时,可以使用此类型的请求。


当我使用HEAD方法时,我的服务器会发送404错误,而当我使用GET方法时,则会收到200的响应。因此,你所描述的差异是不正确的,这也可能取决于应用程序。 - Rohlik
4
可能是您的服务器没有配置头请求,它只接受GET请求。 - Shadab Ali

7

使用HEAD请求而不是GET请求,不会对您的性能产生太大影响。

此外,如果您想使其符合RESTful规范并且需要获取数据,请使用GET请求而不是HEAD请求。


1
我不理解你所说的“body stream 开/关”的问题。响应体将通过与HTTP响应头相同的流传输,并且不会创建第二个连接(顺便说一下,这需要3-6毫秒左右)。这似乎是对某些事情进行了过早的优化尝试,但实际上并没有产生显著甚至可以测量的差异。真正的区别在于符合 REST 的规范,推荐使用 GET 获取数据。因此,我的回答是否定的:如果有意义,请使用 GET,使用 HEAD 不会带来性能上的收益。

假设内容大小为100MB,那么头信息的大小肯定小于内容。当我们通过GET或HEAD方法请求该资源时,你认为它们之间没有性能差异吗? - Mohammad Afrashteh
3
原文:The OP stated 250 chars in the body of the response. Not 100MB. That’s a different question altogether.翻译:原帖中指出回复正文的长度为250个字符,不是100MB。这是完全不同的问题。 - smassey
对于大型资源,比如图像/视频/音频存储,您可以使用HEAD方法来检查信息,而无需下载100MB或更多的内容来获取信息。 - undefined

0
你可以轻松地制作一个小测试来自行测量性能。我认为性能差异将是可以忽略不计的,因为如果您在正文中只返回“Y”或“N”,那么它只是一个附加到已经打开的流的单个额外字节。
我也会选择使用GET,因为这更正确。您不应该在HTTP标头中返回内容,只应该返回元数据。

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