08月29, 2018

Spring Cloud [03_API网关_Spring_Zuul]

服务网关作为服务外部请求的统一入口,将系统内部纷繁复杂的接口路由暴露至外部并为请求-返回流程提供拦截处理服务。

网关组件特性:

  • 高可用 7*24 稳定性
  • 性能并发性 访问压力大
  • 安全性 防恶意访问 通信加密
  • 拓展性

非业务功能:协议转发 流量监控等

Spring Cloud Zuul

Zuul是Spring Cloud微服务生态中的网关组件,在以Spring为技术栈的项目中有着天然的优势。

核心: 路由 + 过滤器 alt

各Filter之间相互独立,通信依靠Zuul上下文容器RequestContext

alt

Request -> PreFilter(参数校验))-> RoutingFilter(路由转发) -> PostFilter(结果处理))-> ErrorFilter(统一异常处理) CustomFilter(自定义过滤器),可以订制在以上任意位置。

Build Zuul

依赖

alt

路由

  • 启动类开启Zuul代理
@SpringBootApplication
@EnableZuulProxy
public class ApiGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayApplication.class, args);
    }
}
  • 配置

application.yml

 zuul:
  routes:
    v1:
      path: /foo/v1/**
      serviceId: foo_service

v1 : 代理路径名称 v1.path : 代理路径 v1.path:被代理服务ID 此处为foo_service添加v1版本路径控制

alt

  • 排除路由
zuul:
  routes:
  ignored-patterns:
    - /foo/v1/

PreFilter权限校验

在Zuul自定义Filter需要继承模板com.netflix.zuul.ZuulFilter,并实现若干抽象方法。

  • filterType() :权限过滤器在ZuulFilter的申明周期中属于前置过滤器

    @Override
    public String filterType() {
      return FilterConstants.PRE_TYPE;
    }
    
  • filterOrder(): 过滤器权重顺序,该值越小越先执行(可利用内置过滤器 -1 控制顺序)

    @Override
    public int filterOrder() {
      return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
    }
    
  • shouldFilter(): 是否开启过滤
@Override
public boolean shouldFilter() {
    return true;
}
  • run(): 过滤器具体逻辑(检查请求头是否持有值为“test_token”的token,否则返回401)

Zuul内置了整个从Request到Response的Filter上下文容器:com.netflix.zuul.context.RequestContext

@Override
public Object run() throws ZuulException {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();

    String token = request.getHeader("token");
    if (!"test_token".equals(token)) {
        ctx.setSendZuulResponse(false);
        ctx.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
    }

    return null;
}

alt

请求头上加上正确的token后,调用成功:

alt

PostFiler 返回结果包装

与前置Filter一样继承模板类并实现方法。

@Override
public String filterType() {
    return FilterConstants.POST_TYPE;
}

@Override
public int filterOrder() {
    return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
}

对返回结果的处理需要后置Filter类型POST_TYPE,并且执行顺序在返回结果之前:

FilterConstants.SEND_RESPONSE_FILTER_ORDER

为每一个Request在Response Header里添加一个随机种子:

@Override
public Object run() throws ZuulException {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletResponse response = ctx.getResponse();

    response.setHeader("Seed", UUID.randomUUID().toString());
    return null;
}

请求一下:

alt

借助Zuul开发者可以方便的控制整个请求返回流程,在PreFilter -> RouteFilter -> PostFilter整个生命周期的任意位置插入自定义Filter,如PreFilter的权限过滤、限流拦截;RouteFilter的路由忽略;PostFiler的结果封装等等。

1.github resource.

本文链接:https://check321.net/post/springcloud_zuul.html

-- EOF --