服务容错保护 Hystrix
造成灾难性雪崩效应的原因:
- 服务提供者不可用。如:硬件故障、程序bug、缓存击穿、并发请求量过大deng。
- 重试加大流量。如:用户重试、代码重试逻辑等。
- 服务调用者不可用。如:同步请求阻塞造成的资源耗尽等。
解决灾难性雪崩效应:
- 降级
- 隔离
- 熔断
- 请求缓存
- 请求合并
雪崩效应的最终结果:服务链条的某一个服务不可用,导致一系列的服务不可用,最终造成服务逻辑崩溃。这种问题造成的后果往往是不可预料的。
1.在client的服务中导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
2.在启动类中加@EnableHystrix 开启容错,让Hystrix相关注解生效
3.服务降级
使用流程:
- 访问远程服务
- 如果有服务返回结果,直接返回;如果没有服务结果(超时),调用本地方法
注意:
springmvc中,处理多值请求参数的时候,
如果数据类型是简单类型(8中基本类型,对应的包装类,字符串)必须使用数组处理。使用集合,会抛出异常
表示集合无法实例化,init方法不存在。
如果数据类型是自定义的实体类型。可以使用数组或者集合处理请求参数。
请求合并:
请求合并的使用情况:单数据查询,且服务调用链很短的时候使用。如:电商的商品查询,新闻查询。
注意:
- 等待时间不能太久 (一次处理的时间的2倍极值,单位必须是1秒)—影响性能(粘合度,体验度)
- 调用链条不能太长—不超出4个
在服务的提供方代码:
@RequestMapping("/getBtIds")
public List<Map<String,Object>> getByIds(List<Integer> ids){
List<Map<String,Object>> result = new ArrayList<>();
//调用服务service的代码,访问数据存储
for(Integer id:ids){
String name = "name"+id;
Map<String,Object> map = new HashMap<>();
map.put("id",id);
map.put("name",name);
result.add(map);
}
return result;
}
在客户端
service:
List<Map<String,Object>> getByIds(List<Integer> ids);
Future<Map<String,Object>> getById(Integer id);
serviceimpl:
private List<Map<String,Object>> getByIdFallBack(List<Integer> ids){
List<Map<String,Object>> result = new ArrayList<>();
for(Integer id :ids){
Map<String,Object> map = new HashMap<>();
map.put("message","服务器正忙,稍后重试");
result.add(map);
}
return result;
}
/**
* 调用远程服务的方法
* @param ids
* @return
*
* HystrixProperty 底层是集合
* maxRequestsInBatch批处理最多多少个
*/
@Override
@HystrixCommand(fallbackMethod = "getByIdFallBack" ,commandProperties = {
@HystrixProperty(name = "maxRequestsInBatch" ,value = "20"),
@HystrixProperty(name = HystrixPropertiesManager.TIMER_DELAY_IN_MILLISECONDS ,value = "10")
})
public List<Map<String, Object>> getByIds(List<Integer> ids) {
ServiceInstance instance = this.loadBalancerClient.choose("first-application-service");
StringBuilder builder = new StringBuilder("");
builder.append("http://")
.append(instance.getHost())
.append(":")
.append(instance.getPort())
.append("/getByIds?");
for (Integer id:ids){
builder.append("ids=").append(id).append("&");
}
builder.deleteCharAt(builder.length()-1);
String url = builder.toString();
System.out.println("本次访问的服务地址是:"+url);
RestTemplate template = new RestTemplate();
ParameterizedTypeReference<List<Map<String, Object>>> type = new ParameterizedTypeReference<List<Map<String,Object>>>() {};
ResponseEntity<List<Map<String, Object>>> exchange = template.exchange(url, HttpMethod.GET, null, type);
List<Map<String, Object>> body = exchange.getBody();
return body;
}
/**
* 是springcloud中的Hystrix提供的代理实现,浏览器调用的方法
* @param id
* @return
*
* @HystrixCollapser 合并请求的方法
* batchMethod 合并请求后使用哪一个批处理方法
* scope 需要合并的请求作用域
* request 一次请求有效范围
* session 一个会话有效范围 查看商品详情
* global 全局作用域
*/
@Override
@HystrixCollapser(batchMethod = "getByIds",
scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL)
public Future<Map<String, Object>> getById(Integer id) {
return null;
}
controller层:
@RequestMapping("/testGetId")
public Map<String,Object> getByIds(Integer id){
Future<Map<String, Object>> future = service.getById(id);
/**
* 阻塞方法,不推荐直接返回
* 阻塞方法需要处理异常(超时)
*/
Map<String, Object> map = null;
try {
map = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return map;
}
熔断机制(断路由)— 服务降级的强化
在一定的时间内,异常请求比例(请求超时,网络故障、服务异常等)达到阈值时,启动断熔器,断熔器一旦启动,则会停止调用具体服务逻辑,通过fallback快速返回托底数据,保证服务链的完整。
熔断有自动恢复机制,如:当熔断器启动后,每个5秒,尝试将新的请求发送给服务提供者,如果服务可以正常执行并返回结果,则关闭熔断器,服务恢复。如果仍旧调用失败,则继续返回托底数据,熔断器持续开启状态。
feign的雪崩处理
熔断机制配置,当远程访问发生错误的时候,是否调用fallback方法逻辑,默认为true
默认开启熔断机制
多少错误请求数,开启断路由
断路由开启后的睡眠时间窗,就是多少毫秒内,不在访问ApplicationService
时间窗内,错误请求比达到多少,开启断路由
是否强制开启断路由,默认false
是否强制关闭断路由,默认false
#当远程访问发送错误的时候,是否调用fallback方法逻辑。默认true
hystrix.command.default.fallback.enabled=true
#默认开启熔断机制
hystrix.command.defalult.circuitBreaker.enabled=true
# 多少错误请求数,开启断路由
hystrix.command.default.circuitBreaker.requestVolumeThreshold=5
#断路由开启后的睡眠时间窗,就是多少毫秒内不在访问applicationService
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000
#时间戳内,错误请求百分比到达多少开启断路由
hystrix.command.default.circuitBreaker.errorThresholdPercentage=50
#是否强制开启断路由,默认false
hystrix.command.default.circuitBreaker.forceOpen=false
#是否强制关闭断路由,默认false
hystrix.command.default.circuitBreaker.forceClosed=false
eureka的自我保护
关闭自我保护机制。只要eureka client心跳3次,
eureka.server.enable-self-preservation=false
Hystrix dashboard – 数据监控
1.在消费方导入依赖
<!--采集被监控的数据 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
2.在启动类上加@EnableHystrixDashboard 开启,@EnableCircuitBreaker
默认开启:
开启actuator相关配置,提供可访问的路径
management.endpoints.web.exposure.include=hystrix.stream
management.endpoint.hystrix.stream.enable=true
在应用启动后,系统提供若干可访问的路径,包括:
http://ip:port/actuator 此路径显示,所有的可以访问的监控地址,由spring-boot-starter-actuator提供。
http://ip:port/hystrix 此路径提供,Hystrix监控数据图形界面,由spring-cloud-starter-netflix-hystrix-dashboard提供。
http://ip:port/actuator/hystrix.stream 此路径提供,Hystrix监控数据收集。由spring-boot-starter-actuator提供。