Spring Cloud(三)--Hystrix

五. Hyxtrix

在这里插入图片描述
容错工具

1 Hystrix提供的容错功能

1.1 降级

当调用后台服务失败或超时,可以向客户端返回降级结果。

快速失败
客户端不必长时间阻塞等待后台服务结果,超时后可以快速获得反馈。
防止雪崩、防止错误传播。

1.2 熔断

熔断就像家里的电箱,有一个总闸,如果过热(访问量过大),会触发熔断,家里的电路会被断开。

当系统访问量过大,出现大量的失败情况时,会触发熔断,断路器打开后,所有的请求直接执行降级代码返回降级结果。

触发熔断的条件

  • 10秒内20次请求(必须首先满足)
  • 50%失败,执行了降级代码

2 添加 Hystrix 降级(sp06项目)

1) 添加hystrix 依赖

使用EditStarts工具。

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

2) 主程序添加@EnalbleCircuitBreaker

启用 hystrix 断路器,触发断路器自动配置。

  • 降级:超时、出错、不可到达时,对服务降级,返回错误信息或者是缓存数据

  • 熔断:当服务压力过大,错误比例过多时,熔断所有请求,所有请求直接降级

可以使用 @SpringCloudApplication 注解代替三个注解:

package cn.tedu.sp06;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

//@EnableCircuitBreaker
//@EnableDiscoveryClient //新版本可省略
//@SpringBootApplication

@SpringCloudApplication
public class Sp06RibbonApplication {

	@LoadBalanced
	@Bean
	public RestTemplate getRestTemplate() {
		SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory();
		f.setConnectTimeout(1000);
		f.setReadTimeout(1000);
		return new RestTemplate(f);
	}

	public static void main(String[] args) {
		SpringApplication.run(Sp06RibbonApplication.class, args);
	}
}

3) 添加降级代码

给每个远程调用方法添加注解 @HystrixCommand ,指定降级方法名
@HystrixCommand(fallbackMethod = "getItemsFB") //指定降级方法的方法名
给每个方法添加降级方法 xxxXxxFB()
package cn.tedu.sp06.controller;

import java.util.List;

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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.web.util.JsonResult;

@RestController
public class RibbonController {
	@Autowired
	private RestTemplate rt;
	
	@GetMapping("/item-service/{orderId}")
	@HystrixCommand(fallbackMethod = "getItemsFB") //指定降级方法的方法名
	public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
		return rt.getForObject("http://item-service/{1}", JsonResult.class, orderId);
	}

	@PostMapping("/item-service/decreaseNumber")
	@HystrixCommand(fallbackMethod = "decreaseNumberFB")
	public JsonResult decreaseNumber(@RequestBody List<Item> items) {
		return rt.postForObject("http://item-service/decreaseNumber", items, JsonResult.class);
	}

	/
	
	@GetMapping("/user-service/{userId}")
	@HystrixCommand(fallbackMethod = "getUserFB")
	public JsonResult<User> getUser(@PathVariable Integer userId) {
		return rt.getForObject("http://user-service/{1}", JsonResult.class, userId);
	}

	@GetMapping("/user-service/{userId}/score") 
	@HystrixCommand(fallbackMethod = "addScoreFB")
	public JsonResult addScore(@PathVariable Integer userId, Integer score) {
		return rt.getForObject("http://user-service/{1}/score?score={2}", JsonResult.class, userId, score);
	}
	
	/
	
	@GetMapping("/order-service/{orderId}")
	@HystrixCommand(fallbackMethod = "getOrderFB")
	public JsonResult<Order> getOrder(@PathVariable String orderId) {
		return rt.getForObject("http://order-service/{1}", JsonResult.class, orderId);
	}

	@GetMapping("/order-service")
	@HystrixCommand(fallbackMethod = "addOrderFB")
	public JsonResult addOrder() {
		return rt.getForObject("http://order-service/", JsonResult.class);
	}
	
	/

    //降级方法的参数和返回值,需要和原始方法一致,方法名任意
	public JsonResult<List<Item>> getItemsFB(String orderId) {
		return JsonResult.err("获取订单商品列表失败");
	}
	public JsonResult decreaseNumberFB(List<Item> items) {
		return JsonResult.err("更新商品库存失败");
	}
	public JsonResult<User> getUserFB(Integer userId) {
		return JsonResult.err("获取用户信息失败");
	}
	public JsonResult addScoreFB(Integer userId, Integer score) {
		return JsonResult.err("增加用户积分失败");
	}
	public JsonResult<Order> getOrderFB(String orderId) {
		return JsonResult.err("获取订单失败");
	}
	public JsonResult addOrderFB() {
		return JsonResult.err("添加订单失败");
	}
}


4) 测试

关闭 user-service 和 order-service 项目。
微服务宕机时,ribbon 无法转发请求,调用失败,会执行降级代码,返回降级结果 。

  • 访问可能超时失败的 item-service:
    在这里插入图片描述
  • 访问未启动的 user-service:
    在这里插入图片描述

3 hystrix 的超时

默认超时时长是1秒,hystrix等待超时后, 会执行降级代码, 快速向客户端返回降级结果。
可在yml中设置超时时间:hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds

注意
在这里插入图片描述
hystrix超时设置一般应大于 ribbon 的重试超时时长,例如 10 秒;否则一旦hystrix已经执行完降级代码并把结果响应给客户端,ribbon还在重试,哪怕重试成功也不会再响应给浏览器了,做的是无用功。

  • 为了测试 hystrix 降级,我们把 hystrix 等待超时设置得非常小(500毫秒)
spring:
  application:
    name: ribbon

server:
  port: 3001

eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka

ribbon:
  MaxAutoRetries: 1
  MaxAutoRetriesNextServer: 2

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 500

访问:http://localhost:3001/item-service/366
F5快速刷新,达到10s 20次,会瞬间得到降级结果,不会再去调用item-service。(只要加了降级,就有熔断

4 hystrix dashboard 断路器仪表盘

hystrix 对请求的降级和熔断,可以产生监控信息,hystrix dashboard可以实时的进行监控,监控hystrix出现错误的情况。
在这里插入图片描述

4.1 actuator

在这里插入图片描述
Springboot 提供的一个项目监控工具,可以监控项目的各种运行数据,hystrx利用actuator,可以添加hystrix的监控数据。

添加 actuator:
1)actuator依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

在这里插入图片描述

2)编辑yml文件,暴露监控数据:
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream
##################################
m.e.w.e.i="*"  # 暴露所有的监控数据
m.e.w.e.i=health  # 暴露健康状态数据
m.e.w.e.i=health,beans,env,hystrix.stream # 暴露多种监控数据
3)访问 actuator 路径,查看监控端点

访问 :http://localhost:3001/actuator 暴露所有的监控数据
在这里插入图片描述
访问 :http://localhost:3001/actuator/hystrix.stream 暴露hystrix的监控数据
在这里插入图片描述

4.2 搭建仪表盘项目

hystrix仪表盘是一个完全独立的项目,启动后,需要在它的界面上指定监控数据的路径。

如果对06项目监控,需要在仪表盘界面,添加06项目的监控路径:
http://localhost:3001/actuator/hystrix.stream

新建 sp08-hystrix-dashboard 项目

在这里插入图片描述

添加 hystrix dashboard 依赖

在这里插入图片描述

yml 配置选择端口 4001
spring:
  application:
    name: hystrix-dashboard

server:
  port: 4001

主程序添加注解@EnableHystrixDashboard,启用 hystrix dashboard
package cn.tedu.sp08;

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

@EnableHystrixDashboard
@SpringBootApplication
public class Sp08HystrixDashboardApplication {

    public static void main(String[] args) {
        SpringApplication.run(Sp08HystrixDashboardApplication.class, args);
    }

}

启动Sp08项目,并访问测试
<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR4</spring-cloud.version>
</properties>

再次查看监控数据:
在这里插入图片描述
一直刷新访问 http://localhost:3001/item-service/35 ,达到10s 20次,断路器就打开,已触发熔断。
在这里插入图片描述
在这里插入图片描述

5 hystrix 熔断

整个链路达到一定的阈值,默认情况下,10秒内产生超过20次请求,则符合第一个条件。
满足第一个条件的情况下,如果请求的错误百分比大于阈值,则会打开断路器,默认为50%。
Hystrix的逻辑,先判断是否满足第一个条件,再判断第二个条件,如果两个条件都满足,则会开启断路器。

断路器打开 5 秒后,会处于半开状态,会尝试转发请求,如果仍然失败,保持打开状态,如果成功,则关闭断路器。

6 使用 apache 的并发访问测试工具–ab

ab -n 20000 -c 50 http://localhost:3001/item-service/35

断路器状态为 Open,所有请求会被短路,直接降级执行 fallback 方法
在这里插入图片描述

ab -n 20000 -c 50 http://localhost:3001/user-service/7

在这里插入图片描述

7 hystrix 配置

  • hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
    请求超时时间,超时后触发失败降级

  • hystrix.command.default.circuitBreaker.requestVolumeThreshold
    10秒内请求数量,默认20,如果没有达到该数量,即使请求全部失败,也不会触发断路器打开

  • hystrix.command.default.circuitBreaker.errorThresholdPercentage
    失败请求百分比,达到该比例则触发断路器打开

  • hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds
    断路器打开多长时间后,再次允许尝试访问(半开),仍失败则继续保持打开状态,如成功访问则关闭断路器,默认 5000

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值