前言

分布式系统面临的问题

复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。不做任何处理的情况下,很容易导致服务雪崩。

服务雪崩:多个微服务之间调用的时候,假设微服务 A 调用微服务 B 和微服务 C,微服务 B 和 微服务 C 又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务 A 的调用就会占用越来越多的系统资源,进而引起系统崩溃,这就是所谓的“服务雪崩”。

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几分钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列、线程和其它系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以免因为单个依赖关系的失败对整个应用程序或系统造成影响。

断路器

“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应,而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

服务熔断

介绍

服务熔断是应对服务雪崩的一种微服务链路保护机制。一般是某个服务故障或者异常引起,类似现实世界中的“保险丝”,当某个异常条件被触发,直接熔断整个服务,而不是一直等到此服务超时。

当扇出链路的某个微服务不可用或响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回“错误”地响应信息。 当检测到该节点微服务调用响应正常后恢复调用链路。在 SpringCloud 中的熔断机制是通过 Hystrix 实现。Hystrix 会监控微服务间的调用状况,当失败的调用到一定阈值,缺省是 5 秒内 20 次调用失败就会启动熔断机制。启用熔断机制的注解是 @HystrixCommand 。

Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多以来不可避免的会调用失败,比如超时、异常等,Hystrix 能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

使用

1、复制 "microservicecloud-provider-dept-8001" 子工程改名为 "microservicecloud-provider-dept-hystrix-8001",新增断路器依赖:

<!--Hystrix 断路器-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

2、修改微服务实例 Id:

server:
  port: 8001

mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml # mybatis 配置文件路径
  type-aliases-package: zze.springcloud.entities # 所有 Entity 别名类所在包
  mapper-locations:
    - classpath:mybatis/mapper/**/*.xml # mapper 映射文件

spring:
  application:
    name: microservicecloud-provider-dept # 当前微服务名称
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource # 数据源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver # mysql 驱动包
    url: jdbc:mysql:///springcloud_8001 # 数据库连接 root
    username: root
    password: root
    dbcp2:
      min-idle: 5 # 数据库连接池的最小维持连接数
      initial-size: 5 # 初始化连接数
      max-total: 5 # 最大连接数
      max-wait-millis: 200 # 等待连接获取的最大超时时间

eureka:
  client: # 将当前工程作为 Eureka 客户端
    service-url:
      # 单机版
      # defaultZone: http://localhost:7001/eureka # Eureka 服务端地址
      defaultZone: http://www.eurekaserver1.com:7001/eureka,http://www.eurekaserver2.com:7002/eureka,http://www.eurekaserver3.com:7003/eureka
  instance:
    instance-id: microservicecloud-provider-dept-hystrix-8001
    prefer-ip-address: true # 访问路径显示 IP

info:
  host: ${java.rmi.server.hostname}
  port: ${server.port}
  app.name: microservicecloud-provider-dept-8001
  build.artifactId: ${project.artifactId}
  build.version: ${project.version}

application.yml

3、修改 Controller,给 get 方法添加上熔断注解,指定回调方法:

package zze.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
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 zze.springcloud.entities.Dept;
import zze.springcloud.service.DeptService;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/dept")
public class DeptController {

    @Autowired
    private DeptService deptService;

    @PostMapping("/add")
    public boolean add(@RequestBody Dept dept) {
        return deptService.add(dept);
    }

    @GetMapping("/get/{id}")
    @HystrixCommand(fallbackMethod = "fallback_get") // fallbackMethod 指定回调方法名,get 方法异常时会调用指定的方法
    public Dept get(@PathVariable Long id) {
        Dept dept = deptService.get(id);
        if(null == dept){
            throw new RuntimeException("没有 id 为" + id + "的这个部门");
        }
        return dept;
    }

    /**
     * get 方法熔断回调
     */
    private Dept fallback_get(@PathVariable Long id){
        return new Dept().setDeptNo(id).setDeptName("该部门不存在").setDbSource("数据源中没有这个部门");
    }

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

zze.springcloud.controller.DeptController

4、修改主启动类,使用注解添加 Hystrix 服务熔断支持:

package zze.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker // Hystrix 熔断功能支持
public class Application_8001 {
    public static void main(String[] args) {
        SpringApplication.run(Application_8001.class, args);
    }
}

zze.springcloud.Application_8001

5、测试:

1、启动 microservicecloud-provider-dept-hystrix-8001 服务
2、访问 http://localhost:8001/dept/get/1 时正常返回数据
3、访问 http://localhost:8001/dept/get/11 时执行了熔断方法,返回了自定义的数据信息:

test

服务端(被调用端)操作,服务熔断实际上类似于异常处理,让服务在发生不可预料的异常时可控的返回一个客户端可处理的结果。

服务降级

简介

什么是服务降级?当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。

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

服务降级主要用于什么场景呢?当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,我们可以将一些不重要或不紧急的服务或任务进行服务的延迟使用或暂停使用。

使用

1、修改 "microservicecloud-provider-dept-8001" 的 Controller 模拟异常情况:

package zze.springcloud.controller;

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 zze.springcloud.entities.Dept;
import zze.springcloud.service.DeptService;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/dept")
public class DeptController {

    @Autowired
    private DeptService deptService;

    @PostMapping("/add")
    public boolean add(@RequestBody Dept dept) {
        return deptService.add(dept);
    }

    @GetMapping("/get/{id}")
    public Dept get(@PathVariable Long id) {
        Dept dept = deptService.get(id);
        if(null == dept){
            throw new RuntimeException("没有 id 为" + id + "的这个部门");
        }
        return dept;
    }

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

    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * 获取所有注册到 EurekaServer 的服务信息
     *
     * @return
     */
    @GetMapping("/discovery")
    public Object discovery() {
        Map<String, Object> map = new HashMap<>();
        // 获取所有注册到 EurekaServer 的微服务名称,对应 spring.application.name
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            // 获取对应服务所有实例
            List<ServiceInstance> instances = discoveryClient.getInstances(service);
            map.put(service, instances);
        }
        return map;
    }
}

zze.springcloud.controller.DeptController

2、修改 "microservicecloud-consumer-dept-feign" 工程,新增断路器依赖,新增熔断回调工厂类:

package zze.springcloud.service.fallback;

import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import zze.springcloud.entities.Dept;
import zze.springcloud.service.DeptClientService;

import java.util.List;

/**
 * 当 DeptClientService 的某方法调用异常时会回调下面实现 DeptClientService 的方法
 */
@Component
public class DeptClientServiceFallBackFactory implements FallbackFactory<DeptClientService> {
    @Override
    public DeptClientService create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public Dept get(Long id) {
                return new Dept().setDeptNo(id).setDeptName("该部门不存在").setDbSource("数据源中没有这个部门");
            }

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

            @Override
            public boolean add(Dept dept) {
                return false;
            }
        };
    }
}

zze.springcloud.service.fallback.DeptClientServiceFallBackFactory

3、修改 Feign 客户端接口类,指定回调工厂类:

package zze.springcloud.service;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import zze.springcloud.entities.Dept;
import zze.springcloud.service.fallback.DeptClientServiceFallBackFactory;

import java.util.List;

/*
 value 表示要调用的微服务名称
 fallbackFactory 指定调用失败时执行的熔断回调工厂类
 */
@FeignClient(value = "microservicecloud-provider-dept",fallbackFactory = DeptClientServiceFallBackFactory.class)
@RequestMapping("/dept")
public interface DeptClientService {
    @GetMapping("/get/{id}")
    public Dept get(@PathVariable("id") Long id);

    @GetMapping("/list")
    public List<Dept> list();

    @PostMapping("/add")
    public boolean add(Dept dept);
}

zze.springcloud.service.DeptClientService

4、修改配置文件,启用 Feign 的熔断功能:

server:
  port: 80

eureka:
  client:
    service-url:
      defaultZone: http://www.eurekaserver1.com:7001/eureka,http://www.eurekaserver2.com:7002/eureka,http://www.eurekaserver3.com:7003/eureka
  instance:
    instance-id: microservicecloud-provider-dept
    prefer-ip-address: true # 访问路径显示 IP

spring:
  application:
    name: microservicecloud-consumer-dept

# 启用 feign 的熔断功能
feign:
  hystrix:
    enabled: true

application.yml

5、测试:

1、启动 7001、7002、7003 Eureka 集群
2、启动 Provider 服务 microservicecloud-provider-dept-8001
3、启动 Consumer 服务 microservicecloud-consumer-dept-80
4、访问 http://localhost/consumer/dept/get/1 ,正常返回信息
5、关闭 8001 Provider 服务,再次访问 http://localhost/consumer/dept/get/1 ,返回熔断回调工厂类中自定义的信息:

test

消费端(调用端)操作,从上面测试结果中可以看到即使 Provider 服务挂了,Consumer 也可以返回可处理的数据而不是随之挂掉。

豪猪HystrixDashboard

介绍

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

使用

1、新建名为 "microservicecloud-consumer-hystrix-dashboard" 的子工程作为监控微服务工程,添加相关依赖:

<!--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>

2、新建配置文件,配置占用端口:

server:
  port: 9001

application.yml

3、新建主启动类,使用注解添加监控支持:

package zze.springcloud;

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

@SpringBootApplication
@EnableHystrixDashboard // 开启监控支持
public class Application_9001 {

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

zze.springcloud.Application_9001

4、保证所有的 Provider 服务都添加了监控依赖:

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

5、测试监控服务自身是否正常:

启动 microservicecloud-consumer-hystrix-dashboard 服务,访问 http://localhost:9001/hystrix 如果出现下面页面则测试通过:

test

6、监控测试:

1、启动 7001、7002、7003 Eureka 集群
2、启动 microservicecloud-provider-dept-hystrix-8001 带有熔断功能的 Provider 服务
3、启动 microservicecloud-consumer-dept-80 消费者服务
4、启动 microservicecloud-consumer-hystrix-dashboard 监控服务
5、访问监控服务提供的可视化 web 页,http://localhost:9001/hystrix:
6、随后出现如下界面:

7、访问被监控的服务,会发现曲线会根据访问频率发生变化

test

java框架之SpringCloud(5)-Hystrix服务熔断、降级与监控的更多相关文章

  1. java框架之SpringCloud(1)-微服务及SpringCloud介绍

    微服务概述 是什么 业界大牛 Martin Fowler 这样描述微服务: 参考[微服务(Microservices)-微服务原作者Martin Flower博客翻译]. 下面是关于上述博客中的部分重 ...

  2. dubbo学习实践(4)之Springboot整合Dubbo及Hystrix服务熔断降级

    1. springboot整合dubbo 在provider端,添加maven引入,修改pom.xml文件 引入springboot,版本:2.3.2.RELEASE,dubbo(org.apache ...

  3. java框架之SpringCloud(3)-Eureka服务注册与发现

    在上一章节完成了一个简单的微服务案例,下面就通过在这个案例的基础上集成 Eureka 来学习 Eureka. 介绍 概述 Eureka 是 Netflix 的一个子模块,也是核心模块之一.Eureka ...

  4. 【5】JMicro微服务-熔断降级

    如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl   1. 使用服务熔断降级特性,必须先启动Pubsub服务,服务监听服务,熔断器服务3个服务 先启动Pubsub及服务监听两 ...

  5. SpringCloud Netflix (五) : Hystrix 服务熔断和服务降级

    什么是Hystrix 在分布式环境中,许多服务依赖项中的一些服务依赖不可避免地会失败.Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助您控制这些分布式服务之间的交互.Hystrix通过隔离服务 ...

  6. SpringCloud实战-Hystrix请求熔断与服务降级

    我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...

  7. springcloud组件之hystrix服务熔断,降级,限流

    hystrix 简介 Hystrix是什么 在分布式环境中,许多服务依赖项中的一些必然会失败.Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互.Hystrix通过 ...

  8. Hystrix(服务熔断,服务降级)

    一.Hystrix 1.服务雪崩 多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C有调用其他的微服务,这就是所谓的”扇出”,如扇出的链路上某个微服务的调用响应式过长或者 ...

  9. spring cloud 学习(4) - hystrix 服务熔断处理

    hystrix 是一个专用于服务熔断处理的开源项目,当依赖的服务方出现故障不可用时,hystrix有一个所谓的断路器,一但打开,就会直接拦截掉对故障服务的调用,从而防止故障进一步扩大(类似中电路中的跳 ...

随机推荐

  1. [lvs]lvs的三种模式

    回顾了下lvs的三种模式的调度机制 1.lvs的dr模式中的arp的抑制,eth用自己口arp回应. 2.keepalive是否直接操作rs? 不直接操作, 只操作dr(配lvs) 3.tunnel模 ...

  2. python之字符串操作方法

    定义及特性: 以引号(单引号,双引号,三引号)包围且不能修改 a= ' \t aBcdE fgFijDlmNopq rSt uTwxy z 123 !@# \t ' 一.判断字符串,返回bool值:F ...

  3. Matlab信号处理基础

    一. 简介 离散傅立叶.离散余弦和离散小波变换是图像.音频信号常用基础操作,时域信号转换到不同变换域以后,会导致不同程度的能量集中,信息隐藏利用这个原理在变换域选择适当位置系数进行修改,嵌入信息,并确 ...

  4. bootstrapTable treegrid的使用

    最近打算自己弄一个后台,在整顿树形插件的时候,遇到问题,bootstrapTable treegrid最开始是怎么都显示不了树形,然后是数据出不来, 现在来记录下. 问题1:最开始怎么都显示不出来的问 ...

  5. 【iCore4 双核心板_ARM】例程三十二:UART_IAP_ARM实验——更新升级STM32

    实验现象及操作说明: 1.本例程共有两个代码包,APP和IAP,IAP程序功能实现将APP程序升级至STM32中. 2.直接上电或烧写程序将执行升级的APP应用程序. BIN升级文件产生方法: 1.编 ...

  6. C#时间格式化显示AM/PM

    .ToString("MM/dd/yyyy hh:mm:ss:ffff tt")); //12小时制 .ToString("MM/dd/yyyy HH:mm:ss:fff ...

  7. 【C语言】 重拾

    [C语言] 因为以前学过C语言,只不过太长时间不用,已经忘得差不多了… 所以这篇文章的性质是把C语言中一些对于现在的我不是很符合预期的知识点记录一下. ■ HelloWorld程序 HelloWorl ...

  8. mysql事务隔离级别及传播机制

    TRANSACTION(事务隔离级别) 在说明事务隔离级别之前先说一下脏读.不可重复读.幻读这三个概念. 脏读:一个事务读取到另一事务未提交的更新新据.当一个事务正在访问数据,并且对数据进行了修改,而 ...

  9. [微信小程序] 认识微信小程序及开发环境搭建

    微信公众平台首页 https://mp.weixin.qq.com 微信公众平台测试帐号系统 https://open.weixin.qq.com/connect/qrconnect?appid=wx ...

  10. 3.贝叶斯网络表示(The Bayesian Network Representation)

    对于一个n随机变量的联合分布,一般需要2**n-1个参数来表示这个分布.但是,我们可以通过随机变量之间的独立性,减少参数的个数. naive Beyes model: Bayesian Network ...