Hystrix的熔断与降级

Hystrix的熔断与降级

1、熔断即服务发生错误时,并不是变成500或其他错误中,而是跳转到一个错误页面中

1)先配置eureka
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</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-actuator</artifactId>
    </dependency>
</dependencies>

主启动类

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

yml文件:

server:
  port: 7001
spring:
  application:
    name: EurekaServer7001
eureka:
  client:
    register-with-eureka: false # 是否需要注册自己
    fetch-registry: false # 是否需要从注册中心拉去服务 不需要拉取服务
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  instance:
    hostname: localhost # 主机名
2、配置服务提供者

导入依赖

这是springcloud-api的依赖

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
        <version>2.1.5</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>
<dependencies>

    <dependency>
        <groupId>org.example</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</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-actuator</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.26</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.0</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.3</version>
    </dependency>


    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
        <version>2.1.5</version>
    </dependency>


</dependencies>
server:
  port: 8001

spring:
  application:
    name: springcloud-provider-8001 # 名字
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db05?useUnicode=true
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
mybatis:
  type-aliases-package: com.ycz.springCloud.entity
  configuration:
    map-underscore-to-camel-case: true # 开启驼峰映射
  mapper-locations: classpath:mapper/*.xml
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/ # 注册的地址
  instance:
    instance-id: provider_8001

mapper

import com.ycz.springCloud.entity.Movie;
import org.apache.ibatis.annotations.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;

/**
 * (Movie)表数据库访问层
 *
 * @author makejava
 * @since 2021-12-17 09:12:13
 */
@Mapper
public interface MovieMapper extends tk.mybatis.mapper.common.Mapper<Movie>,MySqlMapper<Movie> {


}

service

package com.ycz.springCloud.service;

import com.ycz.springCloud.entity.Movie;


/**
 * (Movie)表服务接口
 *
 * @author makejava
 * @since 2021-12-17 09:12:14
 */
public interface MovieService {


    Object getAll();

    Object getOne(Integer id);
}

serviceImpl

package com.ycz.springCloud.service.impl;

import com.ycz.springCloud.entity.Movie;
import com.ycz.springCloud.mapper.MovieMapper;
import com.ycz.springCloud.service.MovieService;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * (Movie)表服务实现类
 *
 * @author makejava
 * @since 2021-12-17 09:12:15
 */
@Service("movieService")
public class MovieServiceImpl implements MovieService {

    @Autowired
    private MovieMapper movieMapper;


    public Object getAll() {
        return movieMapper.selectAll();
    }

    public Object getOne(Integer id) {
        return movieMapper.selectByPrimaryKey(id);
    }
}

controller

import com.ycz.springCloud.entity.Movie;
import com.ycz.springCloud.service.MovieService;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;


/**
 * (Movie)表控制层
 *
 * @author makejava
 * @since 2021-12-17 09:12:12
 */
@RestController
@RequestMapping("movie")
public class MovieController {
    /**
     * 服务对象
     */
    @Autowired
    private MovieService movieService;

    @RequestMapping("getAll")
    public Object getAll(){
       return movieService.getAll();
    }

    @RequestMapping("/getOne/{id}")
    public Object getOne(@PathVariable Integer id){
        return movieService.getOne(id);
    }


}
3、配置消费者

1)导入依赖

<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
        <exclusions>
            <exclusion>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

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

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

</dependencies>

2)配置负载均衡

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 ApplicationConfig {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }


}

application.yml的配置

server:
  port: 9005
spring:
  application:
    name: userconsumer-9005



## 服务降级
feign:
  hystrix:
    enabled: true
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: userconsumer-9005

service:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;


@FeignClient(value = "SPRINGCLOUD-PROVIDER-8001",fallbackFactory = UserServiceFallBackFactory.class)
public interface UserService {


    @RequestMapping("/movie/getAll")
     Object getAll();

    @RequestMapping("/movie/getOne/{id}")
    Object get(@PathVariable("id") Integer id);
}

服务降级

import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

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

@Component
public class UserServiceFallBackFactory implements FallbackFactory<UserService> {
    @Override
    public UserService create(Throwable throwable) {
        return new UserService() {
            @Override
            public Object getAll() {
                Map<String,Object> resultMap=new HashMap<>();
                resultMap.put("code",4445);
                resultMap.put("msg","降级,无id");
                return resultMap;
            }

            @Override
            public Object get(Integer id) {
                Map<String,Object> resultMap=new HashMap<>();
                resultMap.put("code",4444);
                resultMap.put("msg","降级,无id");
                return resultMap;
            }
        };
    }
}

Controller

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.ycz.springCloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RequestMapping("/user/feign")
@RestController
@PropertySource("classpath:application.yml")
public class UserFeignController {

    @Value("${server.port}")
    private String port;

    @Autowired
    private UserService userService;

    @RequestMapping("/getAll")
    @HystrixCommand(fallbackMethod = "error")
    public Object getAll(){
//        int i=1/0;
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("code",200);
        resultMap.put("port",port);
        resultMap.put("data",userService.getAll());
        return resultMap;
    }

    public Object error(){
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("code",40000002);
        resultMap.put("port",port);
        resultMap.put("msg","错误");
        resultMap.put("data",null);
        return resultMap;
    }

    @RequestMapping("/get/{id}")
    public Object get(@PathVariable("id") Integer id){
        return userService.get(id);
    }

}

主启动类:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.ycz.springCloud")
@EnableCircuitBreaker // 熔断
@EnableHystrix //降级?
public class UserConsumer_9005 {
    public static void main(String[] args) {
        SpringApplication.run(UserConsumer_9005.class,args);
    }
}

测试

先打开eureka,再打开服务提供者,再打开消费者

显示都注册上

打开服务测试:
在这里插入图片描述
请添加图片描述

测试服务熔断

    @RequestMapping("/getAll")
    @HystrixCommand(fallbackMethod = "error")
    public Object getAll(){
       int i=1/0; //这里显示一个错误,看下面会发生什么事情
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("code",200);
        resultMap.put("port",port);
        resultMap.put("data",userService.getAll());
        return resultMap;
    }

    public Object error(){
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("code",40000002);
        resultMap.put("port",port);
        resultMap.put("msg","错误");
        resultMap.put("data",null);
        return resultMap;
    }

测试:

请添加图片描述

现在把提供者的服务关了

有熔断机制的会走熔断
请添加图片描述

无熔断机制的会走降级

请添加图片描述


版权声明:本文为weixin_48319193原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。