服务熔断发生在服务端,重点配置 Provider
Provider 的 pom 中添加依赖
Provider 新建 Controller 定义常规方法并通过 @HystrixCommand 注解为其配置熔断回调方法
package com.kaishen.controller;
import com.kaishen.pojo.Dept;
import com.kaishen.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 部门服务 Hystrix 控制层
* @author : toby
* Create in 13:38 2022/5/9
*/
@RestController
@Slf4j
public class DeptHystrixController {
@Resource
private DeptService deptService;
/**
* 根据部门编号查询部门信息
* @param id 部门编号
* @return 返回部门信息
*/
@GetMapping("/hystrix/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixQueryDeptById")
public Dept fusingQueryDeptById(@PathVariable Long id) {
// 调用查询方法
Dept dept = deptService.queryDeptById(id);
log.info("hystrix 查询结果:" + dept);
if (null == dept) {
throw new RuntimeException("查询异常");
}
return dept;
}
/**
* 部门查询熔断方法
* @param id 部门编号
* @return 返回构建的部门实体
*/
@SuppressWarnings("unused")
public Dept hystrixQueryDeptById(@PathVariable Long id) {
return new Dept().setDeptNo(id)
.setDeptName("根据 id = " + id + " 查不到对应的部门信息,此处返回熔断信息")
.setDbSource("没有数据来源");
}
}
启动类开启熔断器 @EnableCircuitBreaker
Consumer 中通过 Feign 正常调用即可
服务降级发生在客户端,重点配置 Consumer
Consumer 端新增接口
package com.kaishen.feign.service;
import com.kaishen.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;
/**
* 支持服务降级的接口
* @author : toby
* Create in 16:52 2022/5/9
*/
@Component
@FeignClient(value = "SPRING-CLOUD-PROVIDER-DEPT", cOntextId= "3", fallbackFactory = DeptHystrixDemotionServiceFallbackFactory.class)
public interface DeptHystrixDemotionService {
/**
* 根据部门编号查询部门信息
* -- 支持服务降级
* -- application.yml 中开启服务降级后不会再去访问后端系统,此处测试降级功能省略后端方法
* @param id 部门编号
* @return 返回部门信息
*/
@GetMapping("/demotion/dept/get/{id}")
Dept demotionQueryDeptById(@PathVariable("id") Long id);
/**
* 说 Hello
* -- 定义多个方法,以供回调工厂处理
*/
@GetMapping("demotion/hello")
void sayHello();
}
自定义工厂类,实现 FallbackFactory 接口,将新建的接口作为泛型传入,重写 create 方法
package com.kaishen.feign.service;
import com.kaishen.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* 支持服务降级的回调工厂
* @author : toby
* Create in 16:57 2022/5/9
*/
@Component
public class DeptHystrixDemotionServiceFallbackFactory implements FallbackFactory
@Override
public DeptHystrixDemotionService create(Throwable cause) {
return new DeptHystrixDemotionService() {
@Override
public Dept demotionQueryDeptById(Long id) {
return new Dept().setDeptNo(id)
.setDeptName("洪峰期,暂不提供此服务")
.setDbSource("没有数据来源");
}
@Override
public void sayHello() {
System.out.println("秒杀时刻,服务降级,暂不提供此服务");
}
};
}
}
在新增的接口中开启 Feign 注解,并通过 fallbackFactory 属性指向降级回调工厂 @FeignClient(value = "SPRING-CLOUD-PROVIDER-DEPT", cOntextId= "3", fallbackFactory = DeptHystrixDemotionServiceFallbackFactory.class)
application.yml 中开启降级
# Feign 配置
feign:
hystrix:
enabled: true # 开启服务降级
新建 Module:spring-cloud-dashboard-9001
编写 pom 引入依赖
编写 application.yml
server:
port: 9001
# Spring 配置
spring:
application:
name: spring-cloud-dashboard9001
# Dashboard 配置
hystrix:
dashboard:
proxy-stream-allow-list: "*" # 允许代理的主机列表
编写启动类,开启注解
package com.kaishen;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
/**
* 监控服务启动类
* @author : toby
* Create in 19:24 2022/5/9
*/
@SpringBootApplication
@EnableHystrixDashboard
public class DashboardApplication9001 {
public static void main(String[] args) {
SpringApplication.run(DashboardApplication9001.class, args);
}
}
启动 Dashboard 可看到如下界面,则 Dashboard 配置成功
被监控的服务中需要引入 actuator 及 Hystrix 依赖
被监控服务的启动类中添加 hystrixMetricsStreamServlet,并开启 @EnableHystrix 注解
package com.kaishen;
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.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
/**
* 部门服务提供者启动类
* @author : toby
* Create in 10:56 2022/5/10
*/
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class DeptHystrixProviderApplication8004 {
public static void main(String[] args) {
SpringApplication.run(DeptHystrixProviderApplication8004.class, args);
}
/**
* 注册监控页面
* @return hystrixMetricsStreamServletServletRegistrationBean
*/
@Bean
public ServletRegistrationBean
ServletRegistrationBean
hystrixMetricsStreamServletServletRegistrationBean.addUrlMappings("/actuator/hystrix.stream");
return hystrixMetricsStreamServletServletRegistrationBean;
}
}
注意注意注意:
http://localhost:8004/hystrix/dept/get/1
被监控服务的 Controller
package com.kaishen.controller;
import com.kaishen.pojo.Dept;
import com.kaishen.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 部门服务 Hystrix 控制层
* @author : toby
* Create in 13:40 2022/5/9
*/
@RestController
@Slf4j
public class DeptHystrixController {
@Resource
private DeptService deptService;
// region fusingQueryDeptById
/**
* 根据部门编号查询部门信息
* @param id 部门编号
* @return 返回部门信息
*/
@GetMapping("/hystrix/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixQueryDeptById")
public Dept fusingQueryDeptById(@PathVariable Long id) {
// 调用查询方法
Dept dept = deptService.queryDeptById(id);
log.info("hystrix 查询结果:" + dept);
if (null == dept) {
throw new RuntimeException("查询异常");
}
return dept;
}
/**
* 部门查询熔断方法
* @param id 部门编号
* @return 返回构建的部门实体
*/
@SuppressWarnings("unused")
public Dept hystrixQueryDeptById(@PathVariable Long id) {
return new Dept().setDeptNo(id)
.setDeptName("根据 id = " + id + " 查不到对应的部门信息,此处返回熔断信息")
.setDbSource("没有数据来源");
}
// endregion
// region sayHello
/**
* 说 Hello
* 此方法无意义,只用于定义多个方法供回调工厂处理
* @param id 入参
* @return 返回字符串
*/
@GetMapping("/hystrix/dept/get/map/{id}")
@HystrixCommand(fallbackMethod = "toSayHello")
public String sayHello(@PathVariable Long id) {
int i = 2;
if (id == i) {
throw new RuntimeException("报错啦");
}
System.out.println("Hello");
return "Hello";
}
@SuppressWarnings("unused")
public String toSayHello(@PathVariable Long id) {
System.out.println(id);
return "toSayHello";
}
// endregion
}
在 Dashboard 界面,填写要被监控的流信息,如下图
进入后即可看到监控页面