spring-cloud之hystrix

Hystrix是由Netflix開源的一個針對分佈式系統容錯處理的開源組件。

1)通過客戶端庫對延遲和故障進行保護和控制。(當被訪問的服務或方法失敗時會調用自定義的容錯方法,容錯方法通常都是已日誌和失敗提示爲主,這樣做使得調用發生的錯誤更優雅的表現出來)。

2)在一個複雜的分佈式系統中停止級聯故障。(例如當A服務調用B服務時,此時B服務因爲其他服務的調用壓力過大延遲或奔潰,那麼A根據配置:過期時間,請求數量等配置觸發fallback邏輯“容錯邏輯”)。

3)快速失敗和迅速恢復。(根據請求失敗率來進行自動隔離服務,此時服務會拒絕所有請求,直到內部線程空出來在迅速恢復服務)

4)在合理的情況下回退和優雅地降級。(當請求壓力大時,會將服務降級“只處理當前進程內邏輯不再接收新的請求”)

5)開啓近實時監控、告警和操作控制。(提供鏈路追蹤的儀表盤,供運維/開發推斷當前配置是否合理)。

Hystrix基本操作:

例子一:

1.eureka客戶端,服務端前幾節有

 pom.xml

<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>
  <parent>
    <groupId>cn.springcloud.book</groupId>
    <artifactId>ch6-1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>

  <artifactId>ch6-1-client-service</artifactId>
  
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>

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

bootstrap.yml

server:
  port: 8888
spring:
  application:
    name: sc-client-service
eureka:
  client:
    serviceUrl:
      defaultZone: http://${eureka.host:127.0.0.1}:${eureka.port:8761}/eureka/
  instance:
    prefer-ip-address: true

ClientApplication:@EnableHystrix啓用Hsystrix

package cn.springcloud.book;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

/**
 * @author www.springcloud.cn
 *
 */
@SpringBootApplication
@EnableHystrix
@EnableDiscoveryClient
public class ClientApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
}

IUserService

package cn.springcloud.book.service;

public interface IUserService {
    public String getUser(String username) throws Exception;

}

UserService:@HystrixCommand(fallbackMethod="defaultUser"),在此處執行hystrix命令,要是被修飾的方法執行失敗則執行指定的方法“defaultUser”

package cn.springcloud.book.service.impl;


import org.springframework.stereotype.Component;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

import cn.springcloud.book.service.IUserService;

/**
 */
@Component
public class UserService implements IUserService{
    
    @Override
    @HystrixCommand(fallbackMethod="defaultUser")
    public String getUser(String username) throws Exception {
        if(username.equals("spring")) {
            return "This is real user";
        }else {
            throw new Exception();
        }
    }
    
     /**
      * 出錯則調用該方法返回友好錯誤
      * @param username
      * @return
      */
     public String defaultUser(String username) {
        return "The user does not exist in this system";
     }
     
}

TestController

package cn.springcloud.book.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import cn.springcloud.book.service.IUserService;

@RestController
public class TestController {

    @Autowired
    private IUserService userService;
    
    @GetMapping("/getUser")
    public String getUser(@RequestParam String username) throws Exception{
        return userService.getUser(username);
    }
}

然後啓動eureka server後啓動此項目即可訪問controller,可以看到當參數爲:spring時返回getUser方法的:"This is real user",否則返回defaultUser方法的:"The user does not exist in this system"。

這就是hystrix在代碼層展示最直觀的方式。

例子二:

spring cloud feign服務間調用也集成了spring cloud hystrix,以及負載均衡 spring cloud ribbon,當調用別的服務失敗時會觸發fallback指定類對應的方法,fallback指定類藥實現當前當前調用接口。

package cn.springcloud.book;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author www.springcloud.cn
 */
@SpringBootApplication
@EnableHystrix
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
    
}
package cn.springcloud.book.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import cn.springcloud.book.service.impl.UserServiceFallback;

@FeignClient(name = "sc-provider-service", fallback = UserServiceFallback.class)
public interface IUserService {
    
    @RequestMapping(value = "/getUser",method = RequestMethod.GET)
    public String getUser(@RequestParam("username") String username);
    
}
package cn.springcloud.book.service.impl;

import org.springframework.stereotype.Component;
import cn.springcloud.book.service.IUserService;

@Component
public class UserServiceFallback implements IUserService{
    /**
      * 出錯則調用該方法返回友好錯誤
      * @param username
      * @return
      */
    public String getUser(String username){
        return "The user does not exist in this system, please confirm username";
    }
}
package cn.springcloud.book.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import cn.springcloud.book.service.IUserService;

@RestController
public class TestController {

    @Autowired
    private IUserService userService;
    
    @RequestMapping(value = "/getUser",method = RequestMethod.GET)
    public String getUser(@RequestParam("username") String username) throws Exception{
        return userService.getUser(username);
    }
}

yml配置:記得在spring cloud feign的配置中打開hystrix,否則hystrix不起作用,調用失敗不會測試調用失敗拋出異常後不會優雅的提示,直接會報錯500.

feign:
  hystrix:
    enabled: true

pom.xml

<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>
  <parent>
    <groupId>cn.springcloud.book</groupId>
    <artifactId>ch6-2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>

  <artifactId>ch6-2-consumer-service</artifactId>
  
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

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

 

要訪問服務的controller,要訪問的項目爲一個正常的擁有controller接口的服務。如果知識單純的被訪問在不需要引入hystrix.

package cn.springcloud.book.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @RequestMapping(value = "/getUser",method = RequestMethod.GET)
    public String getUser(@RequestParam("username") String username) throws Exception{
        if(username.equals("spring")) {
            return "This is real user";
        }else {
            throw new Exception();
        }
    }
}

 hystrix統計各個服務健康狀況,合併請求,隔離方式:https://weread.qq.com/web/reader/71d32370716443e271df020kd67323c0227d67d8ab4fb04

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章