ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第112天学习打卡(SpringCloud Feign:使用接口方式调用服务 Hystrix Dashboard)

2021-04-30 22:03:16  阅读:140  来源: 互联网

标签:Feign Hystrix springcloud springframework dept import org 打卡 com


Feign:使用接口方式调用服务

springcloud-consumer-dept-feign

导入依赖: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>springcloud</artifactId>
         <groupId>com.kuang</groupId>
         <version>1.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 ​
     <artifactId>springcloud-api</artifactId>
 ​
     <properties>
         <maven.compiler.source>8</maven.compiler.source>
         <maven.compiler.target>8</maven.compiler.target>
     </properties>
 ​
     <dependencies>
 ​
         <!--       feign-->
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-feign</artifactId>
             <version>1.4.6.RELEASE</version>
         </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
         </dependency>
     </dependencies>
 ​
 </project>

config

ConfigBean.java

 package com.kuang.springcloud.config;
 ​
 ​
 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.client.RestTemplate;
 ​
 @Configuration
 public class ConfigBean { // @Configuration 相当于---spring 里面的applicationContext.xml
 ​
     //配置负载均衡实现RestTemplate
     //IRule
     // AvailabilityFilteringRule :会先过滤掉,跳闸,访问故障的服务,对剩下的进行轮询
     // RoundRobinRule: 轮询
     //RandomRule: 随机
     // RetryRule: 会先按照轮询获取服务~,如果服务获取失败,则会在指定的时间内进行重试
 ​
 ​
     @Bean
     @LoadBalanced//Ribbon
     public RestTemplate getRestTemplate(){
         return new RestTemplate();
    }
 ​
 ​
 }
 ​

controller

DeptConsumerController.java

 package com.kuang.springcloud.controller;
 ​
 import com.kuang.springcloud.pojo.Dept;
 import com.kuang.springcloud.service.DeptClientService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.client.RestTemplate;
 ​
 import java.util.List;
 ​
 @RestController
 public class DeptConsumerController {
 ​
    @Autowired
    private DeptClientService service = null;
 ​
     @RequestMapping("/consumer/dept/add")
     public boolean add(Dept dept){
         return this.service.addDept(dept);
 ​
    }
 ​
     @RequestMapping("/consumer/dept/get/{id}")
     public Dept get(@PathVariable("id")Long id) {
         return this.service.queryById(id);
 ​
 ​
 ​
    }
     @RequestMapping("/consumer/dept/list")
     public List<Dept> list(){
         return this.service.queryAll();
 ​
    }
 ​
 ​
 ​
 ​
 }
 ​

 

FeignDeptConsumer.java

 package com.kuang.springcloud;
 ​
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.annotation.ComponentScan;
 ​
 //Ribbon和Eureka整合以后,客户端可以直接调用 不用关心IP地址和端口号
 @SpringBootApplication
 @EnableEurekaClient
 @EnableFeignClients(basePackages = {"com.kuang.springcloud"})
 @ComponentScan("com.kuang.springcloud")
 public class FeignDeptConsumer_80 {
     public static void main(String[] args){
         SpringApplication.run( FeignDeptConsumer_80.class,args);
    }
 }
 ​

application.yml

 server:
  port: 80
 ​
 ​
   # Eureka配置
 eureka:
  client:
    register-with-eureka: false # 不向Eureka 注册自己
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
 ​

springcloud-api

pojo

Dept.java

 package com.kuang.springcloud.pojo;
 ​
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.experimental.Accessors;
 ​
 import java.io.Serializable;
 @Data
 @NoArgsConstructor
 @Accessors(chain = true)//链式写法
 //所有的实体类务必实现序列化
 public class Dept implements Serializable {// Dept 实体类 ,orm 对象关系映射(列表关系映射)   mysql里面的表 对应----dept这个类
     private Long deptno;//主键
     private String dname;
     //这个数据存在哪个数据库的字段, 微服务, 一个服务对应一个数据库 同一个信息可能存在不同的数据库所以这里要用 db_source作为区分
     private String db_source;
 //构造器只需要一个就行 deptno主键自增   db_source:数据库函数自动生成
     public Dept(String dname) {
         this.dname = dname;
    }
 ​
 ​
     /*
 ​
     链式写法:
     Dept dept = new Dept();
     dept.setDeptNo(11).setDname('ssss').setDb_source('00') 链式写法就是可以连续的点下一个 而不用分开写
 ​
 ​
      */
 }
 ​

service

DeptClientService.java

 package com.kuang.springcloud.service;
 ​
 import com.kuang.springcloud.pojo.Dept;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 ​
 import java.util.List;
 ​
 @Component
 @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
 public interface DeptClientService {
 ​
     @GetMapping("/dept/get/{id}")
     public Dept queryById(@PathVariable("id") Long id);
 ​
     @GetMapping("/dept/list")
     public List<Dept> queryAll();
 ​
     @PostMapping("/dept/add")
     public boolean addDept(Dept dept);
 ​
 }
 ​

导入的依赖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>springcloud</artifactId>
         <groupId>com.kuang</groupId>
         <version>1.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 ​
     <artifactId>springcloud-api</artifactId>
 ​
     <properties>
         <maven.compiler.source>8</maven.compiler.source>
         <maven.compiler.target>8</maven.compiler.target>
     </properties>
 ​
     <dependencies>
 ​
         <!--       feign-->
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-feign</artifactId>
             <version>1.4.6.RELEASE</version>
         </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
         </dependency>
     </dependencies>
 ​
 </project>

虽然这里面的service @ComponentScan 出现爆红 但是好像没有影响

先启动7001 端口 再启动8001 8002 然后是FeignDeptConsumer_80端口

访问的结果显示:localhost/consumer/dept/list

image-20210430112553959

 

分布式系统面临的问题

复杂分布式系统结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败!

服务雪崩

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

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

我们要 弃车保帅

什么是Hystrix

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

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

能干嘛

  • 服务降级

  • 服务熔断

  • 服务限流

  • 接近实时的监控

  • ...

官网:Home · Netflix/Hystrix Wiki · GitHub

什么是服务熔断

是什么

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

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

springcloud-provider-dept-hystrix-8001

controller

DeptController.java

 package com.kuang.springcloud.controller;
 ​
 import com.kuang.springcloud.pojo.Dept;
 import com.kuang.springcloud.service.DeptService;
 import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RestController;
 ​
 ​
 //Controller提供restful服务
 @RestController  //以json格式传输
 public class DeptController {
     @Autowired //这里就体现了controller调service层
     private DeptService deptService;
 ​
     @GetMapping("/dept/get/{id}")
     @HystrixCommand(fallbackMethod = "hystrixGet") //只要失败 就会调用 hystrixGet
     public Dept get(@PathVariable("id") Long id){
         Dept dept = deptService.queryById(id);
         if(dept==null){
             throw new RuntimeException("id=>" + id + ",不存在该用户,或者信息无法找到");//运行时异常
 ​
        }
         return  dept;
    }
 ​
     //备选方案
     public Dept hystrixGet(@PathVariable("id") Long id){
         return new Dept()
                .setDeptno(id)
                .setDname("id=>"+id+"没有对应的信息, null--@Hystrix")
                .setDb_source("no this database in MySQL");
    }
 ​
 ​
 ​
 }
 ​

dao

DeptDao.java

 package com.kuang.springcloud.dao;
 ​
 import com.kuang.springcloud.pojo.Dept;
 import org.apache.ibatis.annotations.Mapper;
 import org.springframework.stereotype.Repository;
 ​
 import java.util.List;
 ​
 @Mapper
 @Repository //被spring托管
 public interface DeptDao {
 ​
     public boolean addDept(Dept dept);
     public Dept queryById(Long id);//查询部门信息
     public List<Dept> queryAll();
 ​
 }
 ​

service

DeptService.java

 package com.kuang.springcloud.service;
 ​
 import com.kuang.springcloud.pojo.Dept;
 ​
 import java.util.List;
 ​
 public interface DeptService {
     public boolean addDept(Dept dept);
     public Dept queryById(Long id);
     public List<Dept> queryAll();
 }
 ​

DeptServiceImpl.java

 package com.kuang.springcloud.service;
 ​
 import com.kuang.springcloud.dao.DeptDao;
 import com.kuang.springcloud.pojo.Dept;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 ​
 import java.util.List;
 ​
 @Service
 public class DeptServiceImpl implements DeptService{
 ​
     @Autowired
     private DeptDao deptDao;
     @Override
     public boolean addDept(Dept dept) {
         return deptDao.addDept(dept);
    }
 ​
     @Override
     public Dept queryById(Long id) {
         return deptDao.queryById(id);
    }
 ​
     @Override
     public List<Dept> queryAll() {
         return deptDao.queryAll();
    }
 }
 ​

DeptProviderHystrix_8001.java

 package com.kuang.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 //添加对熔断的支持
 public class DeptProviderHystrix_8001 {
     public static void main(String[] args){
         SpringApplication.run(DeptProviderHystrix_8001.class,args);
    }
 }
 ​

resources

mybatis

mybatis-config.xml

 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE configuration
         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 <configuration>
   <settings>
 <!-- 一级缓存是默认的   开启二级缓存-->
       <setting name="cacheEnabled" value="true"/>
   </settings>
 </configuration>
 ​

mapper

DeptMapper.xml

 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.kuang.springcloud.dao.DeptDao">
     <insert id="addDept" parameterType="Dept">
        insert into dept (dname,db_source)
        values (#{dname},DATABASE())
     </insert>
     <select id="queryById" resultType="Dept" parameterType="Long">
        select * from dept where deptno = #{deptno};
     </select>
 ​
     <select id="queryAll" resultType="Dept">
        select * from dept;
     </select>
 ​
 </mapper>
 ​

application.yml

 server:
  port: 8001
 ​
 mybatis:
  type-aliases-package: com.kuang.springcloud.pojo
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml
 ​
 ​
 ​
 spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource # 3个服务名称一致, 只是请求不一样了
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
 ​
 # Eureka的配置,服务注册到哪里
 eureka:
  client:
    service-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上的默认描述信息
 ​
 # info 配置
 info:
  app.name: kuangshen-springcloud
  company.name: blog.kuangstudy.com
 ​

 

导入的依赖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>springcloud</artifactId>
         <groupId>com.kuang</groupId>
         <version>1.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 ​
     <artifactId>springcloud-provider-dept-hystrix-8001</artifactId>
 ​
     <properties>
         <maven.compiler.source>8</maven.compiler.source>
         <maven.compiler.target>8</maven.compiler.target>
     </properties>
     <dependencies>
 <!--hystrix-->
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-hystrix</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>
         <!-- actuator完善监控信息-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
 ​
         </dependency>
 ​
         <dependency>
             <groupId>com.kuang</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-test</artifactId>
         </dependency>
 ​
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
 ​
         </dependency>
 ​
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-jetty</artifactId>
         </dependency>
 ​
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-devtools</artifactId>
 ​
         </dependency>
 ​
     </dependencies>
 ​
 </project>

修改springcloud-consumer-dept-80 里面的myrule中的Kuangrule 把自定义KuangRandomRule 去掉 ,这样访问页面时可以不断跳转而不崩溃

 package com.kuang.myrule;
 ​
 import com.netflix.loadbalancer.IRule;
 ​
 import com.netflix.loadbalancer.RoundRobinRule;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 ​
 @Configuration
 public class KuangRule {
     @Bean
     public IRule myRule(){
         return new RoundRobinRule();//默认为轮询,现在自定义了KuangRandomRule
    }
 }
 ​

 

先启动7001 端口 再启动7002端口 再启动 springcloud-provider-dept-hystrix-8001端口 再启动80端口

测试结果:

image-20210430165741300

 

image-20210430165830993

image-20210430165911536

目录

image-20210430170001960

 

访问正常的springcloud-provider-dept-8001

修改DeptController.java

 package com.kuang.springcloud.controller;
 ​
 import com.kuang.springcloud.pojo.Dept;
 import com.kuang.springcloud.service.DeptService;
 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.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RestController;
 ​
 import java.util.List;
 ​
 //Controller提供restful服务
 @RestController  //以json格式传输
 public class DeptController {
     @Autowired //这里就体现了controller调service层
     private DeptService deptService;
     //获取一些配置的信息,得到具体的微服务
     @Autowired
     private DiscoveryClient client;
 ​
     @PostMapping("/dept/add")//添加请求一般以post提交 get不安全
     public boolean addDept(Dept dept){
         return deptService.addDept(dept);
 ​
    }
     @GetMapping("/dept/get/{id}")
     public Dept get(@PathVariable("id") Long id){
         Dept dept = deptService.queryById(id);
         if (dept==null){
             throw new RuntimeException("Fail");
        }
         return dept;
    }
     @GetMapping ("/dept/list")
     public List<Dept> queryAll(){
         return deptService.queryAll();
    }
 ​
     //注册进来的微服务~ 获取一些消息~
     @GetMapping("/dept/discovery")
     public Object discovery(){
         // 获取微服务列表的清单
         List<String> services = client.getServices();
         System.out.println("discovery=>services:" + services);
         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()
 ​
            );
 ​
 ​
        }
         return this.client;
 ​
 ​
    }
 ​
 }
 ​

把启动的7001 端口 7002端口 springcloud-provider-dept-hystrix-8001端口80端口 中停止springcloud-provider-dept-hystrix-8001端口 然后启动springcloud-provider-dept-8001

测试结果

image-20210430170819414

访问不存在的出现的页面 会报错 而不是向上面启动熔断机制那样显示信息

image-20210430170914235

 

修改application.yml

 server:
  port: 8001
 ​
 mybatis:
  type-aliases-package: com.kuang.springcloud.pojo
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml
 ​
 ​
 ​
 spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource # 3个服务名称一致, 只是请求不一样了
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
 ​
 # Eureka的配置,服务注册到哪里
 eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
 ​
  instance:
    instance-id: springcloud-provider-dept8001 # 修改eureka上的默认描述信息
    prefer-ip-address: true # true 可以显示服务的IP地址
 ​
 # info 配置
 info:
  app.name: kuangshen-springcloud
  company.name: blog.kuangstudy.com
 ​

 

image-20210430171724440

 

image-20210430172149004

 

image-20210430172129050

Hystrix:服务降级

修改springcloud-api

DeptClientService.java

 package com.kuang.springcloud.service;
 ​
 import com.kuang.springcloud.pojo.Dept;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 ​
 import java.util.List;
 ​
 @Component
 @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class)
 public interface DeptClientService {
 ​
     @GetMapping("/dept/get/{id}")
     public Dept queryById(@PathVariable("id") Long id);
 ​
     @GetMapping("/dept/list")
     public List<Dept> queryAll();
 ​
     @PostMapping("/dept/add")
     public boolean addDept(Dept dept);
 ​
 }
 ​

 

DeptClientServiceFallbackFactory.java

 package com.kuang.springcloud.service;
 ​
 import com.kuang.springcloud.pojo.Dept;
 import feign.hystrix.FallbackFactory;
 import org.springframework.stereotype.Component;
 ​
 import java.util.List;
 // 降级
 @Component
 public class DeptClientServiceFallbackFactory 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 false;
            }
        };
    }
 }
 ​

修改springcloud-consumer-dept-feign的application.yml

 server:
  port: 80
 # 开启降级feign.hystrix
 feign:
  hystrix:
    enabled: true
 ​
   # Eureka配置
 eureka:
  client:
    register-with-eureka: false # 不向Eureka 注册自己
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
 ​

 

服务降级在客户端 服务熔断在服务端

测试:先启动7001 然后启动8001(springcloud-proviser-sept-8001) ,80(springcloud-consumer-dept-feign),然后在把8001停掉

测试结果:

image-20210430195151421

 

Hystrix: Dashboard 流监控

springcloud-consumer-hystrix-dashboard

导入依赖:

 <?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.kuang</groupId>
         <version>1.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 ​
     <artifactId>springcloud-consumer-hystrix-dashboard</artifactId>
 ​
     <properties>
         <maven.compiler.source>8</maven.compiler.source>
         <maven.compiler.target>8</maven.compiler.target>
     </properties>
     <!--实体类+web-->
     <dependencies>
 <!--        hystrix依赖-->
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-hystrix</artifactId>
             <version>1.4.6.RELEASE</version>
         </dependency>
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
             <version>1.4.6.RELEASE</version>
         </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>
 ​
         <dependency>
             <groupId>com.kuang</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>
     </dependencies>
 ​
 ​
 </project>

application.yml

 server:
  port: 9001

DeptConsumerDashboard_9001.java

 package com.kuang.springcloud;
 ​
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
 ​
 @SpringBootApplication
 @EnableHystrixDashboard //开启监控页面
 public class DeptConsumerDashboard_9001 {
     public static void main(String[] args){
         SpringApplication.run(DeptConsumerDashboard_9001.class,args);
    }
 }
 ​

springclou-provider-dept-hystrix-8001 修改 DeptProviderHystrix.java

 package com.kuang.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
 @EnableEurekaClient//在服务启动后自动注册到Eureka中
 @EnableDiscoveryClient //服务发现
 @EnableCircuitBreaker //添加对熔断的支持
 public class DeptProviderHystrix_8001 {
     public static void main(String[] args){
         SpringApplication.run(DeptProviderHystrix_8001.class,args);
    }
     //增加一个Servlet
     @Bean
     public ServletRegistrationBean hystrixMetricsStreamServlet(){
         ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
         registrationBean.addUrlMappings("/actuator/hystrix.stream");//访问这个页面就可以被监控了
         return registrationBean;
    }
 }
 ​
 ​
 ​

先启动7001 端口 再启动9001端口 然后启动DeptProviderHystrix_8001端口

 

测试结果图

image-20210430205846158

 

image-20210430205952150

 

 

image-20210430210709594

 

image-20210430210758438

 

image-20210430210910757

 

 

  • 如何看

    • 七色

      image-20210430211121645

 

    • 一圈

    • 实心圆:公有两种含义,他通过颜色的变化代表了实例的健康程度

      它的健康程度从绿色(安全) <黄色 <橙色 <红色 递减

      该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大,该实心圆就越大,所以通过该实心圆的展示,就可以在大量的实例中快速发现故障实例和高压力实例

image-20210430211730357

  • 一线

  • 曲线:用来记录2分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势!

image-20210430211928110

 

  • 整图说明

    image-20210430212622661

  •  

标签:Feign,Hystrix,springcloud,springframework,dept,import,org,打卡,com
来源: https://www.cnblogs.com/doudoutj/p/14723416.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有