服务雪崩解决方法

造成服务雪崩的主要原因:

1.服务提供者不可用(硬件故障,程序bug,缓存击穿,用户大量请求)
2.重试加大流量(用户重试,代码逻辑重试)
3.服务调用者不可用(同步等待造成的资源耗尽)

服务降级

超时降级、资源不足时降级,降级后可以配合降级接口返回托底数据。实现一个fallback方法,当请求后端 服务出现异常的时候,可以使用fallback方法返回的值。

pom中加入:

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

配置文件不需要添加什么
目录结构:
在这里插入图片描述
ProductController中的代码:

@RestController
public class ProductController {
	@Autowired
	private ProductService productService;
	@RequestMapping(value="list",method=RequestMethod.GET)
	public List<Product> listProduct(){
		List<Product> list= this.productService.listProduct();
		return list;
	}
}

ProductService中的代码:

@Service
public class ProductService {
	@Autowired
	private LoadBalancerClient loadBalancerClient;	//ribbon	负载均衡客户端
	@HystrixCommand(fallbackMethod = "fallback",
			commandProperties = {
		      //默认10秒;如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。    @HystrixProperty(name=HystrixPropertiesManager.FALLBACK_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value="15")
		    })
	public List<Product> listProduct(){
		//获取eurekaone-provider客户端
		ServiceInstance	si=loadBalancerClient.choose("e-book-product");
		StringBuffer sb = new StringBuffer("");
		sb.append("http://");
		//获取ip地址
		sb.append(si.getHost());
		sb.append(":");
		//获取端口号
		sb.append(si.getPort());
		sb.append("/product/list");
		System.out.println(sb.toString());  
		RestTemplate rt = new RestTemplate();
		//对象为Product集合
		ParameterizedTypeReference<List<Product>> typeRef =new ParameterizedTypeReference<List<Product>>(){};
		//参数是浏览器地址,请求方法,和转化为的对象
		ResponseEntity<List<Product>> resp= rt.exchange(sb.toString(),HttpMethod.GET, null, typeRef);
		List<Product> plist = resp.getBody();
		return plist;
	}
	public List<Product> fallback() {
		List<Product> list = new ArrayList<Product>();
		list.add(new Product(-1,"fallback"));
		return list;
	}
}

使用降级,我们只是多添加了一个注解,然后创建fallback的方法,如果并发达到15的时候或则product没有,就会自动降级。当我们关闭product的时候:
在这里插入图片描述
它就会自动降级,执行fallback方法。

请求缓存

pom文件中加入:

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

这回的pom文件多加入了redis的依赖。
配置文件中加入:

#程序启动时创建的缓存名称
#spring.cache.cache-names=com.agan.book
# Redis数据索引(默认为0)
spring.redis.database=1
#Redis服务器地址
spring.redis.host=192.168.23.129
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(负值表示没有限制)
spring.redis.pool.max-active=100
#连接池最大阻塞等待时间(负值表示没有限制)
spring.redis.pool.max-wait=3000
#连接池最大空闭连接数
spring.redis.pool.max-idle=200
#连接汉最小空闲连接数
spring.redis.pool.min-idle=50
#连接超时时间(毫秒)
spring.redis.pool.timeout=600

注意你的电脑虚拟机Linux中必须要安装了redis并且注意服务器的地址。
目录文件:
在这里插入图片描述
ProductController代码:

@RestController
public class ProductController {
	@Autowired
	private ProductService productService;
	@RequestMapping(value="list",method=RequestMethod.GET)
	public List<Product> listProduct(){
		List<Product> list= this.productService.listProduct();
		return list;
	}
	@RequestMapping(value="get",method=RequestMethod.GET)
	public Product get(Integer id) {
		return this.productService.get(id);
	}
	@RequestMapping(value="del",method=RequestMethod.GET)
	public void del(Integer id) {
		 this.productService.del(id);
	}
}

这里的代码主要是加入了get和del。
ProductService加入代码:

	@Cacheable(key="'product' + #id")
	public Product get(Integer id) {
		System.out.println("=========get============"+id);
		return new Product(id,"test6");
	}
	@CacheEvict(key="'product' + #id")
	public void del(Integer id) {
		System.out.println("=========del============"+id);
	}

在上面降级的基础上,加入了以上代码。
测试结果:
在这里插入图片描述
我开始将id为2的删除掉,然后get?id=2两次,发现只有第一次打印,第二次没有打印,说明第二次是缓存。
服务器中,注意要选择数据库
在这里插入图片描述

请求合并

在一定时间内将多个请求合并为一个请求。
在pom中加入:

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
			<groupId>com.netflix.hystrix</groupId>
			<artifactId>hystrix-javanica</artifactId>
			<version>RELEASE</version>
</dependency>

配置文件不需要添加。
目录结构:
在这里插入图片描述
ProductController代码

@RestController
public class ProductController {
	@Autowired
	private ProductService productService;
	@RequestMapping(value="getproduct",method=RequestMethod.GET)
	public void getproduct() throws InterruptedException, ExecutionException{
		Future<Product> p1= this.productService.getProduct(1);
		Future<Product> p2= this.productService.getProduct(2);
		Future<Product> p3= this.productService.getProduct(3);
		System.out.println(p1.get().toString());
		System.out.println(p2.get().toString());
		System.out.println(p3.get().toString());
	} 
}

ProductService代码:

@Service
public class ProductService {
	//利用hystrix合并请求  
    @HystrixCollapser(batchMethod = "batchProduct", scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,  
    		collapserProperties = {  
    		//请求时间间隔在50ms之内的请求会被合并为一个请求
            @HystrixProperty(name = "timerDelayInMilliseconds", value = "20"),
            //设置触发批处理执行之前,在批处理中允许的最大请求数。
            @HystrixProperty(name = "maxRequestsInBatch", value = "200"),  
    })
	public Future<Product> getProduct(Integer id) {
		System.out.println("---------"+ id + "---------");
		return null;
	}
	@HystrixCommand
	public List<Product> batchProduct(List<Integer> ids) {
		for (Integer id:ids) {
			System.out.println(id);
		}
		List<Product> list= new  ArrayList<Product>();
		list.add(new Product(1,"test1无的放矢付撒发付付撒奥过过过过过过过过"));
		list.add(new Product(2,"test2无的放矢付撒发付付撒奥过过过过过过过过"));
		list.add(new Product(3,"test3无的放矢付撒发付付撒奥过过过过过过过过"));
		list.add(new Product(4,"44444444444444444444444444444444444444444"));
		return list;
	}
}

测试结果:
在这里插入图片描述
并没有打印---------"+ id + "---------说明请求合并了。

服务熔断

当失败率达到阙值自动触发降级,熔断器触发的快速失败会进行快速恢复。
在pom中加入:

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

目录结构:
在这里插入图片描述
ProductController代码:

@RestController
public class ProductController {
	@Autowired
	private ProductService productService;
	@RequestMapping(value="list",method=RequestMethod.GET)
	public List<Product> listProduct(@RequestParam("n") Integer n){
		List<Product> list= this.productService.listProduct(n);
		return list;
	}
}

ProductService代码:

@Service
public class ProductService {
	@Autowired
	private LoadBalancerClient loadBalancerClient;	//ribbon	负载均衡客户端
	@HystrixCommand(fallbackMethod = "fallback",
			commandProperties = {
			  //默认20个;10s内请求数大于20个时就启动熔断器,当请求符合熔断条件时将触发getFallback()。
		      @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value="10"),
		      //请求错误率大于50%时就熔断,然后for循环发起请求,当请求符合熔断条件时将触发getFallback()。      @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value="50"),
		      //默认5秒;熔断多少秒后去尝试请求      @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value="5000"),
		    })
	public List<Product> listProduct(int n){
		System.out.println(n);
		if (n==1) {
			throw new RuntimeException();
		}
		//获取eurekaone-provider客户端
		ServiceInstance	si=loadBalancerClient.choose("e-book-product");
		StringBuffer sb = new StringBuffer("");
		sb.append("http://");
		//获取ip地址
		sb.append(si.getHost());
		sb.append(":");
		//获取端口号
		sb.append(si.getPort());
		sb.append("/product/list");
		System.out.println(sb.toString());  
		RestTemplate rt = new RestTemplate();
		//对象为Product集合
		ParameterizedTypeReference<List<Product>> typeRef =new ParameterizedTypeReference<List<Product>>(){};
		//参数是浏览器地址,请求方法,和转化为的对象
		ResponseEntity<List<Product>> resp= rt.exchange(sb.toString(),HttpMethod.GET, null, typeRef);
		List<Product> plist = resp.getBody();
		return plist;
	}
	public List<Product> fallback(int n) {
		List<Product> list = new ArrayList<Product>();
		list.add(new Product(-1,"fallback"));
		return list;
	}
}

主要就是改变了注解。
测试:
在这里插入图片描述
在这里插入图片描述
当n为1的时候为关闭的状态,n不为1的时候就是开启的状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值