SpringCloud-5-Hystrix

Hystrix

1. Hystrix概述

Netflix的创造了一个调用的库Hystrix实现了断路器图案。在微服务架构中,通常有多层服务调用。

ia_300000008

当其中有一个系统有延迟,它会阻塞整个用户请求

soa-2-640

在高流量的情况下,一个后端依赖项的延迟可能导致所有服务器上的所有资源在数秒内饱和(即服务雪崩)

ia_300000010

2. 服务熔断

熔断机制是对雪崩效应的一种微服务链路保护机制

熔断机制的注解是@HystrixCommand

1. 添加依赖

我们是在服务端就行服务熔断的,因此在provider中进行操作

<!--Hystrix-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

2. 编写controller

package com.wang.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.wang.springcloud.pojo.Dept;
import com.wang.springcloud.service.DeptService;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;

//提供RestFul服务!
@RestController
@ApiModel("Provider Controller")
public class DeptController {

    @Autowired
    private DeptService deptService;

    //注册DiscoveryClient,注意此时要导入的包是SpringCloud的
    //获取一些配置的信息,得到具体的微服务
    @Autowired
    private DiscoveryClient client;

    @ApiOperation("通过部门编号获得一个部门的信息")
    @GetMapping("/dept/get/{id}")
    //只要失败,调用对应的方法
    @HystrixCommand(fallbackMethod = "hystrixGet")
    public Dept get(@PathVariable("id") @ApiParam("部门的id") Long id){
        Dept dept = deptService.queryById(id);

        //如果id不存在,会返回null,这里抛出异常
        if (dept == null) {
            throw new RuntimeException("id => " + id + ",不存在该用户,或者信息无法找到!");
        }

        return dept;
    }

    //备选方法 ==> 当查询的id不存在,创建对应id的对象,name字段放入提示信息,失败时返回我们创建的对象!
    public Dept hystrixGet(@PathVariable("id") @ApiParam("部门的id") Long id){
        //这里可以用链式编程,是因为我们在pojo的lombok中开启了链式编程的支持
        return new Dept()
                .setDeptno(id)
                .setDname("id => " + id + ",没有对应的信息,null ---- @Hystrix")
                .setDb_source("This database is not exist in Mysql");
    }

    //注册进来的微服务,获得一些信息(得到配置文件中的info的信息)
    @ApiOperation("微服务的信息")
    @GetMapping("/dept/discovery")
    public Object discovery() {
        //获取微服务列表的清单
        List<String> services = client.getServices();
        System.out.println("discovery => services: " + services);

        //得到一个具体的微服务,通过具体的微服务ID,applicationName(即为在配置文件中配置的该SpringBoot的名字!)
        List<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");

        for (ServiceInstance instance : instances) {
            System.out.println(
                    instance.getHost() + "\t" +
                    instance.getPort() + "\t" +
                    instance.getUri() + "\t" +
                    instance.getServiceId()
            );
        }

        //返回这个client就可以了
        return this.client;
    }

}

注意

  • 使用 @HystrixCommand 注解,并用 fallbackMethod 属性指定服务熔断后调用的方法(此处即抛出异常 ==> 不熔断的话显示为500)

  • 熔断调用的方法中,并用写Mapping的注解,和调用该方法的服务用同一个url

  • 可以将错误信息返回到对象中

3. 在主启动类中声明

package com.wang.springcloud;

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.eureka.EnableEurekaClient;

//启动类
@SpringBootApplication
//在服务启动后自动将该服务注册到Eureka中
@EnableEurekaClient
//服务发现,这样就可以监控了
@EnableDiscoveryClient
//添加对熔断的支持(启用断路器)
@EnableCircuitBreaker
public class DeptProviderHystrix_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProviderHystrix_8001.class,args);
    }
}

注意

  • 此处服务熔断要添加的是熔断器的支持 @EnableCircuitBreaker

4. Eureka中的小技巧(没什么用)

可以显示服务的IP地址(最后一行设置为true)

#Eureka配置,配置该服务注册到哪里(与Server中的url地址一致)
eureka:
  client:
    service-url:
      #向集群发布,只需要向所有的Eureka发布url就可以了
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-provider-dept-hystrix-8001  #修改Eureka上的默认描述信息
    prefer-ip-address: true

效果如下

image-20201012155743688

3. 服务降级

服务降级是发生在客户端上的,而且依附于feign,我们在使用了feign的consumer上设置

1. 编写降级的工厂类

我们在API中写降级的工厂类,从而可以被其他模块调用到

package com.wang.springcloud.service;

import com.wang.springcloud.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

//降级
@Component
public class DeptClientFallbackFactory implements FallbackFactory {
    @Override
    public DeptClientService create(Throwable throwable) {

        return new DeptClientService() {
            @Override
            public Dept queryById(Long id) {
                return new Dept()
                        .setDeptno(id)
                        .setDname("id => " + id + " 没有对应的信息,客户端提供了降级的信息,这个服务已经被关闭")
                        .setDb_source("没有数据");
            }

            @Override
            public List<Dept> queryAll() {
                return null;
            }

            @Override
            public Boolean addDept(Dept dept) {
                return null;
            }
        };
    }
}

注意

  • 要注册到SpringBoot中
  • 想要实现服务降级,要实现FallbackFactory接口,并重写方法
  • 重写方法的类型可以换成我们需要的类型(原来是Object,支持所有的类型)
  • 如果我们使用的类型为接口,要在返回值中实现该接口

2. 开启服务降级的支持

开启服务降级,只需要在对应的客户端的配置文件中启用即可

#开启降级feign.hystrix
feign:
  hystrix:
    enabled: true

4. 服务熔断与服务降级的对比

服务熔断

  • 服务端
  • 某个服务超时或异常,引起服务熔断,相当于保险丝

服务降级

  • 客户端
  • 从网站整体的请求负载考虑,当某个服务熔断或者关闭之后,服务将不再被调用,此时在客户端我们可以准备一个 FallbackFactory,返回一个默认的值(缺省值),整体的服务水平下降了,比直接挂掉强

相同点

  • 目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;

  • 最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;

  • 粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改);

  • 自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段;

不同点

  • 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;

  • 管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始)

5. Hystrix Dashboard流量监控

Hystrix提供了一个可视化的流量监控

1. Dashboard的编写

1. 导入依赖

<?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">
    <parent>
        <artifactId>SpringCloud</artifactId>
        <groupId>com.wang</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>SpringCloud-consumer-hystrix-dashboard</artifactId>

    <!--实体类以及Web-->
    <dependencies>
        <dependency>
            <groupId>com.wang</groupId>
            <artifactId>SpringCloud-API</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--热部署工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
        </dependency>
        <!--Ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--Eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--Hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--Hystrix Dashboard-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    </dependencies>


</project>

注意

  • 此监控是在客户端的,因此与被监控的客户端的依赖基本相同,区别是要多配置一个 hystrix-dashboard

2. 编写配置文件

server:
  port: 9002

注意

  • 这里配置好端口号就好了,注意配置的端口是空闲的端口

3. 配置主启动类

package com.wang.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
//开启Hystrix Dashboard
@EnableHystrixDashboard
public class DeptConsumerDashboard_9002 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerDashboard_9002.class,args);
    }
}

注意

  • 在主启动类使用注解 @EnableHystrixDashboard 来开启Hystrix Dashboard

2. 被监控的微服务的编写

1. 前提

注意,微服务被Hystrix Dashboard监控需要满足以下两点

  • 添加了Hystrix依赖
  • 添加了actuator依赖

2. 在主启动类配置Servlet

由于Hystrix Dashboard要求微服务注册一个URL地址,我们在SpringBoot中使用 ServletRegistrationBean 类型来注册一个Servlet的Bean

package com.wang.springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

//启动类
@SpringBootApplication
//在服务启动后自动将该服务注册到Eureka中
@EnableEurekaClient
//服务发现,args);
    }

    //增加一个Servlet的Bean
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet() {
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        registrationBean.addUrlMappings("/hystrix/actuator/hystrix.stream");
        return registrationBean;
    }
}

注意

  • 这里写的URLMapping就是我们在DashBoard中监控的地址的后缀,前面为localhost: 端口号
  • 这里是固定的写法!

3. Hystrix Dashboard

启动Eureka,Provider和DashBoard,访问dashboard下的 /hystrix,输入微服务的URL即可查看

image-20201012222112219

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原理介绍,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。传统事务中回滚点的使...
今天小编给大家分享的是一文解析spring中事务的传播机制,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获...
这篇文章主要介绍了SpringCloudAlibaba和SpringCloud有什么区别,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。Spring Cloud Netfli...
本篇文章和大家了解一下SpringCloud整合XXL-Job的几个步骤。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。第一步:整合pom文件,在S...
本篇文章和大家了解一下Spring延迟初始化会遇到什么问题。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。List 坑列表 = new ArrayList(2);...
这篇文章主要介绍了怎么使用Spring提供的不同缓存注解实现缓存的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇...
本篇内容主要讲解“Spring中的@Autowired和@Resource注解怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学...
今天小编给大家分享一下SpringSecurity怎么定义多个过滤器链的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家
这篇文章主要介绍“Spring的@Conditional注解怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring的@Con...
这篇文章主要介绍了SpringCloudGateway的熔断限流怎么配置的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringCloud&nb...
今天小编给大家分享一下怎么使用Spring解决循环依赖问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考
这篇文章主要介绍“Spring事务及传播机制的原理及应用方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Sp...
这篇“SpringCloudAlibaba框架实例应用分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价
本篇内容主要讲解“SpringBoot中怎么使用SpringMVC”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习...
这篇文章主要介绍“SpringMVC适配器模式作用范围是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringMVC
这篇“导入SpringCloud依赖失败如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要讲解了“SpringMVC核心DispatcherServlet处理流程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来
今天小编给大家分享一下SpringMVCHttpMessageConverter消息转换器怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以...
这篇文章主要介绍“Spring框架实现依赖注入的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring框架...
本篇内容介绍了“Spring单元测试控制Bean注入的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下