微服務架構中,微服務之間相互調用,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的斷路器已經生效了。