微服务架构中,微服务之间相互调用,springcloud能够用feign方式和RestTemplate+ribbon方式来实现服务间的相互调用。但若是某一个服务出现问题,全部调用该出问题的服务都将出现阻塞,若是有大量的请求,则Servlet容器的线程资源会被消耗完毕,致使服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统形成灾难性的严重后果,这就是服务故障的“雪崩”效应。java
为了解决这个问题,业界提出了断路器模型。web
1.ribbon中使用断路器hystrixspring
build.gradle文件架构
buildscript { ext { springBootVersion = '2.0.4.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } ext { springCloudVersion = 'Finchley.SR1' } dependencies { compile('org.springframework.boot:spring-boot-starter-web') compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix') compile('org.springframework.cloud:spring-cloud-starter-netflix-ribbon') testCompile('org.springframework.boot:spring-boot-starter-test') } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
application.yml文件app
server: port: 8797 spring: application: name: service-ribbon-hystrix eureka: client: service-url: defaultZone: http://localhost:8791/eureka/
主方法eclipse
package com.example.serviceribbonhystrix; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @EnableHystrix @EnableEurekaClient @SpringBootApplication public class ServiceRibbonHystrixApplication { public static void main(String[] args) { SpringApplication.run(ServiceRibbonHystrixApplication.class, args); } @Bean RestTemplate restTemplate() { return new RestTemplate(); } }
HelloService.java文件maven
package com.example.serviceribbonhystrix; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class HelloService { @Autowired RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "errorMsg") public String hiService() { return restTemplate.getForObject("http://EUREKA-CLIENT-SAY-HI/hi", String.class); } public String errorMsg(){ return "I am ribbon with hystrix,Wrong!"; } }
HelloController.java文件ide
package com.example.serviceribbonhystrix; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @Autowired HelloService helloService; @RequestMapping("/hi") public String sayHi() { return helloService.hiService(); } }
只是单独启动该服务,不启动eureka-client-say-hi服务,访问http://localhost:8797/hispring-boot
返回要返回的信息,此时断路器已经生效了:微服务
2.feign中使用断路器hystrix
由于feign是自带断路器的,因此依赖中就不须要加hystrix
build.gradle
buildscript { ext { springBootVersion = '2.0.4.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } ext { springCloudVersion = 'Finchley.SR1' } dependencies { compile('org.springframework.boot:spring-boot-starter-web') compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') compile('org.springframework.cloud:spring-cloud-starter-openfeign') testCompile('org.springframework.boot:spring-boot-starter-test') } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
application.yml文件
server: port: 8796 spring: application: name: service-feign-hystrix eureka: client: service-url: defaultZone: http://localhost:8791/eureka/ feign: hystrix: enabled: true #feign自带断路器,但须要打开
主方法:
package com.example.servicefeignhystrix; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; @EnableEurekaClient @EnableFeignClients @SpringBootApplication public class ServiceFeignHystrixApplication { public static void main(String[] args) { SpringApplication.run(ServiceFeignHystrixApplication.class, args); } }
接口SayHiService.java文件
package com.example.servicefeignhystrix; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @FeignClient(value = "eureka-client-say-hi",fallback = SayHiServiceWithHystrix.class) public interface SayHiService { @RequestMapping(value = "/hi", method = RequestMethod.GET) String sayHiFromClient(); }
SayHiServiceWithHystrix.java文件
package com.example.servicefeignhystrix; import org.springframework.stereotype.Component; @Component public class SayHiServiceWithHystrix implements SayHiService { @Override public String sayHiFromClient() { return "sorry,I am wrong"; } }
HelloController.java文件
package com.example.servicefeignhystrix; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @Autowired SayHiService sayHiService; @RequestMapping("/hi") public String sayHi(){ return sayHiService.sayHiFromClient(); } }
此时启动eureka-server,以及eureka-client-say-hi项目的两个实例,以及刚才新建的项目service-feign-hystrix.
访问http://localhost:8796/hi
出现如下两种场景:
和
若是关掉8792端口的服务,则会返回hi,I am port 8793
若是关掉eureka-client-say-hi服务的8792和8793两个端口实例,则会返回
此时标明,feign的断路器已经生效了。