天天看點

3_服務容錯_保護斷路器_@EnableCircuitBreaker和引入@SpringCloudApplication

前言

前面做了一個簡單的服務 注冊。服務發現,服務提供者和消費者的項目,現在我們還是準備之前的項目代碼

1、 服務容錯保護,準備的項目工程

1、服務注冊中心 ,端口為1111

2、服務提供者,端口為8080,8081

3、服務消費者 端口為9000

2、在服務消費者中引入依賴包

hystrix 對應的中文名字是“豪豬”,豪豬周身長滿了刺,能保護自己不受天敵的傷害,代表了一種防禦機制,這與hystrix本身的功能不謀而合,是以Netflix團隊将該架構命名為Hystrix,并使用了對應的卡通形象做作為logo。
在一個分布式系統裡,許多依賴不可避免的會調用失敗,比如逾時、異常等,如何能夠保證在一個依賴出問題的情況下,不會導緻整體服務失敗,這個就是Hystrix需要做的事情。Hystrix提供了熔斷、隔離、Fallback、cache、監控等功能,能夠在一個、或多個依賴同時出現問題時保證系統依然可用。
<dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-hystrix</artifactId>
   </dependency>      
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.didispace</groupId>
   <artifactId>ribbon-consumer</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>ribbon-consumer</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.3.7.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-eureka</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-ribbon</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-hystrix</artifactId>
      </dependency>

   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Brixton.SR5</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>

</project>      

3、注解開啟斷路器功能@EnableCircuitBreaker

解釋:這裡還可以使用 @ SpringCloudApplication 注解代替上面三個注解,由此也可以得到spring Cloud标準應用包含服務發下和斷路器

@EnableCircuitBreaker //開啟斷路器功能
@EnableDiscoveryClient //開啟服務發現用戶端,
@SpringBootApplication
@SpringCloudApplication //可以取代上面三個
public class ConsumerApplication {

   @Bean
   @LoadBalanced
   RestTemplate restTemplate() {
      return new RestTemplate();
   }
   public static void main(String[] args) {
      SpringApplication.run(ConsumerApplication.class, args);
   }

}

//或者下面這個
@ SpringCloudApplication 
public class ConsumerApplication {

   @Bean
   @LoadBalanced
   RestTemplate restTemplate() {
      return new RestTemplate();
   }
   public static void main(String[] args) {
      SpringApplication.run(ConsumerApplication.class, args);
   }

}      

4、@HystrixCommand(方法内部報錯之後,自動去找復原的方法)

4.1、建立service類,用來添加指定回調方法

@Service
public class HelloService {

    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "helloFallBack")
    public String hello(){
        return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();
    }


    public String helloFallBack(){
        return "error";
    }
}      

5、修改之前服務消費者的Controller方法

@RestController
public class ConsumerController {


    @Autowired
    HelloService helloService;

    @ResponseBody
    @RequestMapping(value = "/ribbon-consumer", method = RequestMethod.GET)
    public String helloConsumer() {
        return helloService.hello();
    }

}      

6、開始驗證斷路器的實作的回調邏輯,

6.1、啟動所有的服務

通路​​http://localhost:9000/ribbon-consumer ​​

6.2、在8080 8081 這兩個服務提供者工作的時候,傳回的結果都是一樣的

3_服務容錯_保護斷路器_@EnableCircuitBreaker和引入@SpringCloudApplication

6.3、直接斷開8081服務提供者

這個時候我們将8081的服務提供者挂掉,繼續通路,發現一會正常,一會顯示error,但是時間長了,就還是隻會顯示hello ,出現這種情況,應該是注冊中心沒有及時檢測到挂掉了8081,還繼續提供給消費者服務。但是時間長了,就肯定原型畢露

7、模拟服務阻塞,添加延遲

解釋:(hystrix預設逾時2000毫秒) (啟動所有的服務)

7.1、服務提供者中添加延遲時間設定為3000毫秒

/**
 * 2、斷路器,模拟服務阻塞
 */
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() throws InterruptedException {

   ServiceInstance instance = client.getLocalServiceInstance();


   int sleepTime = new Random().nextInt(3000);
   logger.info("處理線程等待 "+sleepTime+" 秒");
   Thread.sleep(sleepTime);

   logger.info("/hello, host:" + instance.getHost() + ", service_id:" + instance.getServiceId());
   return "Hello World";
}      

7.2、結果 :和上面的測試是一樣的,也是有錯誤,有正常