SpringCloud-Hystrix熔断器(7)

x33g5p2x  于2021-12-18 转载在 其他  
字(10.3k)|赞(0)|评价(0)|浏览(389)

简介:

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会条用失败,比如超时,异常等。Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障以 提高分布式的弹性
熔断器 本身是一种开关装置,当某个服务单元发生故障之后,通过熔断器的故障监控(类似与保险丝)向调用方返回一个符合预期的,可处理的备选响应(Fall Back)而不是长时间的等待或者抛出调用方无法处理的异常。这样就保证了服务调用方的线程不会被长时间 不必要地占用,从而避免了故障在分布式系统的蔓延,乃至雪崩

服务雪崩

多个微服务之间调用的时候 假设微服务A调用用微服务B和微服务C, 微服务B和微服务C又调用其他微服务,这就是所谓的扇出 如果扇出的链路上某个微服务的调用响应时间过长或者不可用 对微服务A的调用就会占用越来越多的资源呢,进而引起系统崩溃,所谓的雪崩效应
对于高流量的应用来说,单一的 后端依赖可能导致所有微服务器上的所有资源都在几秒钟内饱和,比失败更糟糕的是这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张 导致整个系统发生更多的级联故障 ,这些故障和延迟进行隔离和管理 ,以便单个依赖关系的失败,不能取消整个应用程序或系统

服务熔断

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

创建 熔断器的 提供者microservicecloud-provider-dept-hystrix-8085

Hystrix 依赖

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

pom 文件

<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">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.xxx</groupId>
    <artifactId>microservicecloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>microservicecloud-provider-dept-hystrix-8085</artifactId>

 <dependencies>
		<!-- hystrix -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>
		<!-- 将微服务provider侧注册进eureka -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<!-- 引入自己定义的api通用包,可以使用Dept部门Entity -->
		<dependency>
			<groupId>com.xxx</groupId>
			<artifactId>microservicecloud-api</artifactId>
			<version>${project.version}</version>
		</dependency>	    	
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<!-- actuator监控信息完善 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</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-starter-jetty</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-test</artifactId>
		</dependency>
		<!-- 修改后立即生效,热部署 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>
	
	</dependencies>

</project>

. yml文件

server:
  port: 8085
  
mybatis:
                                          
  type-aliases-package: com.xxx.user                  # 所有user别名类所在包
  mapper-locations:
  - classpath:mybatis/mapper/**/*.xml                       # mapper映射文件
    
spring:
   application:
    name: microservicecloud-dept 
   datasource:
    type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型
    driver-class-name: com.mysql.jdbc.Driver               # mysql驱动包
    url: jdbc:mysql://localhost:3306/1809              # 数据库名称
    username: root
    password: root
    dbcp2:
      min-idle: 5                                           # 数据库连接池的最小维持连接数
      initial-size: 5                                       # 初始化连接数
      max-total: 5                                          # 最大连接数
      max-wait-millis: 200  
eureka: 
  client: #客户端注册进eureka服务列表内
    service-url: 
      # defaultZone: http://localhost:7001/eureka
      #             http://euerka7001.com:7001/eureka/,http://euerka7002.com:7002/eureka/,http://euerka7003.com:7003/eureka/
       defaultZone: http://euerka7001.com:7001/eureka/,http://euerka7002.com:7002/eureka/,http://euerka7003.com:7003/eureka/     
    instance: 
       instance-id: microservicecloud-dept8083
       prefer-ip-address: true  # 显示ip地址      
       
       
info: 
  app.name: atguigu-microservicecloud
  company.name: www.baidu.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$
       
      
freemarker: 
    template-loader-path: classpath:/templates/
    cache: false
    charset: UTF-8
    check-template-location: true
    content-type: text/html; charset=utf-8
    expose-request-attributes: true
    expose-session-attributes: true
    request-context-attribute: request                                                          

       
logging: 
   level:   
     com.xxx.mapper: debug

注解:

//服务熔断
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",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"), //失败率达到多少后跳闸
})

controller

熔断器 本身是一种开关装置,当某个服务单元发生故障之后,通过熔断器的故障监控(类似与保险丝)向调用方返回一个符合预期的,可处理的备选响应(Fall Back)
@HystrixCommand(fallbackMethod=“test”) 这个注解 就处理响应过长 或者其他原因 造成的异常,进而熔断该节点微服务的调用 快速返回错误的香影信息,当检测到该节点微服务调用响应正常后恢复调用链路

package com.xxx.controller;

import java.util.List;

import org.bouncycastle.crypto.RuntimeCryptoException;
import org.bouncycastle.jcajce.provider.asymmetric.dsa.DSASigner.detDSA;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.ribbon.proxy.annotation.Hystrix;
import com.xxx.service.UserService;

import com.xxx.user.User;

import lombok.experimental.PackagePrivate;

@Controller
public class UserController {

	@Autowired
	private UserService  userService;
	
	@Autowired
	private DiscoveryClient client;     
	
	@RequestMapping(value = "/list/user", method = RequestMethod.GET)
	public String list(ModelMap map){
		List<User> list=userService.list();
		map.put("list", list);
		return "user";
	}
	
	
	
	
	@ResponseBody
	@RequestMapping(value = "/list/userlist", method = RequestMethod.GET)
	public List<User> userlist(){
		
		return userService.userlist();
	}
	
	

	/** * 单条查询数据 * @param userId * @return */
	@RequestMapping(value="user/getId/{userId}",method=RequestMethod.GET)
	@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",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"), //失败率达到多少后跳闸
})
	@ResponseBody
	public User getId(@PathVariable("userId") Integer  userId) {
		 
		    User user= this.userService.getId(userId);
	
		    if (user==null) {
				throw new RuntimeException("用户Id"+userId+"抱歉数据为空");
				
			}
		
	  return user;

		
	}
	//返回异常信息提示
   
	@ResponseBody
	 public User test(@PathVariable("userId") Integer  userId) {
		 
		 return  new User(404,"该查询这个"+userId+"不存在",1,1);
	 }  
	
	
}

service

package com.xxx.service;

import java.util.List;

import com.xxx.user.User;

public interface UserService {

	
	

	public List<User> list();
	
	
	public List<User> userlist();

	public User getId(Integer userId);
}

impl

package com.xxx.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xxx.mapper.UserMapper;
import com.xxx.service.UserService;
import com.xxx.service.UserServiceFeign;
import com.xxx.user.User;
@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserMapper userMapper;

	@Override
	public List<User> list() {
		// TODO Auto-generated method stub
		return userMapper.findAll();
	}
	
	
	@Override
	public List<User> userlist() {
		// TODO Auto-generated method stub
		return userMapper.userlist();
	}

	/**
	 *查询单条数据 
	 */
	@Override
	public User getId(Integer userId) {
		// TODO Auto-generated method stub
		return  userMapper.getId(userId);
	}
	
	
}

mapperr 借口 mapper.xml 就你正常的写就可以

启动类 启动类 添加@EnableCircuitBreaker

package com.xxx;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
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 User8085 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
	    SpringApplication.run(User8085.class,args);
	}

}

启动项目测试

eureka 集群注册(7001,7002,7003)-----》提供者(8085)-----》消费者(8084)一共5个项目

测试
我现在 这个表里 就一条数据

如果我们恶意的去查询一条数据 库没有的数据 就会报空指针 但是我们使用了-Hystrix熔断器 这个就像我们 Spring里 异常通知 差不多

我下面去查一个不存在的和 一个存在的 就能对比一下

当你查询异常时就会 调用 @HystrixCommand(fallbackMethod=“test”)

相关文章