zuul网关简介
Zuul 网关的核心 是系列过滤器,可以在 Http 请求发起和响应返回期间执行 系列的过滤器。 Zuul 包括以下 四种过滤器:
1,PRE 过滤器 它是在请求路由到具体的服务之前执行的,这种类型的过滤器可 以做安全验证,例如身份验证、 参数验证等。
2,ROUTING 过滤器 它用于将请求路由到具体的微服务 。在默认情况下,它使用Http Client 进行网络请求。
3,POST 过滤器:它是在请求己被路由到微服务后执行的,一 般情况下,用作收集统计信息、指标,以及将响 传输到客户端。
4,ERROR 过滤器:它是在其他过滤器发生错误时执行的。
当一个客户端 Request 请求进入 Zuul 服务时,网关先进入“pre filter “,进行一 系列的验证、操作或者判断 然后交给“routing filter ”进行路由转发,转发到具体的服务实例进行逻辑处理、返回数据。当具体的服务处理完后,最后由“post filter” 进行处理, 该类型的处理器处理完之后,将 Response 信息返回给客户端。
搭建网关服务
新建eureka-zuul-client模块:

引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
配置文件
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ server: port: 5000 spring: application: name: service-zuul zuul: routes: hiapi: path: /hiapi/** serviceId: eureka-client # url: http://localhost:8762 #这样写不会做负载均衡 # serviceId: hiapi-v1 ribbonapi: path: /ribbonapi/** serviceId: eureka-ribbon-client feignapi: path: /feignapi/** serviceId: eureka-feign-client # stripPrefix: false 有该字段,请求的"feignapi"会被转发到 #zuul.prefix: /v1 #加个前缀 #ribbon: # eureka: # enabled: false # #hiapi-v1: # ribbon: # listOfServers: http://localhost:8762,http://localhost:8763
在网关上添加熔断器
如何在 Zuul 上实现熔断功能。Zuul 实现熔断功能需要实现 ZuulFallbackProvider 接口。实现该接口有两个方法,getRoute()方法,用于指定熔断功能应用于哪些路由的服务 ,另一个方法 fallbackResponse()为进入熔断功能时执行的逻辑 。新建熔断器类MyFallbackProvider,如下:
@Component
class MyFallbackProvider implements ZuulFallbackProvider {
@Override
public String getRoute() {
// return "eureka-client";
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("oooops!error, i'm the fallback.".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
在网关上添加过滤器
实现过滤器其实很简, 只需要继承 ZuulFilter ,并实现 ZuulFilter 中的抽象方法,包括 filterType()和filterOrder(),以及 ZuulFilter 的shouldFilter ()和 Object run ()的两个方法。其中 filterType()即过滤器的类型,它有四 种类型,分别是“pre '’“ post ”“ routing ”和"error",filterOrder() 是过滤顺序,它为 Int 类型的值,值越小,越早执行该过滤器shouldFilter () 表示该过滤器是否过滤逻辑,如果为 true ,则执行 run()方法:如果为 false ,则不执行 run () 方法。 run ()方法写具体的过滤的逻辑。在本例中,检查请求的参数中是否传了token这个参数。新建MyFilter过滤器类
@Component public class MyFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(MyFilter.class); @Override public String filterType() { return PRE_TYPE; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
if(!ctx.sendZuulResponse()){
return false;
}
return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString())); Object accessToken = request.getParameter("token"); if(accessToken == null) { log.warn("token is empty");
//false代表的意思是,这个请求最终不会被zuul转发到后端服务器,但是如果当前Filter后面还存在其他Filter,那么其他Filter仍然会被调用到 ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); try { ctx.getResponse().getWriter().write("token is empty"); }catch (Exception e){} return null; } log.info("ok"); return null; } }
启动类添加注解
@EnableZuulProxy
测试
启动eureka-server实例,启动两个eureka-client实例,启动eureka-feign-client,eureka-ribbon-client,eureka-zuul-client实例。浏览器依次输入http://localhost:5000/hiapi/hi?name=1212333,http://localhost:5000/ribbonapi/hi?name=1212333,http://localhost:5000/feignapi/hi?name=1212333测试结果
浙公网安备 33010602011771号