一.hystrix的局部降级逻辑的处理方式
1.局部服务降级(提供方)
1.再8001服务的提供方,放开Hysetix依赖
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.对8001的service进行重新配置
@Service
public class PaymentService {
/**
* 可以正常访问的方法
* @param id
* @return
*/
public String paymentInfo_Ok(Integer id){
return "线程池:" + Thread.currentThread().getName() + " ,paymentInfo_OK,id:" + id;
}
/**
超时访问的方法
*/
@HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
//设置峰值,超过 3 秒,就会调用兜底方法,这个时间也可以由feign控制
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public String paymentInfo_Timeout(Integer id){
int interTime = 5;
//int i = 10/0;
try{
TimeUnit.SECONDS.sleep(interTime);
}catch (Exception e){
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + " ,paymentInfo_Timeout,id:" + id + "耗时" + interTime + "秒钟";
}
// 定义服务出现异常之后,兜底的方法
public String timeoutHandler(Integer id){
return "服务异常,请重试......";
}
}
3.在启动类上开启服务熔断的注解
@EnableCircuitBreaker //开启服务熔断
4.启动8001服务测试。
5.改动服务方里面的代码进行测试。
2.局部服务降级(消费方)
1.将服务提供方关于所有服务降级的设置全部去掉
2.在消费放引入hystrix依赖(放开注释即可)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
3.在启动类上开启服务熔断
@EnableCircuitBreaker//开启熔断器
4.在Controller编写降级逻辑
@RestController
@Slf4j
@SuppressWarnings("all")
public class OrderController {
@Autowired
OrderService orderService;
@GetMapping("/consumer/payment/hystrix/{id}")
public String paymentInfo_OK(@PathVariable("id")Integer id){
log.info("paymentInfo_OKKKKOKKK");
return orderService.paymentInfo_OK(id);
}
@HystrixCommand(fallbackMethod = "handeException", commandProperties = {
//设置峰值,超过 1.5 秒,就会调用兜底方法
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value = "1500")
})
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String paymentInfo_Timeout(@PathVariable("id")Integer id){
log.info("paymentInfo_timeout");
return orderService.paymentInfo_Timeout(id);
}
public String handeException(Integer id){
return "服务调用异常,请稍后再试.....";
}
}
5.启动测试。
6.修改,然后再启动测试看是成功。
二.全局降级处理方式
1.全局服务降级
1.全局服务降级处理在服务消费方上面实现,在消费方的controller里面编写全局降级逻辑的方法
// 全局降级处理方法
public String globalHandler(){
return "这是全局处理降级逻辑的方法.......";
}
2.使用注解开启全局服务降级逻辑处理
//类上
@DefaultProperties(defaultFallback="")
//方法上
@HystrixCommand
插入照片实例:
3.启动测试。
2.全局服务降级—服务降级方法的抽取
1.在yml配置文件开启Feign基于对Hystrix的支持
#用于服务降级 在注解@FeignClient 中添加 fallback 属性值
feign:
hystrix:
enabled: true # 在feign中开启 hystrix
2.定义一个类实现Feign客户端接口
@Component
public class FallBackService implements OrderService {
@Override
public String paymentInfo_OK(Integer id) {
return "进行paymentInfo_OK方法降级处理......";
}
@Override
public String paymentInfo_Timeout(Integer id) {
return "进行paymentInfo_Timeout方法降级处理";
}
}
3.修改Feign客户端接口
@FeignClient(value = "cloud-payment-service",fallback = FallBackService.class)
public interface OrderService {
@GetMapping("/payment/hystrix/{id}")
public String paymentInfo_OK(@PathVariable("id")Integer id);
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_Timeout(@PathVariable("id")Integer id);
}
4.启动测试
三.什么是熔断? 熔断有哪几种状态 断路器的工作原理
1.熔断机制是应对雪崩效应的一种微服务链路保护机制,当闪出链路的某个微服务出错不可用或者响应时间太长时,会进行服务降级,进而,熔断该节点微服务的调用,快速返回错误的响应信息。
2.三种状态,分别为:
2.1熔断打开
2.2熔断关闭
2.3熔断半开
3.原理:
3.1在8001项目里进行操作,service层的方法设置服务熔断,首先在启动类上开启服务@EnableCircuitBreaker//开启熔断
@Service
public class PaymentService {
/**
* 可以正常访问的方法
* @param id
* @return
*/
public String paymentInfo_Ok(Integer id){
return "线程池:" + Thread.currentThread().getName() + " ,paymentInfo_OK,id:" + id;
}
/**
超时访问的方法
*/
/*@HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
//设置峰值,超过 3 秒,就会调用兜底方法,这个时间也可以由feign控制
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})*/
public String paymentInfo_Timeout(Integer id){
// int interTime = 5;
int i = 10/0;
/*try{
TimeUnit.SECONDS.sleep(interTime);
}catch (Exception e){
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + " ,paymentInfo_Timeout,id:" + id + "耗时" + interTime + "秒钟";*/
return "hello";
}
//服务熔断
@HystrixCommand(fallbackMethod = "timeoutHandler", commandProperties = {
@HystrixProperty(name="circuitBreaker.enabled", value="true"), // 是否开启断路器
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="10"), //请求次数
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds", value="10000"), // 时间窗口期
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value="60"), // 失败率达到多少后跳闸
//整体意思:10秒内 10次请求,有6次失败,就跳闸
})
public String paymentCircuitBreaker(Integer id){
//模拟发生异常
if(id < 0){
throw new RuntimeException("*****id,不能为负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;
}
public String timeoutHandler(Integer id){
return "id不能为负数,请重试......";
}
}
2.定义Controller
//服务熔断
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id")Integer id){
return paymentService.paymentCircuitBreaker(id);
}
3.启动测试,分别测试大于零和不大于零的结果是否正确。
4.如何开启熔断?
4.1在8001项目里进行操作,service层的方法设置服务熔断,首先在启动类上开启服务@EnableCircuitBreaker//开启熔断
@Service
public class PaymentService {
/**
* 可以正常访问的方法
* @param id
* @return
*/
public String paymentInfo_Ok(Integer id){
return "线程池:" + Thread.currentThread().getName() + " ,paymentInfo_OK,id:" + id;
}
/**
超时访问的方法
*/
/*@HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
//设置峰值,超过 3 秒,就会调用兜底方法,这个时间也可以由feign控制
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})*/
public String paymentInfo_Timeout(Integer id){
// int interTime = 5;
int i = 10/0;
/*try{
TimeUnit.SECONDS.sleep(interTime);
}catch (Exception e){
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + " ,paymentInfo_Timeout,id:" + id + "耗时" + interTime + "秒钟";*/
return "hello";
}
//服务熔断
@HystrixCommand(fallbackMethod = "timeoutHandler", commandProperties = {
@HystrixProperty(name="circuitBreaker.enabled", value="true"), // 是否开启断路器
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="10"), //请求次数
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds", value="10000"), // 时间窗口期
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value="60"), // 失败率达到多少后跳闸
//整体意思:10秒内 10次请求,有6次失败,就跳闸
})
public String paymentCircuitBreaker(Integer id){
//模拟发生异常
if(id < 0){
throw new RuntimeException("*****id,不能为负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;
}
public String timeoutHandler(Integer id){
return "id不能为负数,请重试......";
}
}
4.2.定义Controller
//服务熔断
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id")Integer id){
return paymentService.paymentCircuitBreaker(id);
}
4.3.启动测试,分别测试大于零和不大于零的结果是否正确。
5.什么是网关? gateway 的核心概念
1.为微服务架构提供一种简单有效的统一的API路由管理方式。它就相当于一个壳子,通过负载均衡的机制去调用微服务。
2.Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。它的特性:
2.1基于SpringFramework 5,ProjectRector和SpringBoot2.0进行构建;
2.2动态路由:能够匹配任何请求属性:
2.3可以对路由指定predicate(断言)和filter(过滤器)
2.4集成Hystrix的断路器功能
2.5集成Springcloud服务发现功能
2.6易于编写的predicate(断言)和filter(过滤器)
2.7请求限流功能
2.8支持路径重写
3。Getway有三大核心:
Route(路由),Predicate(断言),Filter(过滤器)
6.如何简单使用gateway
1.创建网关模块,尾部默认为9527
2.导入pom依赖
<dependencies>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--eureka-client gateWay作为网关,也要注册进服务中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- gateway和web不能同时存在,即web相关jar包不能导入 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<groupId>com.krisswen.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
3.编写application。yml配置文件
server:
port: 9527
spring:
application:
name: cloud-gateway
## GateWay配置
cloud:
gateway:
routes:
- id: payment_routh # 路由ID , 没有固定的规则但要求唯一,建议配合服务名
uri: http://localhost:8001 # 匹配后提供服务的路由地址
predicates:
- Path=/payment/** # 断言,路径相匹配的进行路由
- id: payment_routh2 # 路由ID , 没有固定的规则但要求唯一,建议配合服务名
uri: http://localhost:8001 # 匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** # 断言,路径相匹配的进行路由
# 注册进 eureka Server
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
register-with-eureka: true
fetch-registry: true
4.编写启动类
@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GatewayMain9527.class,args);
}
}
5.启动测试
先启动没有使用网关前的进行测试,然后再使用网关后的进行操作。