美文网首页
zuul路由配置路径前缀问题

zuul路由配置路径前缀问题

作者: Best_Scenery | 来源:发表于2018-08-26 13:06 被阅读0次

    zuul路由配置路径前缀问题

    背景

    我们项目组刚使用spring cloud项目不久,项目运行了几个月也没有使用zuul作网关,之前是使用nginx配置不同路径规则进行不能服务端口的转发。nginx配置如下:

    location ^~ /user/ {
        proxy_pass http://xx.xx.xx.xx:xxxx;
    }
    location ^~ /product/ {
        proxy_pass http://xx.xx.xx.xx:xxxx;
    }
    location ^~ /cert/ {
        proxy_pass http://xx.xx.xx.xx:xxxx;
    }
    ...
    

    路径转发后对原始路径没有做任何修改,因此服务中Rest接口定义路径的时候会保留 /user/、/product/、/cert/这样的前缀。如:

    @RestController
    @RequestMapping("/user/")   // 保留服务模块定位前缀
    public class XXXController {
        // code
    }
    

    为什么要使用zuul?

    zuul作为网关除了做路由转发之外,它提供的过滤器可以做权限控制、限流、API监控等功能,因此引入zuul对项目的长期维护来说是有好处的。

    出现问题

    添加了一个gateway-zuul工程,在application.yml中添加了如下路由配置:

    spring:
      application:
        name: gateway-zuul
    
    server:
      port: 8888
    
    zuul:
      routes:
        api-user:
          path: /user/**
          service-id: xxx-USER-SERVICE
    

    启动工程, 访问接口:http://localhost:8888/user/xxx/xxx, 返回404。

    排查问题

    1. 首先调试代码排查,发现路由过程是按照下面类的流程走的

      ZuulServletFilter
      ->
      ZuulRunner
      -> route()
      FilterProcessor
      -> runFilters('route')
      ZuulFilter
      -> run()
      RibbonRoutingFilter
      
      

      发现RibbonRoutingFilter执行中RequestContext中的RequestURI的值已经是/xxx/xxx了

      前缀/user不见了

    2. 猜测在preRouting 阶段应该是做了path截断了.

      发现pre截断有一个Filter类叫 PreDecorationFilter,

      它的run方法是这样的:

       @Override
       public Object run() {
           RequestContext ctx = RequestContext.getCurrentContext();
           final String requestURI = this.urlPathHelper.getPathWithinApplication(ctx.getRequest());
           Route route = this.routeLocator.getMatchingRoute(requestURI);
           if (route != null) {
               // ....
           }
           // ...   
          }
      

      在解析requestURI获取组装对象Route的时候发现 route中的path前缀被截取了,继续深入
      发现了SimpleRouteLocator这个类中获取路由对象的方法:

      
       protected Route getRoute(ZuulRoute route, String path) {
           if (route == null) {
               return null;
           }
           if (log.isDebugEnabled()) {
               log.debug("route matched=" + route);
           }
           String targetPath = path;
           String prefix = this.properties.getPrefix();
           if (path.startsWith(prefix) && this.properties.isStripPrefix()) {
               targetPath = path.substring(prefix.length());
           }
           if (route.isStripPrefix()) {
               int index = route.getPath().indexOf("*") - 1;
               if (index > 0) {
                   String routePrefix = route.getPath().substring(0, index);
                   targetPath = targetPath.replaceFirst(routePrefix, "");
                   prefix = prefix + routePrefix;
               }
           }
           Boolean retryable = this.properties.getRetryable();
           if (route.getRetryable() != null) {
               retryable = route.getRetryable();
           }
           return new Route(route.getId(), targetPath, route.getLocation(), prefix,
                   retryable,
                   route.isCustomSensitiveHeaders() ? route.getSensitiveHeaders() : null);
       }
      

      中截取route前缀的地方是

           if (route.isStripPrefix()) {  //这里有个判断
               int index = route.getPath().indexOf("*") - 1;
               if (index > 0) {
                   String routePrefix = route.getPath().substring(0, index);
                   targetPath = targetPath.replaceFirst(routePrefix, "");
                   prefix = prefix + routePrefix;
               }
           }
      

      发现截取条件表达式route.isStripPrefix()的值是在ZuulProperties类中获取,而ZuulProperties类的数据来源就是application.yml中的zuul配置。

      问题定位。

    解决问题

    设置ZuulProperties类中的stripPrefix属性,在application.yml相应route配置的地方加上配置属性strip-prefix:fase,如下:

    zuul:
      routes:
        api-user:
          path: /user/**
          service-id: CASH-USER-CENTER-SERVICE
          strip-prefix: false
    

    重启服务,发现路径不再被截断,问题解决!

    相关文章

      网友评论

          本文标题:zuul路由配置路径前缀问题

          本文链接:https://www.haomeiwen.com/subject/pzhoiftx.html