前言
Http是一种协议,对于header、请求方法、内容传送方式等给出了相关定义和推荐用法,但并不会要求你强制遵循的。我们只所以要把一些细节掌握好是因为“专业性”,要把约定俗成的一些细节用好。
需求场景
流量入口到统一接入API网关层,当突发洪峰时虽然后端服务具有弹性能力,但毕竟资源的启动和应用预热都需要时间,所以服务能力的扩容具有延后性。用户越是接收不到预期的返回越是会疯狂重试,最终导致洪峰放大N倍后后端雪崩。如果我们想彻底解决这个问题,需要做两手准备。第一,做好后端的限流保护,当服务能力超过预期时保证能力内的请求正常返回,限流的策略一般分为信号量和并发数两种思路,这个不在我们本期Retry-After讨论范围内。第二,当后端被限流后要让客户端明确感知到,并采取一些措施防止用户重试,避免造成更多无效的请求。
设计思路
我们将第二点需求拆分成两个:1,让客户端知道限流了;2:限制它们重试。
限流感知:
需要协商一个非200的状态码,具体使用哪个状态码呢?这里先卖个关子,其实可以自定义,当然作为http协议专业用法我们还是用推荐的code。
限制重试:
需要用到我们这里的主角Retry-After,它有两种使用方法:
Retry-After: <http-date>
Retry-After: <delay-seconds>
例如:
Retry-After: Wed, 21 Oct 2015 07:28:00 GMT
Retry-After: 120
根据案例很好理解,第一种表示别人在某个时间点之前都不要再发起重试了,第二种表示多少秒只能不要发起重试。个人推荐使用第二种,这个对资源开销最小,否则还需要消耗计算资源去计算时间。
OK,我们订好了要用Retry-After头信息后我们的返回状态码也随之有着落了。
与Retry-After配套出现的有两种主要的场景:
场景一:表示因为服务端服务能力不足引起的限流,推荐使用503,当然503不仅只应用于限流场景。
场景二:表示因客户端请求太过频繁引起的限流,荐使用429,这个是客户端被限流专用的状态码。
方案定好后后面就是客户端的研发工作了,需要找到禁用重试的点,例如下拉列表框、按钮等,当然在体验之上的互联网时代有些UI还是需要好好设计下,如何友好的提示用户。
结束语
再次强调下,Http只是个协议,你可以不用它推荐的使用方式,回到我们这个场景完全可以自己定义一个header自己定义一个code,照样可以达到目的,但是我们要用还是要尽量用的专业些。