首先介绍一下系统故障常用方案:降级、熔断、限流、排队
一、服务器降级(自身的故障)
1、服务降级:
服务降级,当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。也就是说,当服务器负载达到饱和时,将一些无关轻重、可有可无的服务停掉,以此来达到主功能的完整执行。
2、降级方式
- 服务接口拒绝服务:无用户特定信息,页面能访问,但是添加删除提示服务器繁忙。页面内容也可在Varnish或CDN内获取。
- 页面拒绝服务:页面提示由于服务繁忙此服务暂停。跳转到varnish或nginx的一个静态页面。
- 延迟持久化:页面访问照常,但是涉及记录变更,会提示稍晚能看到结果,将数据记录到异步队列或log,服务恢复后执行。
- 随机拒绝服务:服务接口随机拒绝服务,让用户重试,目前较少有人采用。因为用户体验不佳。
3、具体实现方式
消息中间件:所有API调用可以使用消息中间件进行控制
前端页面:指定网址不可访问(NGINX+LUA)
底层数据驱动:拒绝所有增删改动作,只允许查询
二、服务器熔断(依赖的第三方服务):
在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。
这种牺牲局部,保全整体的措施就叫做熔断。
降级与熔断使用场景不同。二者不可混淆。熔断是由于下游服务发生异常,而将下游服务停掉的做法;降级则是为了更好的完成主服务的执行而将一些服务停掉。
三、服务雪崩
1、服务血崩:当系统中的某个基础服务不可用时,导致整个系统不可用的情况。这种现象被称为服务雪崩效应. 为了应对服务雪崩, 一种常见的做法是手动服务降级. 而Hystrix的出现,给我们提供了另一种选择.
四、hystrix
实现参考这两篇文章:hystrix入门手册,SpringBoot使用Hystrix
在配置hystrix的上,可以使用 DefaultProperties 注解来对类进行配置。
@DefaultProperties(groupKey = "service",
commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE"),
@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "50"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
},
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "30"),
@HystrixProperty(name = "maxQueueSize", value = "101"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "15"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1440")
})
原理:
五:缓存
通过重写getCacheKey来开启缓存
通过注解开启缓存
当然,我们也可以通过注解来开启缓存,和缓存相关的注解一共有三个,分别是@CacheResult、@CacheKey和@CacheRemove,我们分别来看。
@CacheResult
@CacheResult方法可以用在我们之前的Service方法上,表示给该方法开启缓存,默认情况下方法的所有参数都将作为缓存的key,如下:
@CacheResult
@HystrixCommand
public Book test6(Integer id,String aa) {
return restTemplate.getForObject("http://HELLO-SERVICE/getbook5/{1}", Book.class, id);
}
此时test6方法会自动开启缓存,默认所有的参数都将作为缓存的key,如果在某次调用中传入的两个参数和之前传入的两个参数都一致的话,则直接使用缓存,否则就发起请求,如下:
@RequestMapping("/test6")
public Book test6() {
HystrixRequestContext.initializeContext();
//第一次发起请求
Book b1 = bookService.test6(2, "");
//参数和上次一致,使用缓存数据
Book b2 = bookService.test6(2, "");
//参数不一致,发起新请求
Book b3 = bookService.test6(2, "aa");
return b1;
}
当然这里我们也可以在@CacheResult中添加cacheKeyMethod属性来指定返回缓存key的方法,注意返回的key要是String类型的,如下:
@CacheResult(cacheKeyMethod = "getCacheKey2")
@HystrixCommand
public Book test6(Integer id) {
return restTemplate.getForObject("http://HELLO-SERVICE/getbook5/{1}", Book.class, id);
}
public String getCacheKey2(Integer id) {
return String.valueOf(id);
}
此时默认的规则失效。
@CacheKey
当然除了使用默认数据之外,我们也可以使用@CacheKey来指定缓存的key,如下:
@CacheResult
@HystrixCommand
public Book test6(@CacheKey Integer id,String aa) {
return restTemplate.getForObject("http://HELLO-SERVICE/getbook5/{1}", Book.class, id);
}
这里我们使用@CacheKey注解指明了缓存的key为id,和aa这个参数无关,此时只要id相同就认为是同一个请求,而aa参数的值则不会作为判断缓存的依据(这里只是举例子,实际开发中我们的调用条件可能都要作为key,否则可能会获取到错误的数据)。如果我们即使用了@CacheResult中cacheKeyMethod属性来指定key,又使用了@CacheKey注解来指定key,则后者失效。
@CacheRemove
这个当然是用来让缓存失效的注解,用法也很简单,如下:
@CacheRemove(commandKey = "test6")
@HystrixCommand
public Book test7(@CacheKey Integer id) {
return null;
}
注意这里必须指定commandKey,commandKey的值就为缓存的位置,配置了commandKey属性的值,Hystrix才能找到请求命令缓存的位置。举个简单的例子,如下:
@RequestMapping("/test6")
public Book test6() {
HystrixRequestContext.initializeContext();
//第一次发起请求
Book b1 = bookService.test6(2);
//清除缓存
bookService.test7(2);
//缓存被清除,重新发起请求
Book b2 = bookService.test6(2);
//参数一致,使用缓存数据
Book b3 = bookService.test6(2);
return b1;
}
六:SpringCloud 使用hystrix
1 使用:
2 使用 dashboard可视化
踩坑点:
2.1 :可视化界面如果js 或css 找不到,添加以下代码:
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/hystrix/**").addResourceLocations("classpath:/static/hystrix/");
2.2 如果结合feign 不生效的话,可以配置以下代码:
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = true)
public Feign.Builder feignHystrixBuilder() {
return HystrixFeign.builder();
}
2.3 如果结合trubine 监控不到的话,需要看一下服务提供者 是否有 @EnableHystrixDashboard 注解,如果有去掉,并把对应的dashboard 的maven依赖去掉 。
2.4 如果配置turbine的话, app-config 必须配,且cluster-config 只能是大写字母,不能是小写字母。
可以通过 /cluster 来查看当前集群
可视化界面说明:
- 实心圆:1、通过颜色的变化代表了实例的健康程度,健康程度从绿色、黄色、橙色、红色递减。2、通过大小表示请求流量发生变化,流量越大该实心圆就越大。所以可以在大量的实例中快速发现故障实例和高压实例。
- 曲线:用来记录2分钟内流浪的相对变化,可以通过它来观察流量的上升和下降趋势。