说明:本文仅作为本人学习<<深入理解Spring Cloud与微服务构建>>一书的学习笔记,所有代码案例及文字描述均参考该书,不足之处,请留言指正,不胜感激.
一.在Zuul上配置熔断器
上一篇提到zuul的起步依赖集成了ribbon和hystrix,接下来我们来看看如何在网关上实现熔断功能.
首先我们需要了解在Zuul中实现熔断功能需要实现ZuulFallbackProvider的接口.实现该接口有两个方法,一个是getRoute()方法,用于指定熔断功能应用于哪个路由服务;另一个方法fallbackResponse()为进入熔断功能时执行的逻辑.具体实现可以参看如下代码:
/** * 网关熔断配置 * * @author zhyu * @version v1.0 * @date 2018年07月03日 19:54:28 */
@Component
public class MyZuulFallbackProvider implements ZuulFallbackProvider {
@Override
public String getRoute() {
//实现对producer-server服务的熔断
return "producer-server";
//return "*"; 实现对所有的路由服务的熔断
}
@Override
public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return 200;
}
@Override
public String getStatusText() throws IOException {
return "OK";
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("{\"status\":500,\"message\":\"sorry,the system goes to sleep,please try again later!\"}".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
接着我们启动eureka-server,zuul-server服务,不启动producer-server服务,然后通过网关访问producer-server的接口,结果如下:
可见,熔断器配置起了作用,如果我们将getRoute()方法的返回改为”*”,那么将对所有的路由服务都加熔断功能.
二.在Zuul中使用过滤器
在Zuul中自定义过滤器很简单,只需要继承ZuulFilter,并实现它的抽象方法就好,最后将其注入到IoC容器,如下:
package com.example.zuulserver.Filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/** * 自定义过滤器 * 实现起来很简单,只需要继承ZuulFilter,并实现它的抽象方法 * @author zhyu * @version v1.0 * @date 2018年07月05日 19:11:49 */
@Component
public class MyZuulFilter extends ZuulFilter {
/** * 返回过滤器的类型 * @return */
@Override
public String filterType() {
/** * Zuul有一下四种过滤器 * "pre":是在请求路由到具体的服务之前执行,这种类型的过滤器可以做安全校验,例如身份校验,参数校验等 * "routing":它用于将请求路由到具体的微服务实例,在默认情况下,它使用Http Client进行网络请求 * "post":它是在请求已被路由到微服务后执行,一般情况下,用作收集统计信息,指标,以及将响应传输到客户端 * "error":它是在其他过滤器发生错误时执行 */
return "pre";
}
/** * 过滤顺序,值越小,越早执行该过滤器 * @return */
@Override
public int filterOrder() {
return 0;
}
/** * 表示该过滤器是否过滤逻辑,如果是ture,则执行run()方法;如果是false,则不执行run()方法. * @return */
@Override
public boolean shouldFilter() {
return true;
}
/** * 具体的过滤逻辑 * 本例中,检查请求的参数中是否传了token这个参数,如果没传,则请求不被路由到具体的服务实例, * 直接返回响应,状态码为401 * @return */
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String token = request.getParameter("token");
if(token == null){
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
try{
ctx.getResponse().getWriter().write("token is empty");
}catch(Exception e){
}
}
return null;
}
}