Hystrix(服务保护机制)
问题:出现雪崩问题,现在一业务会调用多个服务接口,如果一服务出现问题,就会造成堵塞,原本线程有限,但那问题服务会因为每次请求失败而累加堵塞最终会导致所有线程都被占据,这就是问题所在
解决优化:线程隔离与服务降级
所谓线程隔离及时每个服务接口提前分好线程,就那么多,超出了也不会占用其它服务
而服务降级就是指在服务出问题后不是让用户干等,而是返回一个友好的反馈信息,而作出反馈就是熔断机制
操作:
导入依赖:
spring-cloud-starter-netflix-hystrix
启动器:
在起动器上多配置个@EnableCiruitBreaker,其实可以直接配置个@SpringCloudApplication,它已经包含下面三个了
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
Controller:
编写降级逻辑,有局部和全局默认局部就是在要处理的方法上加@HystrixComand(fallbackMethod=“”)
@HystrixCommand(fallbackMethod = “queryByIdFallBack”)
public String queryById(@PathVariable(“id”) Long id){
String url = “http://user-service/user/” + id;
String user = restTemplate.getForObject(url, String.class);
return user;
}
public String queryByIdFallBack(Long id){
log.error(“查询用户信息失败,id:{}”, id);
return “对不起,网络太拥挤了!”;
}
注意:这反馈方法是有条件,就是是参数和返回类型和主方法一致
全局默认:
@DefaultProperties(defaultFallback = “defaultFallBack”)
public class ConsumerController {
public String defaultFallBack(){
@Autowired
private RestTemplate restTemplate;
@GetMapping("{id}")
@HystrixCommand
public String queryById(@PathVariable("id") Long id){
String url = "http://user-service/user/" + id;
String user = restTemplate.getForObject(url, String.class);
return user;
}
return "默认提示:对不起,网络太拥挤了!";
}
}
此时就没有什么限制了,毕竟要对所有方法处理,而不可能统一,但是所有方法必须和默认反馈方法返回属性一致
配置
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 2000//将超时时间延长下,默认一秒就会服务降级
服务熔断:
所谓熔断就是在降级服务多的情况下,一般是大于20或多余总次数50%以上的请求出错才会触发,
最明显的区别就是反馈错误信息更快了,之前的错误反馈是有一小点处理时间的,现在直接反馈,几乎不处理。
而且熔断后会关停服务5秒,5秒后再半开线程,放进一个,请求,如果仍然失败,就继续关停5秒,依次循环,直到半开时请求成功,就会打开服务
-
requestVolumeThreshold:触发熔断的最小请求次数,默认20
-
errorThresholdPercentage:触发熔断的失败请求最小占比,默认50%
-
sleepWindowInMilliseconds:休眠时长,默认是5000毫秒
Feign(服务转发优化)
作用就是将rest请求隐藏起来并单独处理,里面包含了ribbon和xystrix,但一般xystrix不用它的
依赖
springcloudstarter-openfeign
启动器
可以多加个@EableFeignCilent
但其实只要写一个@springcloudapplication就行,这个就已经包含了springbootapplication,
enableDiscoveryCilent和enableFeignCilent,还有就是干掉restTemplate
配置
没有什么好配置好的,主要是对负载均衡的配置,比如比如关闭服务重试
ribbon:
ConnectTimeout: 1000 # 连接超时时长
ReadTimeout: 2000 # 数据通信超时时长
MaxAutoRetries: 0 # 当前服务器的重试次数
MaxAutoRetriesNextServer: 0 # 重试多少次服务
OkToRetryOnAllOperations: false # 是否对所有的请求方式都重试
编写feigncilent接口客户端
@FeignClient(“user-service”)//指向服务id
public interface UserClient {
@GetMapping("/user/{id}")//具体功能
User queryById(@PathVariable(“id”) Long id);//这要和主方法保持一致,及返回参数和方法参数
}
controller
不再使用restTemplate了,直接注入feigncilent接口就行
@Autowired
private UserClient userClient;
@GetMapping("{id}")
public User queryById(@PathVariable("id") Long id){
return userClient.queryById(id);
}
zuul(安保机制)
用户访问时现在都要经过它,由它向eureka拉取服务列表再向服务调用,它本身也是个服务主要功能就是过滤与路由
依赖
springcloudstarter-ngtflix-zuul
springcloudstarter-ngtflix-eureka-cilent
启动器
只要springbootapplication与enablezuulproxy就行
配置
和其它服务器一样,配置名称和端口,还有就是注册
自己还要配置规则,默认是以服务名称作为映射路径,如果重写,要忽略它
#映射规则
zuul:
routes:
user-service: # 这里是路由id,随意写
path: /user-service/** # 这里是映射路径
url: http://127.0.0.1:8081 # 映射路径对应的实际url地址
#prefix: /api # 添加路由前缀,可以不加,但加了就要在访问时带上
#strip-prefix:false 这要加上,否则前缀没用
#优化映射规则
zuul:
routes:
prefix: /api # 添加路由前缀,可以不加,但加了就要在访问时带上
user-service: /user-service/** # 这里是映射路径
ignored-services:
- user-service
- consumer
前提是映射路径规则与服务id一致,但还要注意的是忽略默认以服务id作为映射,
就算重新写映射规则也没用,还是存在默认,所以要忽略掉
过滤器:
自定义过滤器
继承zuulfilter
@Component
public class AuthFilter extends ZuulFilter {
/**
* 过滤器类型
* @return
*/
@Override
public String filterType() {
return PRE_TYPE;
}
/**
* 过滤器顺序
* @return
*/
@Override
public int filterOrder() {
return FORM_BODY_WRAPPER_FILTER_ORDER + 1;
}
/**
* 要不要执行run
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 过滤逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
// 获取上下文(每一次请求都会生成一个上下文容器,在整个反向代理过程中共享)
RequestContext ctx = RequestContext.getCurrentContext();
// 获取request
HttpServletRequest request = ctx.getRequest();
// 获取请求参数中的role
String role = request.getParameter("role");
// 判断角色是否是admin
if(!StringUtils.equals(role, "admin")){
// 否:拦截
ctx.setSendZuulResponse(false);// 拦截
ctx.setResponseStatusCode(401);// 返回未授权 unAuthorized
}
// 是:放行
return null;
}
}
负载均衡和hystrix在zuul也得到集成,我们可以配置
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
ribbon:
ConnectTimeout: 1000
ReadTimeout: 2000
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 0