本篇集成Hystrix,继续搭建demo。前端
雪崩效应:
在微服务架构中一般会有多个服务层调用,基础服务的故障可能会致使级联故障,进而形成整个系统不可用的状况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用致使“服务消费者”的不可用,并将不可用逐渐放大的过程。web
若是下图所示:A做为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引发了B的不可用,并将不可用像滚雪球同样放大到C和D时,雪崩效应就造成了。spring
熔断器:
熔断器的原理很简单,如同电力过载保护器。它能够实现快速失败,若是它在一段时间内侦测到许多相似的错误,会强迫其之后的多个调用快速失败,再也不访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操做,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器也可使应用程序可以诊断错误是否已经修正,若是已经修正,应用程序会再次尝试调用操做。后端
熔断器模式就像是那些容易致使错误的操做的一种代理。这种代理可以记录最近调用发生错误的次数,而后决定使用容许操做继续,或者当即返回错误。
熔断器开关相互转换的逻辑以下图:缓存
Hystrix熔断器:
1.断路器机制服务器
断路器很好理解, 当Hystrix Command请求后端服务失败数量超过必定比例(默认50%), 断路器会切换到开路状态(Open). 这时全部请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回状况, 若是请求成功, 断路器切回闭路状态(CLOSED), 不然从新切换到开路状态(OPEN). Hystrix的断路器就像咱们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 而且断路器有自我检测并恢复的能力.架构
2.Fallbackmvc
Fallback至关因而降级操做. 对于查询操做, 咱们能够实现一个fallback方法, 当请求后端服务出现异常的时候, 可使用fallback方法返回的值. fallback方法的返回值通常是设置的默认值或者来自缓存.app
3.资源隔离ide
在Hystrix中, 主要经过线程池来实现资源隔离. 一般在使用的时候咱们会根据调用的远程服务划分出多个线程池. 例如调用产品服务的Command放入A线程池, 调用帐户服务的Command放入B线程池. 这样作的主要优势是运行环境被隔离开了. 这样就算调用服务的代码存在bug或者因为其余缘由致使本身所在线程池被耗尽时, 不会对系统的其余服务形成影响. 可是带来的代价就是维护多个线程池会对系统带来额外的性能开销. 若是是对性能有严格要求并且确信本身调用服务的客户端代码不会出问题的话, 可使用Hystrix的信号模式(Semaphores)来隔离资源.
咱们在movie微服务中使用Hystirx,新建文件以下目录
在controller中,能够直接使用Hystrix注解,而且自定义fallback函数,当请求后端服务出现异常的时候, 可使用fallback方法返回的值.
@GetMapping("/movie/{id}") @HystrixCommand(fallbackMethod = "fallbackMovie",commandProperties = @HystrixProperty(name = "execution.isolation.strategy",value = "semaphore")) public User findmovie(@PathVariable int id){ return userFeignClient.find(id); } public User fallbackMovie(int id){ User user=new User(); user.setId(10); return user; }
其中commandProperties = @HystrixProperty(name = "execution.isolation.strategy",value = "semaphore")
的value Hystrix默认为thread,
默认使用线程池里隔离的线程,要想切换到调用者相同线程使用Spring Security的context,就要设置隔离策略为semaphore。
关于Spring父子容器context:
1. 首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;
2. 其次,在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;
3. 再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet能够配置多个,以最多见的DispatcherServlet为例,这个servlet其实是一个标准的前端控制器,用以转发、匹配、处理每一个servlet请求。DispatcherServlet上下文在初始化的时候会创建本身的IoC上下文,用以持有spring mvc相关的bean。在创建DispatcherServlet本身的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取以前的根上下文(即WebApplicationContext)做为本身上下文的parent上下文。有了这个parent上下文以后,再初始化本身持有的上下文。这个DispatcherServlet初始化本身上下文的工做在其initStrategies方法中能够看到,大概的工做就是初始化处理器映射、视图解析等。这个servlet本身持有的上下文默认实现类也是mlWebApplicationContext。初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key,而是经过一些转换,具体可自行查看源码)的属性为属性Key,也将其存到ServletContext中,以便后续使用。这样每一个servlet就持有本身的上下文,即拥有本身独立的bean空间,同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean。
feign中使用Hystrix:
feign客户端
@FeignClient(name="userprovider",configuration = FeignClient.class,fallback = HystrixFallbackClient.class) public interface UserFeignClient { @RequestMapping (value = "/user/{id}",method = RequestMethod.GET) public User find(@PathVariable("id") int id); }
fallback的类HystrixFallbackClient实现fallback方法
@Component public class HystrixFallbackClient implements UserFeignClient { @Override public User find(int id) { User user=new User(); user.setId(1); return user; } }
若想禁用某个feignClient的Hystrix能够更改feignClient的config,在里面返回feign.bulider,默认为Hystrix的
FeignConfig:
@Configuration public class FeignConfig { @Bean public Contract feignContract(){ return new feign.Contract.Default(); } @Bean @Scope("prototype") public Feign.Builder feignBuilder(){ return Feign.builder(); } }
若是须要访问回退触发的缘由,Hystrix也提供fallbackfactory :
改写UserFeignClient的属性:
@FeignClient(name="userprovider",configuration = FeignClient.class,fallbackFactory = HystrixFallbackFactory.class) public interface UserFeignClient { @RequestMapping (value = "/user/{id}",method = RequestMethod.GET) public User find(@PathVariable("id") int id); }
建立HystrixFallbackFactory,和一个继承UserFeignClient的接口
HystrixUserFeignClientWithFactory:
public interface HystrixUserFeignClientWithFactory extends UserFeignClient { }
HystrixFallbackFactory:
@Component public class HystrixFallbackFactory implements FallbackFactory<UserFeignClient>{ private static final Logger logger= LoggerFactory.getLogger(HystrixFallbackFactory.class); @Override public UserFeignClient create(Throwable throwable) { this.logger.info("异常缘由为{}",throwable.getMessage()); return new HystrixUserFeignClientWithFactory() { @Override public User find(int id) { User user=new User(); user.setId(0); return user; } }; } }
hystrix实时监控可视化可使用dashboard
eureka的pom添加
`<dependency>
<groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>`
并给application添加注解@EnableHystrixDashboard,启动eureka,movie微服务(记得改UserFeignClient的fallback为fallbackfactory,删除fallback属性以及UserFeignClient实现类,否则报错)访问hystrix
先使用movie微服务,hystrix才能打印日志记录,访问http://localhost:8088/hystrix...
而后在http://localhost:8761/hystrix,输入http://localhost:8088/hystrix...地址,成功监控