在邮件标头中找到无效的字符

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. {在头值中找到无效的字符。} 发email的时候 遇到这个问题 老师解决

  2. 在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义

    使用Tomcat8部署项目时,有接口会报400错误,后端提示在请求目标中找到无效字符.有效字符在RFC 7230和RFC 3986中定义 原因 在日志显示的请求地址中包含非法字符,出现400错误 to ...

  3. java.lang.IllegalArgumentException: 在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义

    org.apache.coyote.http11.Http11Processor.service 解析 HTTP 请求 header 错误注意:HTTP请求解析错误的进一步发生将记录在DEBUG级别. ...

  4. java.lang.IllegalArgumentException: 字符[_]在域名中永远无效。 at

    [http-nio-8080-exec-1] org.apache.coyote.AbstractProcessor.parseHost [xxx_tomcat] 是无效主机注意:更多的请求解析错误将 ...

  5. python找出只出现一次的字符_在一个字符串中找到第一个只出现一次的字符。

    题目: 在一个字符串中找到第一个只出现一次的字符.如输入 abaccdeff,则输出 b. 分析: 一个字符串存储的都是ASCII字符,其ASCII范围不超过255. 因此可以再创建一个255个元素的 ...

  6. 如何在服务器中找到数据库文件夹,如何在服务器中找到数据库文件

    如何在服务器中找到数据库文件 内容精选 换一换 本手册基于华为云关系型数据库实践所编写,用于指导您完成相关设置,购买更符合业务的数据库实例. 华为云帮助中心,为用户提供产品简介.价格说明.购买指南.用 ...

  7. 指针真的是个小机灵--将字符串中的n个字符左移,串中的前n个字符移到最后

    题目:编写一函数:strlshif(char *s,int n),其功能是吧字符串s中的所有的字符左移n个位置,串中的前n个字符移到最后. 解题思路: 找到字符的最后位置,然后循环n次赋值,将前n个字 ...

  8. python删除字符串中重复字符_删除字符串中重复字符python 用CAD怎么画DNA反向

    用CAD怎么画DNA反向平行双螺旋结构绘螺旋线时,用选扭曲,确定顺时针. 画双头螺旋线时,第二根螺旋线底圆起点与第一根螺旋线底圆起点,可用角度分隔如180°.python去除文本中重复的字符串可有可无 ...

  9. 如何在服务器中找到数据库文件夹,如何在服务器中找到数据库文件路径

    如何在服务器中找到数据库文件路径 内容精选 换一换 可以根据应用备份将资源的数据恢复到备份时刻的状态.需要恢复的资源的状态为"在线".不建议对正在运行的应用程序的文件进行恢复,建议 ...

最新文章

  1. 【机器学习基础】--感知机完全解读
  2. 【LeetCode】深搜DFS(共85题)
  3. Django annotate: 外键字段解析问题
  4. 印度孟买机器人餐厅_印度孟买自动化展:该国最重要、规模最大的国际自动化展...
  5. java线程集合点_Jmeter集合点(线程组和同步定时器)
  6. jq使用教程04_高校版教程
  7. SpringBoot动态切换数据源-快速集成多数据源的启动器
  8. linux学习笔记:linux中查看文件内容的命令
  9. 项目实施流程和规范模板(测试方向)
  10. CVE-2014-6332学习笔记
  11. 【高德地图】------- JavaScript实现高德地图经纬度获取地址位置
  12. C/C++的刷题练习之牛客网,一个友好的网站
  13. 2007年在职攻读硕士学位全国联考
  14. 基于wiki的*GW需求体系化空间
  15. QQ音乐、网易云音乐、酷狗音乐歌单导入到Spotify
  16. 【JZOJ1320】拯救奶牛
  17. html设置图像路径,Html图像标签、绝对路径和相对路径:
  18. 国产安卓和原生android,定制安卓和原生Android到底有哪些不同?真相了!
  19. javaweb——jsp(jsp的本质是什么、jsp九大内置对象、四个域对象、jsp的主要作用)
  20. Android常用热门开源库汇总(持续更新)

热门文章

  1. 【DP】Rotating Substrings(CF1363F)
  2. 什么是线程安全,你真的了解吗
  3. JSP2.0中的表达式语言(EL表达式)
  4. SpringCloud Eureka自我保护机制
  5. JVM菜鸟进阶高手之路
  6. Java 线程同步总结
  7. 马踏棋盘算法(骑士周游)+贪心优化
  8. 2016蓝桥杯省赛---java---B---1(煤球数目)
  9. 二叉排序树的删除+图解
  10. idea左右切换页面 返回上一次鼠标位置