SpringCloud &Hystrix的使用

330 阅读4分钟

简述

image.png

注:本次的样例是在之前的项目上进行更改

什么是 Hystrix?

  • 在分布式环境中,不可避免地会遇到所依赖的服务挂掉的情况,Hystrix 可以通过增加 延迟容忍度 与 错误容忍度,来控制这些分布式系统的交互。Hystrix 在服务与服务之间建立了一个中间层,防止服务之间出现故障,并提供了失败时的 fallback 策略,来增加你系统的整体可靠性和弹性。
  • 中文文档

服务熔断

样例

提供在故障时的应急方法(fallback)

  • 熔断是在服务提供者上进行的。

  • 选其中一个服务提供者使用Hystrix

  • 步骤如下

  1. 导入依赖
  2. 启动类上使用@EnableCircuitBreaker//开启熔断
  3. controller层创建应急方法(fallback),使用@HystrixCommand
  • 代码 依赖
    <dependencies>
        <!-- 实体类-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>SpringCloud-Api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</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-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>
  • controller
//提供restful 服务
@RestController
public class DeptController {
    @Autowired
    private DeptService service;

    //用8001端口不行,非要用得post请求。消费服务端ok
    @RequestMapping(value = "/add")
    public boolean add(@RequestBody Dept dept) {
        System.out.println(dept.getDname());
        return service.addDept(dept);
    }

    @GetMapping("/byId/{id}")
    @HystrixCommand(fallbackMethod = "HystrixgetDeptById")//抛出异常时使用备选方法
    public Dept getDeptById(@PathVariable(value = "id") int id) {
        Dept dept = service.getById(id);
        if (dept == null) {
            throw new RuntimeException("id=>" + id + "查无此人");
        }
        return dept;
    }

    @GetMapping("/getAll")
    public List<Dept> getAll() {
        return service.getAll();
    }

    //备选方法
    public Dept HystrixgetDeptById(int id) {
        return new Dept()
                .setDeptId(id)
                .setDname("id=>" + id + "没有对应的信息,nul1--@Hystrix")
                .setDb_source("数据库中没有对应数据");
    }
}

  • 启动类
@EnableEurekaClient
/*
客户端的便利注释,用于启用Eureka发现配置(特别是)。
如果您想发现并确定知道它是您想要的Eureka,请使用此(可选)。
 它所做的只是打开发现功能,并让自动配置找到可用的eureka类(即,您在类路径上也需要Eureka)。
 */
@SpringBootApplication
@EnableCircuitBreaker//开启熔断
public class DeptProvider_Hystrix_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_Hystrix_8001.class,args);
    }
}

小结

image.png

服务降级

  • 在整体资源不够的时候,适当放弃部分服务,将主要的资源投放到核心服务中。

样例

步骤

  1. 导入依赖
  2. 在api项目实现接口FallbackFactory,创建后备实例
  3. 在api的service上的注解@FeignClient添加参数fallbackFactory = xxx.classFallbackFactory的实现类
  4. 在服务消费者配置application.yaml

feign.hystrix.enabled: true

  • 依赖
 <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在api项目实现接口FallbackFactory

/*
返回适合给定原因的后备实例
原因–通常与com.netflix.hystrix.AbstractCommand.getExecutionException()对应
 */
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory<FeignDeptService> {
    @Override
    public FeignDeptService create(Throwable cause) {
        return new FeignDeptService(){//实现接口
            @Override
            public boolean addDept(Dept dept) {
                return false;
            }

            @Override
            public Dept getById(int id) {
                return new Dept()
                        .setDeptId(id).setDname("id=>"+id+"无法查询")
                        .setDb_source("服务器已关闭,稍后开启");
            }

            @Override
            public List<Dept> getAll() {
                List<Dept> list= new ArrayList<>();
                list.add(new Dept().setDname("服务器已关闭,稍后开启"));
                return list;
            }
        };
    }
}

api中的service

@Service
@FeignClient(value= "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)//value=服务id
public interface FeignDeptService {
    @RequestMapping(value = "/add")
    boolean addDept(@RequestBody Dept dept);
    @GetMapping("/byId/{id}")
    Dept getById(@PathVariable(value = "id") int id);
    @GetMapping("/getAll")
    List<Dept> getAll();
}
  • 服务消费者启动类
@SpringBootApplication//(scanBasePackages = "com.cloud.service")
@EnableEurekaClient
@EnableFeignClients//(basePackages = {"com.cloud.service"})
//@ComponentScan(basePackages = "com.cloud.service")//需要加,不然找不到工厂类
public class FeignDeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(FeignDeptConsumer_80.class,args);
    }
}

小结

image.png

服务熔断:在服务端进行。
服务降级:当服务端不可用时,服务消费端自给自足。

熔断监控(Breaker Dashboard)

  • 只能监控有熔断方法的服务

步骤

  1. 创建Hystrix Dashboard项目
  2. 导入依赖,服务提供者和Dashboard要导依赖
  3. 配置文件
  4. 在需要监控的服务端创建HystrixMetricsServlet

创建Hystrix Dashboard项目创建Hystrix Dashboard项目

依赖

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

服务提供者要导

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

Hystrix Dashboard项目 启动类

@SpringBootApplication
@EnableHystrixDashboard

public class DeptConsumerDashboard_9001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerDashboard_9001.class,args);
    }
}

配置文件application.yaml

server:
  port: 9001
hystrix:
  dashboard:
    proxy-stream-allow-list: 'localhost'

启动9001,访问http://localhost:9001/hystrix

image.png

监控的服务端创建HystrixMetricsServlet

@EnableEurekaClient
/*
客户端的便利注释,用于启用Eureka发现配置(特别是)。
如果您想发现并确定知道它是您想要的Eureka,请使用此(可选)。
 它所做的只是打开发现功能,并让自动配置找到可用的eureka类(即,您在类路径上也需要Eureka)。
 */
@SpringBootApplication
@EnableCircuitBreaker//开启熔断
public class DeptProvider_Hystrix_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_Hystrix_8001.class,args);
    }
    //增加HystrixMetricsServlet
    @Bean
    public ServletRegistrationBean hystrixMetricsServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        return registrationBean;
    }
}

如何使用

  • 先访问有 @HystrixCommand注解的方法,

本例是http://localhost/consumer/byId/1

本例是8001端口有熔断方法

image.png

  • 最后出现

image.png