Retry-After是鲜为人知的HTTP响应标头。 让我引用RFC 2616(HTTP 1.1规范)的相关部分:

14.37重试后

Retry-After响应标头字段可与503服务不可用 )响应一起使用,以指示请求该客户端的服务预计无法使用多长时间。 该字段也可以与任何3xx(重定向)响应一起使用,以指示在发出重定向请求之前,要求用户代理等待的最短时间。 该字段的值可以是响应日期之后的HTTP日期或整数秒(十进制)。

Retry-After  = "Retry-After" ":" ( HTTP-date | delta-seconds )

其用法的两个示例是:

Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
Retry-After: 120

在后一个示例中,延迟为2分钟。

尽管具有3xx响应的用例很有趣,尤其是在最终一致的系统中(“ 您的资源将在2秒内在此链接下可用 ),但我们将重点放在错误处理上。 通过将Retry-After添加到响应服务器,服务器可以在客户端再次可用时提供提示。 有人可能会争辩说,服务器几乎不知道何时将其重新联机,但是在几种有效的用例中,可以通过某种方式推断出这种知识:

  • 计划的维护–这很明显,如果您的服务器在计划的维护窗口内关闭,则可以从代理发送Retry-After ,并提供准确的回叫时间。 如果客户理解并尊重此标头,客户当然不会更早地重试
  • 队列/线程池已满-如果您的请求必须由线程池处理且已满,则可以估计何时可以处理下一个请求。 这需要绑定队列(请参阅: ExecutorService – 10个技巧和窍门 ,第6点),并粗略估计处理一项任务需要多长时间。 有了这些知识,您可以估计何时可以在不排队的情况下为下一个客户提供服务。
  • 断路器打开–在Hystrix中,您可以查询
  • 下一个可用令牌/资源/任何

让我们关注一个非平凡的用例。 假设您的Web服务由Hystrix命令支持:

private static final HystrixCommand.Setter CMD_KEY = HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("REST")).andCommandKey(HystrixCommandKey.Factory.asKey("fetch"));@RequestMapping(value = "/", method = GET)
public String fetch() {return fetchCommand().execute();
}private HystrixCommand<String> fetchCommand() {return new HystrixCommand<String>(CMD_KEY) {@Overrideprotected String run() throws Exception {//...}};
}

这可以按预期工作,如果命令失败,超时或断路器打开,客户端将收到503。但是,在断路器的情况下,我们至少可以估计重新闭合电路需要多长时间。 不幸的是,没有公共API可以告诉您在发生灾难性故障时确切的电路将保持断开状态多长时间。 但是我们知道断路器默认保持断开状态多长时间,这是一个很好的最大估计值。 当然,如果基础命令不断失败,电路可能会保持断开状态。 但是Retry-After不能保证服务器会在给定的时间运行,这只是客户端停止尝试的提示。 以下实现很简单,但是很糟糕:

@RequestMapping(value = "/", method = GET)
public ResponseEntity<String> fetch() {final HystrixCommand<String> command = fetchCommand();if (command.isCircuitBreakerOpen()) {return handleOpenCircuit(command);}return new ResponseEntity<>(command.execute(), HttpStatus.OK);
}private ResponseEntity<String> handleOpenCircuit(HystrixCommand<String> command) {final HttpHeaders headers = new HttpHeaders();final Integer retryAfterMillis = command.getProperties().circuitBreakerSleepWindowInMilliseconds().get();headers.set(HttpHeaders.RETRY_AFTER, Integer.toString(retryAfterMillis / 1000));return new ResponseEntity<>(headers, HttpStatus.SERVICE_UNAVAILABLE);
}

如您所见,我们可以询问任何命令其断路器是否断开。 如果打开,则使用circuitBreakerSleepWindowInMilliseconds值设置Retry-After标头。 该解决方案存在一个细微但灾难性的错误:如果某一天电路断开,我们将再也不会运行命令,因为我们会急于返回503。这意味着Hystrix将永远不会重试执行它,并且电路将永远保持断开状态。 我们必须尝试每次调用命令并捕获适当的异常:

@RequestMapping(value = "/", method = GET)
public ResponseEntity<String> fetch() {final HystrixCommand<String> command = fetchCommand();try {return new ResponseEntity<>(command.execute(), OK);} catch (HystrixRuntimeException e) {log.warn("Error", e);return handleHystrixException(command);}
}private ResponseEntity<String> handleHystrixException(HystrixCommand<String> command) {final HttpHeaders headers = new HttpHeaders();if (command.isCircuitBreakerOpen()) {final Integer retryAfterMillis = command.getProperties().circuitBreakerSleepWindowInMilliseconds().get();headers.set(HttpHeaders.RETRY_AFTER, Integer.toString(retryAfterMillis / 1000));}return new ResponseEntity<>(headers, SERVICE_UNAVAILABLE);
}

这个很好用。 如果命令抛出异常并且相关电路断开,我们将设置适当的标题。 在所有示例中,我们花费毫秒并归一化为秒。 我不推荐这样做,但是如果由于某些原因,您更喜欢Retry-After标头中的绝对日期而不是相对超时,则HTTP日期格式最终是Java的一部分(自JDK 8起):

import java.time.format.DateTimeFormatter;//...final ZonedDateTime after5seconds = ZonedDateTime.now().plusSeconds(5);
final String httpDate = DateTimeFormatter.RFC_1123_DATE_TIME.format(after5seconds);

关于自动DDoS的注意事项

如果将相同的时间戳发送给许多唯一的客户端,则必须谨慎使用Retry-After标头。 想象现在是15:30,然后您将Retry-After: Thu, 10 Feb 2015 15:40:00 GMT发送给周围的所有人-只是因为您以某种方式估计服务将在15:40开通。 您持续发送相同时间戳的时间越长,尊重Retry-After客户端所期望的DDoS“攻击”就越大。 基本上每个人都会在15:40安排重试的时间(很明显,时钟未完全对齐,并且网络延迟有所变化,但仍然存在),从而使系统充满了请求。 如果您的系统设计正确,那么您可能会幸免于难。 但是,您可能会通过发送另一个固定的Retry-After标头来缓解这种“攻击”,此举实际上是Retry-After重新安排攻击时间。

话虽这么说,避免将固定的绝对时间戳发送给多个唯一的客户端。 即使您确切知道系统何时可用,也可以Retry-After一段时间内分散“ Retry-After值。 实际上,您应该逐渐让越来越多的客户进入,因此请尝试不同的概率分布。

摘要

Retry-After HTTP响应标头既不是普遍已知的,也不是经常适用的。 但是在极少数情况下可以预期停机的情况下,请考虑在服务器端实施停机。 如果客户端也意识到这一点,则可以在减少系统流量和改善系统吞吐量和响应时间的同时,大幅度减少网络流量。

翻译自: https://www.javacodegeeks.com/2015/02/retry-http-header-practice.html

在实践中重试HTTP标头相关推荐

  1. 在邮件标头中找到无效的字符_在实践中重试HTTP标头

    在邮件标头中找到无效的字符 Retry-After是鲜为人知的HTTP响应标头. 让我引用RFC 2616(HTTP 1.1规范)的相关部分: 14.37重试后 Retry-After响应标头字段可与 ...

  2. 一致性协议raft详解(四):raft在工程实践中的优化

    一致性协议raft详解(四):raft在工程实践中的优化 前言 性能优化 client对raft集群的读写 参考链接 前言 有关一致性协议的资料网上有很多,当然错误也有很多.笔者在学习的过程中走了不少 ...

  3. 前端和后端开发人员比例_前端开发人员vs后端开发人员–实践中的定义和含义

    前端和后端开发人员比例 Websites and applications are complex! Buttons and images are just the tip of the iceber ...

  4. tmux系统剪切板_实践中的tmux:与系统剪贴板集成

    tmux系统剪切板 by Alexey Samoshkin 通过阿列克谢·萨莫什金(Alexey Samoshkin) 在实践中使用tmux:与系统剪贴板集成 (tmux in practice: i ...

  5. 复旦肖仰华:领域知识图谱落地实践中的问题与对策

    肖仰华博士,复旦大学计算机科学与技术学院教授,博士生导师,知识工场实验室负责人. 报告摘要:近年来,知识图谱技术进展迅速,各种领域知识图谱技术在很多领域或行业取得了显著落地效果.在领域知识图谱技术的落 ...

  6. SVM算法在项目实践中的应用!

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:苏丽敏,Datawhale优秀学习者,北理工计算机硕士 支持向量机 ...

  7. 高可用 Prometheus 架构实践中的踩坑集锦

    监控系统的历史悠久,是一个很成熟的方向,而 Prometheus 作为新生代的开源监控系统,慢慢成为了云原生体系的事实标准,也证明了其设计很受欢迎. 本文主要分享在 Prometheus 实践中遇到的 ...

  8. 奥卡姆剃刀是什么?机器学习实践中那些学习模型或者那些评估指标践行了这一理论?

    奥卡姆剃刀是什么?机器学习实践中那些学习模型或者那些评估指标践行了这一理论? 奥卡姆剃刀:无无必要,勿增实体. 奥卡姆剃刀原理应用于模型选择时变为以下想法:在所有可能选择的模型中,能够很好地解释已知数 ...

  9. SAP WM Storage Location Reference在项目实践中的使用

    SAP WM Storage Location Reference在项目实践中的使用 笔者目前所在的一个项目是一个已经上了SAP系统,但是需要扩展到新工厂的项目.该项目在组织结构设计的时候,结合业务的 ...

最新文章

  1. keras训练完以后怎么预测_使用Keras建立Wide Deep神经网络,通过描述预测葡萄酒价格...
  2. easyui-datagrid行数据field原样输出html标签
  3. DDOS SYN Flood攻击、DNS Query Flood, CC攻击简介——ddos攻击打死给钱。限网吧、黄网、博彩,,,好熟悉的感觉有木有...
  4. Catalan数推导(转载)
  5. Google学术发布2019年最有影响力的7篇论文(附下载链接)
  6. 台达plc自由口通讯_台达PLC和ABB机器人Devicenet通讯
  7. 论文浅尝 - ICLR2020 | 通过神经逻辑归纳学习有效地解释
  8. 微处理器硬件喂狗_硬件基础:微控制器到底是什么?
  9. 诺基亚赢得运营商Orange比利时5G合同,华为回应...
  10. 设计模式之单例模式8种实现方式,其五:懒汉式(线程不安全,同步代码块)
  11. Eclipse:An internal error occurred during: Building workspace. GC overhead limit exceeded
  12. [Java] 蓝桥杯ALGO-78 算法训练 确定元音字母位置
  13. CTFHUB Web前置技能 题解记录(HTTP部分)
  14. html日期选择器小日历样式,9 款样式华丽的 jQuery 日期选择和日历控件
  15. 在数据库中存储IP地址
  16. 构造伽罗华域GF(2^m)的方法
  17. elasticsearch学习(六):IK分词器
  18. 思杰虚拟服务器退出管理主机,详解Citrix思杰XenServer虚拟化(8)
  19. 留几手:互联网创业到底是咋回事(说得真经典,创业者不创业的都值得一看)
  20. 一项“和灾难赛跑的教育”工程 ——马小平编著《人文素养读本》序

热门文章

  1. ssh(Spring+Spring mvc+hibernate)——DeptDaoImpl.java
  2. Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)
  3. Arrays工具类(jre中基本类库提供的工具类)
  4. StringBuilder的使用
  5. javaweb---简易邮件发送
  6. 保定有国家承认的计算机学校吗,河北省122所大学名单,不在名单内的都是国家不承认的野鸡学校...
  7. HDU2068(错列排序)
  8. mockito java_Java:使用Mockito模拟ResultSet
  9. spring boot示例_Spring Boot完成示例
  10. spring-junit4_基于Spring的应用程序-迁移到Junit 5