Zuul的回退fallback
- hystrix具有fallback回退能力,如果服务调用出现了异常,则可以执行指定的fallback方法。那现在zuul对api服务集群进行了反向代理,集成了hystrix,那zuul也能fallback了同样也拥有了hystrix回退的能力。
fallback实例
1.创建回退类并集成ZuulFallbackProvider 接口,实现方法。
- getRoute中返回的是serviceId,如果需要所有调用都支持回退,则return "*"或return null
- fallbackResponse 返回失败时回退给前端的Response信息
@Component
public class MyFallbackProvider implements ZuulFallbackProvider {
@Override
public String getRoute() {
return "microservice-consumer-hystrix";
}
/**
* 如果请求用户服务失败,返回什么信息给消费者客户端
*/
@Override
public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.BAD_REQUEST;
}
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.BAD_REQUEST.value();
}
@Override
public String getStatusText() throws IOException {
return HttpStatus.BAD_REQUEST.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(("fallback" + MyFallbackProvider.this.getRoute()).getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
2.既然是依靠hystrix的回退功能实现的,那么一样可以依靠dashboard监控回退的状态等信息。具体操作见hystrix章节。
Zuul的过滤器
- 通过Filter,我们可以实现安全控制,比如,过滤掉一些可能的非法访问,及访问结束或出错时需要的一些辅助处理。
Zuul的过滤器实例
1.创建过滤器类并继承ZuulFilter类
/**
* 过滤包含关键字的url
*/
public class KeyWordFilter extends ZuulFilter {
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
System.out.println(String.format("%s KeyWordFilter request to %s", request.getMethod(), request.getRequestURL().toString()));
String url = request.getRequestURL().toString();
if (url != null && url.indexOf("movie") >= 0) {
//过滤该请求,不往下级服务去转发请求,到此结束
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.setResponseBody("{\"result\":\"url contains key word!\"}");
ctx.set("isSuccess", false);
} else {
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
ctx.set("isSuccess", true);
}
//这里的return值没有任何含义,不被使用到
return null;
}
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
}
2.在入口程序中添加bean
@Bean
public KeyWordFilter keyWordFilter(){
return new KeyWordFilter();
}
Zuul的过滤器说明
1.一共有四种类型的过滤器,分别在不同的生命周期调用,在filterType返回对应的字符串来定义
- PRE: 该类型的filters在Request routing到源web-service之前执行。用来实现Authentication、选择源服务地址等
- ROUTING:该类型的filters用于把Request routing到源web-service,源web-service是实现业务逻辑的服务。这里使用HttpClient请求web-service。
- POST:该类型的filters在ROUTING返回Response后执行。用来实现对Response结果进行修改,收集统计数据以及把Response传输会客户端。
- ERROR:上面三个过程中任何一个出现错误都交由ERROR类型的filters进行处理。
如图示意:
2.filterOrder代表过滤器顺序,数值越小优先级越高。
3.过滤器间的协调
过滤器没有直接的方式来访问对方。 它们可以使用RequestContext共享状态,这是一个类似Map的结构,具有一些显式访问器方法用于被认为是Zuul的原语,内部是使用ThreadLocal实现的,有兴趣的同学可以看下源码。
4.shouldFilter 过滤器是否有效
- 返回true即代表该过滤器启用
- 可以通过根据上一级的的过滤器执行成功与否来决定是否需要启用当前过滤器
@Override
public boolean shouldFilter() {
//如果前一个过滤器的结果为true,则说明上一个过滤器成功了
RequestContext ctx = RequestContext.getCurrentContext();
return (boolean) ctx.get("isSuccess");
}
5 run函数
- 实现具体过滤逻辑
- 通过RequestContext获取所需的信息