欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微服务中的Zuul网关

程序员文章站 2022-06-14 14:37:54
...

一、简介

服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。Spring Cloud Netflix中的Zuul就担任了这样的一个角色,为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。

微服务中的Zuul网关

二、使用

  • 应用启动类增加注解 @EnableZuulProxy

微服务中的Zuul网关

  • 配置增加映射规则,把所有 /user 开头的请求都转发到127.0.0.1:8081(这是写死转发路径的方式)
zuul:
  routes:
    user-service: # 这里是路由id,随意写
      path: /user/** # 这里是映射路径
      url: http://127.0.0.1:8081 # 映射路径对应的实际url地址
  • 如果采用动态路由方式,到Eureka注册中心获取服务列表,先增加Eureka依赖,并在启动类添加注解@EnableDiscoveryClient,同时增加Eureka配置,具体Eureka客户端配置过程见另一篇博文 注册中心 Eureka
  • 这时便可以把写死转发路径的方式修改为转发到指定服务名称
zuul:
  routes:
    user-service: # 这里是路由id,随意写
      path: /user/** # 这里是映射路径
      serviceId: user-service # 指定服务名称

注:我们的配置规则如下:

zuul.routes.<route>.path=/xxx/**,来指定映射路径。<route>是自定义的路由名。
zuul.routes.<route>.serviceId=/user-service,来指定服务名,由于我们的<route>路由名称往往和服务名会写成一样。
所以Zuul提供了一种简化的配置语法:zuul.routes.<serviceId>=<path>,如果后面的path不写,则默认为/<serviceId>/**

zuul:
  routes:
    user-service: /user/** # 这里是映射路径

注:路由前缀,路径/api/user-service/user/1将会被代理到/user-service/user/1

zuul:
  prefix: /api # 添加路由前缀
  routes:
      user-service: # 这里是路由id,随意写
        path: /user-service/** # 这里是映射路径
        service-id: user-service # 指定服务名称

三、自定义过滤器

1、ZuulFilter是过滤器的*父类。4个最重要的方法:

//     shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。
//     run:过滤器的具体业务逻辑。
//     filterType:返回字符串,代表过滤器的类型。包含以下4种:
    //     pre:请求在被路由之前执行
    //     routing:在路由请求时调用
    //     post:在routing和errror过滤器之后调用
    //     error:处理请求时发生错误调用
//     filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。
abstract public String filterType();
abstract public int filterOrder();
boolean shouldFilter();// 来自IZuulFilter
Object run() throws ZuulException;// IZuulFilter

2、自定义,继承ZuulFilter

@Component
public class LoginFilter extends ZuulFilter{
    @Override
    public String filterType() {
        // 登录校验,肯定是在前置拦截
        return "pre";
    }
    @Override
    public int filterOrder() {
        // 顺序设置为1
        return 1;
    }
    @Override
    public boolean shouldFilter() {
        // 返回true,代表过滤器生效。
        return true;
    }
    @Override
    public Object run() throws ZuulException {
        // 登录校验逻辑。
        // 1)获取Zuul提供的请求上下文对象
        RequestContext ctx = RequestContext.getCurrentContext();
        // 2) 从上下文中获取request对象
        HttpServletRequest req = ctx.getRequest();
        // 3) 从请求中获取token
        String token = req.getParameter("access-token");
        // 4) 判断
        if(token == null || "".equals(token.trim())){
            // 没有token,登录校验失败,拦截
            ctx.setSendZuulResponse(false);
            // 返回401状态码。也可以考虑重定向到登录页。
            ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        // 校验通过,可以考虑把用户信息放入上下文,继续向后执行
        return null;
    }
}

四、增加负载均衡和熔断器

Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制,但默认值比较不合理,我们显式配置

zuul:
  retryable: true
ribbon:
  ConnectTimeout: 250 # 连接超时时间(ms)
  ReadTimeout: 2000 # 通信超时时间(ms)
  OkToRetryOnAllOperations: true # 是否对所有操作重试
  MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
  MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
  command:
  	default:
        execution:
          isolation:
            thread:
              timeoutInMillisecond: 6000 # 熔断超时时长:6000ms