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

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