2018/2/20 Springretry,Feign,以及用通俗的语言(自认为)教会你关于Hystrix的复杂概念
本来想昨天写的,但临时有事。弄的一晚上都没睡觉,现在头好晕,所以此笔记如果有语言措辞的组织不当,还请见谅;最后,本文可能涉及到大量专业名词,我会尽量用通俗的语句去阐述清楚它们的意思,但如果还是没看懂,请自己百度;
首先介绍下Springretry,Spring为我们提供的一个重试机制工具类,而在SpringCloud中,其一般都是与ribbon整合来进行负载均衡调用的重试;
这里注掉连接超时时间和处理超时时间的原因的是我在没有配置断路器(Hystrix的时候,这两个设置没起到作用,只有配置的情况下才起到作用);
另外要注意的是,重试时切换示例次数那个配置如果不配置的话会把你当前要调用服务的所有实例都切换然后试一次;
最后在配置retry的时候一定要做好幂等处理,因为当你的请求发过去后,处理超时不代表连接超时,可能服务的提供方已经在做一些逻辑处理,只是还没结束,但这个时候到达了处理超时时间,那么retry就会直接再发一次请求。这样如果你是做post请求的话,那么就等于插入了多条数据;
Hystrix,这个要划重点,我觉得在说这个框架之前,有必要先说说分布式架构里著名的CAP定理,C(数据一致性),A(服务可用性(对一个服务的请求必须要得到响应)),P(服务容错性(不能因为一个服务的问题而影响到其它服务));
我个人认为Hystrix在分布式服务里解决了非核心业务中中的P以及A。为什么这么说呢?
先来给大家模拟一个场景:
服务A与服务B,其中服务B是服务A的依赖服务。此时,一个请求访问了服务A,而服务A为了响应这个请求则必须去调用服务B。但此时,服务B因为机器原因出现了一些故障导致无法很快速的响应服务A,因此,服务A堆积的请求越来越多,线程资源无法释放,这样一来,就会导致服务A瘫痪,而服务A一瘫痪,可能会导致依赖服务A的服务也会
跟着瘫痪,就像多米诺骨牌一样,服务一个连着一个瘫痪掉,形成了雪堆效应(网上通用说法,我更喜欢理解为蝴蝶效应),这也就是没法实现CAP定理中的P了;
而Hystrix做了什么事呢?
很简单,降级处理,依赖隔离,信号量,以及熔断机制
降级处理,很简单,当服务连接或处理超时,亦或者触发了某些条件后(依赖隔离,信号量),就不会走实际调用的方法,而是走fallback属性指定的一个方法,比如我们本来是要去从redis中获取一条数据的,但因为redis连接或处理超时,亦或者访问线程超过了我们设定的数值后,那么我们就可以在fallback方法中指定一个方法,而这个方法则是去
访问数据库的,这就是所谓的降级处理,当最佳选择不能使用时,便实行次佳选择;
当然也可以在触发异常时做降级处理
依赖管理:
就是说当前这个方法的运行,我Hystrix内部维护一个线程池专门去运行它,而不需要你的容器请求线程,此时你容器的请求线程就可以离开,等到我完成任务的时候,再会通知请求线程返回我处理完的结果;
其实当你调用HystrixCommand这个注解的时候,已经就是默认开启了依赖管理,至于默认的线程数量,任务队列的大小,我倒是没有在官方文档中找到,不过这个是可以配置的;
前面两个配置应该都能看懂,最后一个是什么意思呢?
queueSizeRejectionThreshold这个属性的意思是,实际任务队列的大小,而且此属性是动态的,也就是说,你可以在项目运行时更改,它可以动态的去控制,貌似这个是用到什么Rxjava热观察的一个技术,具体的也不用去深究,理解为热加载一类的技术即可;
至于为什么需要这个属性呢?这是为了根据服务器实际情况去动态的调整任务队列,以免引起任务积压,导致响应太慢;
最后一但任务队列满了后,就会自动走降级方法;
这里再提一个点:
这个commanKey属性看上去没有意义,但其实是对于实行依赖管理后线程组的分组,也就是说,多个方法使用了同一个key,那么它们就共用同一个线程组;
信号量:
因为依赖管理使用的是内部线程池,并且是并发状态,考虑到线程并发处理,线程之间的切换调度,这些都比较耗资源与时间。所以如果对于响应时间要求非常高的服务,那么依赖管理肯定无法满足我们的需求,这个时候就需要信号量了;
那么信号量是什么呢?信号量其实就是一个开关,比如你现在限定只能有十个线程同时调用此方法,如果此时有第十一个线程的话,那么便会直接走降级方法;
熔断机制:
此机制概念较模糊,它的作用是,在一定的时间内(官方术语叫快照窗),你当前如果有超过一定百分比的请求都走了降级处理的话(当然它有一个请求的最低数量限制,只有超过了这个请求数量才会开始计算),那么后面的请求都是走降级方法。在经过一段时间后,它会放行一个请求去走主逻辑(原本我们调用的方法),如果此时没有出现问题,
那么它就会快速清空线程池,并关闭熔断机制,让后面的请求继续交由依赖管理机制;
看到这里应该明白为什么我说Hystrix能解决A和P了吧?其实Hystrix的功能十分强大,远不止于这些,详情可以查询官方文档;ps:谷歌浏览器的翻译贼好用,推荐英文不行的使用谷歌浏览器访问,翻译控件开关在右上角。收藏的那个★旁边;
最后Feign:
其实就是本地创建一个你要调用的服务的代理,这个太简单,直接看代码就行,我注释都写的比较全
此时负责降级处理的类
在访问依赖服务的时候,直接调用我们使用Feign的在本地绑定的访问服务的代理即可,spring会帮我们依赖注入
有一点要注意:
如果你是Dalston.SR1版本请手动开启feign的断路器功能,其它版本请忽略,网上的教程也大都是此版本,但我当时使用的是SR3,并且当时没有手动开启,而断路器功能是正常启用的,所以如果SR3版本应该是默认开启的