重试 – HTTP响应头后 – 它影响什么?
如果我想礼貌地拒绝网站上的服务,由于临时过载,HTTP响应503服务不可用似乎是合适的。 该规范提到用503发送一个Retry-after头。
有什么意思吗? Retry-After会影响到什么吗? 浏览器是否注意到它?
据我所知,没有浏览器注意到 Retry-after
标题。代理和caching可能,但是
显然,一些浏览器现在包含对Retry-After
某种级别的支持(虽然支持仍然是最好的)。 我并不完全相信在浏览器中这样做的好处, 一般来说,caching失败是一个坏主意。 但如果你知道什么时候你会再次接受请求,告诉客户不能伤害。 (如果你早于预期地回来,那么任何真正尊重标题的程序都应该假设 – 并且报告 – 该网站仍然在运行。)
最明显的好处是,似乎Googlebot(也可能是其他的蜘蛛)会关注标题,如果它在那里,可以防止一段时间的页面不索引。
尽pipe如此,如果增加一些微不足道的东西,你可以拿出一个合理准确的估计服务何时可用的方法。 尽pipe如此,我不build议你不要这样做。 无论如何,这只是一个build议,把错误的时间放在那里可能会导致更多的问题,而不是不包括标题。
Retry-After标题的当前状态
自从最初发布这个问题以来,客户端和服务器中Retry-After头的实现在最近几年中有所变化。 所以我想我会提供一个更新的答案。
首先,RFC 2616, 第14.37节Retry-After声明:
Retry-After response-header字段可与503(服务不可用)响应一起使用,以指示服务对于请求客户端来说预计不可用的时间。
…
两个使用的例子是
Retry-After: Fri, 31 Dec 1999 23:59:59 GMT Retry-After: 120
在后面的例子中,延迟是2分钟。
支持客户端和服务器软件
以下是各种软件中的Retry-After标题的代码库提交消息,通告和文档。
镀铬/铬
2012年11月22日的代码提交日志消息: 添加了检测超时和使用Retry-After HTTP标头 。
火狐浏览器
2012年3月27日的代码提交日志消息: 实现5xxs的处理,X-Weave-Backoff,Retry-After 。 此外,在Mercurial存储库中还有另外三个Retry-After标题 。
一个错误最初是在2004年1月6日提交的,标题为Retry-HTTP3发送响应后被忽略 。
Googlebot的
Google网站pipe理员中央博客有关处理网站停机的文章提到, Retry-After标题可用于确定何时重新抓取url 。
Bingbot / MSNBot会
找不到任何正式的Retry-After支持文档。 不过,在随机论坛中有一些提到在503响应中使用这个标题来扼杀微软的机器人。
Nginx的
add_header指令指出:
如果响应代码等于200,201,204,206,301,302,303,304或307,则将指定的字段添加到响应报头。
因此,要使用以下版本为503响应添加Retry-After标题:
-
1.7.4及更早版本,使用第三方模块,比如Headers More 。
-
1.7.5及更高版本,将
always
参数附加到add_header
指令。
阿帕奇
与Nginx不同的是,Apache 头文件并没有表明它不能在503响应中发送Retry-After头。 关于非2xx回应,文件陈述:
向本地生成的非成功(非2xx)响应(例如redirect)添加头,在这种情况下,只有总是对应的表被用于最终响应。
正如文件build议的,这是一个SO答案 ,它为503个答复设置了一个Retry-After头。
AskApache文章提供了其他configuration示例, 指导如何指示search引擎使用带有Retry-After标头的503响应返回 。
客户端testing
我写了一个Ruby服务器,它只是返回一个503响应,Retry-After头部设置为10秒,而一个包含随机数的主体。
require 'sinatra' get '/' do headers 'Content-Type' => 'text/plain', 'Retry-After' => '10' status 503 body rand(1000).to_s end
我访问了它:
- 使用Chromium 44,Firefox-ESR 38和Seamonkey 2.33的OpenBSD 5.8,
- 使用Chrome 47和Safari 6.1的Mac OSX 10.7.5,
- Windows 10使用Chrome 48,Firefox 41和Edge 25。
我期待这些浏览器在10秒后自动刷新URL并显示一个新的随机数。 但是,即使几分钟后,所有的浏览器都不会重试。 我尝试了更短,更长的Retry-After时期以及相同的结果。 服务器访问日志确认没有从这些浏览器的任何重试。
此外,在“重试后”时间段之前的“软”刷新会立即重新捕获URL。 因此,Retry-After标题不能用于节制“更新快乐”的用户。 我提到这一点是因为我在一些论坛上看到,这个头文件可以用来扼杀不耐烦的用户打击你的网站。
作为一个方面说明,对于“软”刷新在超时期限之前没有动作似乎是合乎逻辑的,但是“硬”或者高速caching绕过刷新将忽略任何超时并立即重新获取URL。
结论
在客户端和服务器上对Retry-After头的支持仍然看起来有点粗略。 尽pipe如此,如果configuration不难,为503个响应设置重试超时值是个好主意。
即使Googlebot是支持标题的唯一客户端,并且在超时期限后实际重试,它也可能会使您的页面不被删除索引 – 而不是404,500,502或504响应。
我认为这是一个鸡与鸡蛋的问题:没有浏览器目前实施重试 – 之后,因为没有网站打扰。 在我看来,继续作为服务发送给用户。 如果他们select的浏览器没有实现它,那么他们的浏览器就是不给他们有用的信息。 你做到了!
当要实现具有多个竞争实现的标准时,我总是试图遵守这些标准,而不是注意不同的实现(除非我特别试图模仿一个实现,比如cURLing,但是伪装我的头文件看起来像网页浏览器)。 否则,我们最终会达到事实上的标准,如果你还记得你不想要的IE浏览器霸主日!
如果你想在X时间后自动刷新,你可以发送一个
Refresh: 120; url=http://your_url.com
在PHP中:
header("Refresh: " .$retry_time."; url=". $url);
要刷新当前页面,您可以使用$_SERVER["REQUEST_URI"]
作为$ url。
我在不同版本的Opera,Firefox和Internet Explorer中testing了这个头文件。
这个头甚至用于刷新二进制内容像图像(但只有当直接加载或在框架中 – 一个IMG标签不能重新加载)。