完整源码-仅供参考

https://github.com/ChannD/SpringCloudDemo

1. 概述

1. 分布式系统面临的问题

  • 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
  • 服务雪崩
    • 多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的 “扇出(一把扇子慢慢的打开,层层递出,有一个打不开整个扇子也打不开)”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”.
    • 对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
      image.png

2. 是什么

  • Hystrix是一个用于处理分布式系统的延迟容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
  • “断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝), 向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常, 这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

3. 能干嘛

  • 服务降级
  • 服务熔断
  • 服务限流
  • 接近实时的监控
  • ...

4. Github官网资料


2. 服务熔断

1. 是什么?

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

2. 参考microservicecloud-provider-dept-8001项目新建新建microservicecloud-provider-dept-hystrix-8001项目(大致的代码复制过来即可)

3. 修改POM[新增代码]

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

4. 修改YML[也就是修改下服务名称]

instance-id: microservicecloud-dept8001-hystrix

5. 修改DeptController

  • 一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法[如图]
  • image.png

6. 修改主启动类DeptProvider8001_Hystrix_App并添加新注解@EnableCircuitBreaker[完整代码]

package com.chann.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
@EnableEurekaClient //本服务启动后会自动注册进eureka服务中
@EnableDiscoveryClient //服务发现
@EnableCircuitBreaker//对hystrixR熔断机制的支持
public class DeptProvider8001_Hystrix_App
{
    public static void main(String[] args)
    {
        SpringApplication.run(DeptProvider8001_Hystrix_App.class, args);
    }
}

7. 测试

  • 3个eureka先启动
  • 主启动类DeptProvider8001_Hystrix_App
  • Consumer启动microservicecloud-consumer-dept-80
  • http://localhost/consumer/dept/get/112
  • 返回JSON如下[如果对应的ID:112,数据库里面没有这个记录,我们报错后统一返回。]
{
  "deptno": 112,
  "dname": "该ID:112没有没有对应的信息,null--@HystrixCommand",
  "db_source": "no this database in MySQL"
}

3. 服务降级

1. 是什么

  • 整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。
  • 一般是从整体负荷考虑,就是当某个服务熔断后, 服务器将不再被调用, 此时客户端可以自己准备一个本地的fallback回调, 返回一个缺省值. 这样做虽然服务水平下降,但是好歹可用,比直接挂掉强!
  • 而且刚刚服务熔断,每个方法都需要有个处理,这样容易出现两个问题, 一是方法膨胀,第二根据Spring原则 , AOP面向切面, 既然是SpringCloud那么spring的概念应该是可以沿用的, 那么服务降级可以实现解耦和分离!

2. 服务降级处理是在客户端实现完成的,与服务端没有关系

3. 修改microservicecloud-api工程,根据已经有的DeptClientService接口新建一个实现了FallbackFactory接口的类DeptClientServiceFallbackFactory

  • 千万不要忘记在类上面新增@Component注解,大坑!!!
  • 统一的放入这个方法进行处理,实现之前的解耦
  • [完整代码]
package com.chann.springcloud.service;

import com.chann.springcloud.entities.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

@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)
                        .setDname("该ID:"+id+"没有没有对应的信息,Consumer客户端提供的降级信息,此刻服务Provider已经关闭")
                        .setDb_source("no this database in MySQL");
            }

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

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

    }
}

4. 修改microservicecloud-api工程,DeptClientService接口在注解@FeignClient中添加fallbackFactory属性值[代码]

//这个接口里面的任何方法出了问题,都找DeptClientServiceFallbackFactory, 实现处理[一锅端]
@FeignClient(value = "MICROSERVICECLOUD-DEPT", fallbackFactory=DeptClientServiceFallbackFactory.class)

5. microservicecloud-api工程

6. microservicecloud-consumer-dept-feign工程修改YML[新增代码]

feign: 
  hystrix: 
    enabled: true

7. 测试

  • 3个eureka先启动
  • 微服务microservicecloud-provider-dept-8001启动
  • microservicecloud-consumer-dept-feign启动
  • 正常访问测试[http://localhost/consumer/dept/get/1]
{
  "deptno": 1,
  "dname": "开发部",
  "db_source": "cloudDB01"
}
  • 故意关闭微服务 microservicecloud-provider-dept-8001
{
  "deptno": 1,
  "dname": "该ID:1没有没有对应的信息,Consumer客户端提供的降级信息,此刻服务Provider已经关闭",
  "db_source": "no this database in MySQL"
}
  • 客户端自己调用提示
    • http://localhost/consumer/dept/get/1
    • 此时服务端provider已经down了,但是我们做了服务降级处理,让客户端在服务端不可用时也会获得提示信息而不会挂起耗死服务器

4. 服务监控hystrixDashboard

1. 概述

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

2. 新建工程microservicecloud-consumer-hystrix-dashboard

3. POM [完整代码]

<?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>microservicecloud</artifactId>
        <groupId>com.chann.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

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

    <dependencies>
        <!-- 自己定义的api -->
        <dependency>
            <groupId>com.chann.springcloud</groupId>
            <artifactId>microservicecloud-api</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 修改后立即生效,热部署 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!-- Ribbon相关 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!-- feign相关 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</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>

4. YML[完整代码]

server:
  port: 9001

5. 主启动类改名+新注解@EnableHystrixDashboard [代码]

package com.chann.springcloud;

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

@SpringBootApplication
@EnableHystrixDashboard
public class DeptConsumer_DashBoard_App
{
    public static void main(String[] args)
    {
        SpringApplication.run(DeptConsumer_DashBoard_App.class,args);
    }
}

6. 所有Provider微服务提供类(8001/8002/8003)都需要监控依赖配置 [新增]

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

7. 启动microservicecloud-consumer-hystrix-dashboard该微服务监控消费端

8. 启动3个eureka集群

9. 启动microservicecloud-provider-dept-hystrix-8001

10. 启动的相关微服务工程[如图]

image.png

11. 监控测试

  • 多次刷新http://localhost:8001/dept/get/1
  • 观察监控窗口
    • 填写监控地址
    • image.png
    • 监控结果 [可以尝试多次刷新上面的get/1]
    • 如何看?[7色, 1圈 , 1线] --[如图说明]
    • image.png
    • image.png
    • 一图
      • 实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康度从绿色<黄色<橙色<红色递减。
        该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大该实心圆就越大。所以通过该实心圆的展示,就可以在大量的实例中快速的发现故障实例和高压力实例
    • 一线
      • 曲线:用来记录2分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势。
    • 搞懂一个才能看懂复杂的 [网上找的图]
    • image.png

5. 总结

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

脸朝大海, 春暖花开 ----江大脸