作者|George
编辑|包包
是一种用于处理分布式系统延迟和容错的开源库。在分布式系统中许多依赖不可避免的会调用失败,比如超时、异常等,断路器保证出错不会导致整体服务失败,避免级联故障。
断路器其实就是一种开关设置,类似保险丝,像调用方返回一个符合预期的、可处理的备选响应,而不是长时间等待或者抛出无法处理的异常,保证服务调用方线程不会被长时间 不必要占用,从而避免了在分布式系统中蔓延,乃至雪崩。
微服务中 client->微服务A->微服务B->微服务C->微服务D,其中微服务B异常了,所有请求微服务A的请求都会卡在B这里,就会导致线程一直累积在这里,那么其他微服务就没有可用线程,导致整个服务器雪崩。
针对这方案有 服务限流、超时监控、服务熔断、服务降级
降级 超时
降级就是服务响应过长 ,或者不可用了,就是服务调用不了了,我们不能把错误信息返回出来,或者长时间卡在哪里,所以要准备一个策略当发生这种问题我们直接调用这个方法快速返回这个请求,不让他一直卡在那。
要在调用方做降级(要不然那个微服务都down掉了在做降级就没有意义)。
引入hystrix依赖
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
在启动类上加入@EnableHystrix 或者@EnableCircuitBreaker。
@RequestMapping("/feignPower.do")
@HystrixCommand(fallbackMethod = "fallbackMethod")
public Object feignPower(String name){
return powerServiceClient.power();
}
fallbackMethod:
public Object fallbackMethod(String name){
System.out.println(name);
return R.error("降级信息");
}
这里的降级信息具体内容根据业务需求来,比如返回一个默认的查询信息等等。
hystrix有超时监听,当你请求超过1秒 就会超时,这个是可以配置的
降级什么用
第一他可以监听服务有没有超时。第二报错了他这里直接截断了没有让请求一直卡在这个。
其实降级,当你系统迎来高并发的时候,这时候发现系统马上承载不了这个大的并发 ,可以先关闭一些不重要 的微服务(就是在降级方法返回一个比较友好的信息)把资源让出来给主服务,其实就是整体资源不够用了,忍痛关闭某些服务,待过渡后再打开。
熔断限流
熔断就像生活中的跳闸,比如电路故障了,为了防止事故扩大,这里切断你的电源以免意外发生。当一个微服务调用多次,hystrix就会采取熔断 机制,不在继续调用你的方法,会默认短路,5秒后试探性的先关闭熔断机制,如果在这时候失败一次会直接调用降级方法,一定程度避免雪崩,
限流,限制某个微服务使用量,如果线程占用超过了,超过的就会直接降级该次调用。
Feign整合hystrix
feign默认支持hystrix,需要在yml配置中打开。
feign:
hystrix:
enabled: true
降级方法
@FeignClient(value = "SERVER-POWER", fallback = PowerServiceFallBack.class)
public interface PowerServiceClient {
@RequestMapping("/power.do")
public Object power(@RequestParam("name") String name);
}
在feign客户端的注解上 有个属性叫fallback 然后指向一个类 PowerServiceClient
@Component
public class PowerServiceFallBack implements PowerServiceClient {
@Override
public Object power(String name) {
return R.error("测试降级");
}
}
zuul包含了对请求的路由和过滤两个主要功能
路由是将外部请求转发到具体的微服务实例上。是实现统一入口基础而过滤器功能负责对请求的处理过程干预,是实现请求校验等功能。
Zuul与Eureka进行整合,将zuul注册在Eureka服务治理下,同时从Eureka获取其他服务信息。(zuul分服务最终还是注册在Eureka上)
路由
org.springframework.cloud
spring-cloud-starter-netflix-zuul
dependency>
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
最后要注册在Eureka上所以需要引入eureka依赖
YML
server:
port: 9000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:3000/eureka/ #eureka服务端提供的注册地址 参考服务端配置的这个路径
instance:
instance-id: zuul-0 #此实例注册到eureka服务端的唯一的实例ID
prefer-ip-address: true #是否显示IP地址
leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒
spring:
application:
name: zuul #此实例注册到eureka服务端的name
启动类 @EnableZuulProxy
在实际开发当中我们肯定不会/server-power这样通过微服务调用,
可能只要一个/power就好了
zuul:
routes:
mypower:
serviceId: server-power
path: /power/**
myorder:
serviceId: server-order
path: /order/**
注意/**代表是所有层级 /* 是代表一层。
一般我们会禁用服务名调用
ignored-services:server-order 这样就不能通过此服务名调用,
不过这个配置如果一个一个通微服务名字设置太复杂
一般禁用服务名 ignored-services:“*”
有时候要考虑到接口调用需要一定的规范,比如调用微服务URL需要前缀/api,可以加上一个prefix
prefix:/api 在加上strip-prefix: false /api前缀是不会出现在路由中
zuul:
prefix: /api
ignored-services: "*"
stripPrefix: false
routes:
product:
serviceId: server-product
path: /product/**
order:
serviceId: server-order
path: /order/**
过滤器
过滤器(filter)是zuul的核心组件,zuul大部分功能是通过过滤器实现的,zuul中定义了4种标准过滤器类型,这些过滤器类型对应与请求的生命周期,
PRE:这种过滤器在请求路由前被调用,可利用过滤器进行身份验证,记录请求微服务的调试信息等。
ROUTING:这种过滤器将请求路由到微服务,这种过滤器用于构建发送给微服务请求,并使用 Apache HttpClient或Netfix Ribbon请求微服务。
POST:这种过滤器在路由微服务后执行,可用来相应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端。
ERROR:在其他阶段发送错误时执行过滤器
继承ZuulFilter
@Component
public class LogFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER+1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
//被代理到的微服务
String proxy = (String)ctx.get("proxy");
//请求的地址
String requestURI = (String)ctx.get("requestURI");
//zuul路由后的url
System.out.println(proxy+"/"+requestURI);
HttpServletRequest request = ctx.getRequest();
String loginCookie = CookieUtil.getLoginCookie(request);
ctx.addZuulRequestHeader("login_key",loginCookie);
return null;
}
}
由此可知道自定义zuul Filter要实现以下几个方法。
filterType:返回过滤器类型,有pre、route、post、erro等几种取值
filterOrder:返回一个int值指定过滤器的顺序,不同过滤器允许返回相同数字。
shouldFilter:返回一个boolean判断过滤器是否执行,true执行,false不执行。
run:过滤器的具体实现。
Spting-Cloud默认为zuul编写并开启一些过滤器。如果要禁用部分过滤器,只需在application.yml里设置zuul…disable=true,例如zuul.LogFilter.pre.disable=true
zuul也整合了了hystrix和ribbon的, 提供降级回退,继承FallbackProvider 类 然后重写里面的方法。
- - - -全文完- - - -
喜欢本文的朋友,欢迎关注公众号 并发编程网,收看更多精彩内容