SpringCloud——Hystrix熔断/降级

简介

Hystrix断路器,又称Hystrix熔断器。它主要做SpringCloud里面的做服务熔断,服务降级的处理。它的思想和Spring里面的前置通知,环绕通知也有相似之处。

在复杂的分布式系统中,微服务之间可能有数十个依赖关系,而这些依赖关系中,总会不可避免的出现调用失败。比如A服务调用B服务,B服务又调用C服务…这也就是所谓的扇出,而在这扇出链路上,如果有一个环节出现了问题,就可能导致系统的资源被一直占用着,进而引起系统的崩溃,这并不是我们想看到的。

Hystrix就类似于保险丝,比如这会冬天到了,热得快,电热毯一下子全开,电路压力很大,如果承受不住,保险丝就会熔断,进而保证安全。Hystrix就是当某个单元出现故障,通过断路器的故障监控,向调用方法返回一个符合预期的、可处理的备选响应(fallback),而不是长时间的等待或抛出异常。SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。

熔断和降级

服务熔断:一般是某个服务故障或异常引起的,类似于现实世界的保险丝,为了防止系统雪崩,直接熔断整个服务,而不是一直等到此服务超时。服务熔断可能会带来方法膨胀和高度耦合。所以我们可以针对某个接口中的所有方法总的来做一次熔断处理。

服务降级:一般是从整体符合考虑。就是当某个服务熔断后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强。

服务降级是在客户端实现完成的,与服务端没有关系。也即客户端访问的时候,我们自身就带着一个准备好的本地的fallback回调,会返回一个缺省值。如果成功调用,则返回数据,如果不能成功调用,则返回fallback方法里的缺省值。 能访问,就访问对应的服务接口,不能访问就去找fallback回调。

搭建

Hystrix需要配置在服务提供端,即provider。我们可以拷贝之前的provider的服务的配置文件,进行一些修改。

第一步

修改pom.xml文件。在之前的pom.xml基础上,添加如下依赖。

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

第二步

在provider的controller中,我们自定义 fallback 方法。

package com.zxb.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.zxb.springcloud.bean.User;
import com.zxb.springcloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping(path = "/user/get/{id}")
    @HystrixCommand(fallbackMethod = "getFallBackData")
    public User getUserById(@PathVariable(value = "id") Integer id) {
        User user = userService.findById(id);
        if (user == null)
            throw new RuntimeException("用户不存在");
        else
            return user;
    }
	// 出现异常,会自动调用此方法
    public User getFallBackData(@PathVariable(value = "id") Integer id) {
        User user = new User();
        user.setId(id);
        user.setName("查无此人");
        user.setDbSource("查无此数据库");
        return user;
    }
    
}

第三步

配置主启动类,在主启动类上,需要加上 @EnableCircuitBreaker 注解,表示对 hystrix 熔断机制的支持。

@SpringBootApplication
@MapperScan(basePackages = {"com.zxb.springcloud.mapper"})
@EnableCircuitBreaker
@EnableEurekaClient
public class UserProvider8001_Hystrix_APP {
    public static void main(String[] args) {
        SpringApplication.run(UserProvider8001_Hystrix_APP.class, args);
    }
}

好,provider微服务配置好了。

现在通过消费者查询一个不存在的id
在这里插入图片描述

这里要注意,我们写的Fallback方法的返回类型,要和标注了 @HystrixCommand 注解的返回类型一样或者是其子类,否则会有如下错误:

Hint: Fallback method 'public java.lang.String 
com.zxb.springcloud.controller.UserController.getFallBackData(java.lang.Integer)'
must return: class com.zxb.springcloud.bean.User or its subclass错误

-----------------------------------------------------------华丽的分割线-----------------------------------------------------------

现在看似很完美,但是实则有些小问题。可能一个controller很多方法,我们一个一个去写 fallback 方法十分麻烦。并且在provider服务的controller中我们只想写一些业务逻辑相关的代码,并不想将熔断的代码也写在里面,耦合度过高。而且如果我们将provider服务停止了,这样消费者去访问,就不会出现熔断的信息,而是直接拒绝连接,出现500异常。这都是我们不想看到的。

接下来,就来解决这些问题。

之前的博客中,已经配置搭建了用Feign来进行远程调用。而消费者调用provider,靠的就是feign去调用provider的接口,如果我们将服务熔断和降级定义在这,就可以完美解决以上问题。

创建一个 FallbackFactory 接口的实现类,该接口的泛型就是Feign接口类型。

package com.zxb.springcloud.service;

import com.zxb.springcloud.bean.User;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class UserClientServiceFallbackFactory implements FallbackFactory<UserClientService> {
    @Override
    public UserClientService create(Throwable cause) {
        return new UserClientService() {
            @Override
            public User getUserById(Integer id) {
                User user = new User();
                user.setId(id);
                user.setName("该" + id + "没有对应的信息," +
                        "这是Consumer客户端提供的降级信息,此刻服务Provider已经关闭");
                user.setDbSource("查无此库");
                return user;
            }

            @Override
            public Boolean addUser(User user) {return null;}
            @Override
            public Integer deleteUser(Integer id) {return null;}
            @Override
            public void updateUser(User user) {}
            @Override
            public List<User> getUsers() {return null;}
        };
    }
}

这里注意,一定要将该实现类加入到IOC容器中,我这里使用 @Component 注解。

随后,在Feign接口上标注的 @FeignClient注解加上 fallbackFactory属性,值为我们刚定义的实现类。

@FeignClient(value = "springcloudservice-user",fallbackFactory = UserClientServiceFallbackFactory.class)

配置好后,重新将 feign 模块,mvn clean,mvn install打包,让其他引用的地方获取到最新值。

此时,我们启动注册中心,provider,consumer进行测试。

当我访问不存在的值:
在这里插入图片描述
此时假设请求过多,保持核心功能即可,关闭非核心微服务。将 provider 微服务停止。再去访问该接口。
在这里插入图片描述

服务监控

Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。

了解了概念,就整起!

搭建

新建一个模块,专门用来做服务监控。

pom.xml如下

<?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>springcloudservice</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloudservice-hystrix-dashboard</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- hystrix和 hystrix-dashboard相关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
        </dependency>
    </dependencies>

</project>

application.properties 配置如下:设置端口即可

server.port=9001

在主启动类上加一个注解:@EnableHystrixDashboard

@SpringBootApplication
@EnableHystrixDashboard // 支持 hystrix 图形化界面
public class HystrixDashboard_App {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboard_App.class, args);
    }
}

接下来注意,我们要监控微服务,那么那些微服务也要情愿被我们监控,大家要约定一个规矩。所以,所有被监控的服务,都要加上如下配置:

 <!-- actuator监控信息完善 -->
   <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-actuator</artifactId>
   </dependency>

我在三个provider微服务的pom.xml中都添加了这个依赖。配置完后,开始测试。

直接启动这个监控微服务,必须这个监控微服务启动成功没毛病,才能监控其他微服务。访问ip+port/hystrix 即可。我这里是 http://localhost:9001/hystrix

看到这个豪猪哥,则表示配置成功。
在这里插入图片描述

监控

搭建完毕,现在我们可以去监控其他微服务的健康状况、压力状况、调用状况以图形化的界面展示。

启动之前搭建好的Eureka-Server集群,再启动前面搭建的带有hystrix熔断的provider微服务。

先正常访问接口:http://localhost:8001/user/get/。然后我们看Hystrix Dashboard 主页,这里提示我们输入地址。
在这里插入图片描述

按照它的格式,在浏览器地址栏输入 http://localhost:8001/hystrix.stream并访问。
在这里插入图片描述
hystrix其实一直在ping,并且给我们返回data。但是这个界面十分的不友好。所以我们也可以设置成图形化界面。

在这里插入图片描述
在最上面的文本框输入被监控的微服务地址,我要监控谁,我就填谁。豪猪哥的placeholder也给了我们提示。我现在9001监控8001,那么我就填8001即可。那么什么格式呢?就是主机名+ip +端口号/hystrix.stream 即可。 即: http://localhost:8001/hystrix.stream。
1:Delay:该参数用来控制服务器上轮询监控信息的延迟时间,默认为2000毫秒,可以通过配置该属性来降低客户端的网络和CPU消耗。

2:Title:该参数对应了头部标题Hystrix Stream之后的内容,默认会使用具体监控实例的URL,可以通过配置该信息来展示更合适的标题。

在这里插入图片描述
随后单击 monitor,出现如下界面则成功。
在这里插入图片描述
这图怎么看呢? 七色一圈一线。
在这里插入图片描述
现在还没有任何请求到 provider,这里先记录洗状态:
在这里插入图片描述
接下来我再疯狂访问 http://localhost:8001/user/get/1 这个请求,看看这图会有啥变化。
在这里插入图片描述
我猛的访问了27次该路径,此时圆圈变大了,直线也上升了,并且27次都成功了,是绿色。
这会不访问了,圈又小了,波动也下来了。
在这里插入图片描述
图示分析:
在这里插入图片描述
再复杂点的微服务的监控图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值