微服务架构的技术点:
- 超时时间设置
- 接口重试机制
- 流量QPS限流
- 请求熔断处理
- 请求降级处理
今天给大家分享一下以上相关的知识点,通过微服务系统之间RPC通信的方式,以架构图的形式给大家展开介绍:
1、超时时间设置:
应用访问业务系统A,业务系统A调用业务系统B,整个链路都没有设置超时时间timeout,此刻如果业务系统B某个pod响应特别慢,会产生一个啥现象呢?如下图所示,业务系统A会因为线程耗完而僵死,导致整个业务系统A不可用。通过抓包或者使用jvm分析工具,可以分析线程的状态(blocked)
为了解决上图的问题,可以采用timeout,调用方设置一个超时时间,比如说,设置 timeout=1s,那么意思就是说,我们调用别的系统如果超过 1s 没有响应,就直接抛个异常就返回了,这样就可以避免我们的 线程 长时间阻塞了。
注:上图中,DNS也会设置超时时间,咱们在设置超时时间时,RPC的接口超时时间需要小于DNS的超时时间,否则会产生业务系统A的线程还在等待业务系统B返回,但是DNS已经超时返回了。
经验推敲:
timeout应该如何设置??
例如:
业务系统B A接口一般都是300~400ms 可以返回,咱们设置timeout=500,这么设置会有啥问题呢?。
因为有可能某一天因为搞活动流量比较大,业务系统B被调用压力比较大,导致他的 CPU 负载很高,结果今天导致RT响应平均是 500~600ms 了,刚好超过了 timeout 时间。
此时就会导致,你大量的请求即将处理完毕要返回的时候,结果一到 500ms 就超时异常抛出,一到 500ms 就超时异常抛出。
【敲重点啦】:所以说,timeout 超时参数设置,通常是这么设置的,对于你要调用的系统你要看看他平时调用要多久能返回,然后比正常的耗时设置的多个 50% 就可以了。
比如平时一般正常在 100~200ms,偶尔高峰会在 500ms,那你设置个 timeout=800ms 或者 1s 其实都可以。
2、接口重试机制:
接口重试机制,就是说如果你 RPC 调用一个服务要是失败了或者超时了,此时就可以通过 retry 设置自动做一个重试。
比如说自动可以重试 2 次,那么这个时候如果是因为网络偶然抖动导致的调用失败,就可以通过重试 2 次让他能够成功完成调用了。如果是其他原因,发起重试基本也是失败。
【隐患】接口重试给业务交易数据带来的隐患:
如下图,第一次插入操作,业务系统B1.5秒返回(底层业务逻辑已经正常走完,数据正常入库),接口层面超时,因为设置了重试机制,第二次重新发起,如果业务系统B不支持幂等性,数据库会存在两条一样的数据。
经验推敲:
查询操作,天生具备幂等性,所以建议对查询操作可以设置重试机制,针对其他操作,例如新增操作,重试机制要慎重,数据处理上需要支持幂等性。
3、流量QPS限流:
假设业务系统A有两个POD节点,单节点支持的QPS=2,当瞬时有三个请求到某个POD节点,会导致有一个请求处于阻塞等待
解决方案:
引入开源组件sentinel,设置限流规则:
如下图所示,针对超出的流量,设置快速失败的流控策略:
4、请求熔断处理:
日常熔断的场景有几种:接口超时熔断、接口异常熔断,参考sentinel熔断配置页面:
如下图:pod1节点在熔断期间内,相关请求将直接返回失败,路由到其他节点的请求依旧可以正常处理。
测试页面:
监测页面:
【疑问】为啥设置了超时时间,设置了流控策略,还需要额外设置熔断规则呢?
业务系统A调用业务系统B,当业务系统B某个实例异常时,响应特别慢,分发到该异常实例的请求,需要一直等到超时时间到了才会返回,导致业务系统A大量的线程被占用。
针对这种异常场景,可以引入熔断保护策略,设置熔断时间,在熔断时间内,分发到该异常实例的请求,都会快速失败,快速释放线程资源。
5、请求降级处理:
当业务系统A的服务器压力剧增的情况下,根据当前业务情况以及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。
降级是利用有限资源,保障系统核心功能高可用,属于有损的架构方法。
电商场景:电商促销活动时,例如双十一,瞬时并发流量很容易导致系统崩溃,此时开发者使用限流来进行限制访问量;当达到限流阈值,后续请求会被降级处理;
降级的处理方案可以是:排队页面(将用户倒流到排队页面等一会重试);无货(直接告知用户没有货了)、错误页(如活动太火爆了,稍后重试) 。