编程语言
首页 > 编程语言> > 在Spring Cloud Netflix Zuul中以编程方式设置路由

在Spring Cloud Netflix Zuul中以编程方式设置路由

作者:互联网

我创建了两个AWS Beanstalk环境,每个环境都有自己的应用程序版本.这些env的URL是https://beta.myserver.com/v1073https://beta.myserver.com/v1084.这些url指向负载均衡器.

现在我还有一个具有以下配置的Zuul实现.

    zuul:
      routes:
        beta:
          path: /api/**
          serviceId: beta-root
          strip-prefix: false
          sensitive-headers: Cookie,Set-Cookie

    ribbon:
      eureka:
        enabled: false

    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 5000

    beta-root:
      ribbon:
        listOfServers: https://beta.myserver.com

请求我的应用程序必须有一个版本标题.我有一个Zuul“pre”过滤器来检查这个标头值.目标是根据标头值路由请求.

我已经能够拦截请求,但无法从过滤器中路由它.代码片段如下.运行代码后,请求仍尝试转到https://beta.myserver.com/api/

@Override
public Object run() {
    /* Logic to get version header etc */

    /* Set the new route */
    Map<String, ZuulRoute> routes = zuulProps.getRoutes();
    ZuulRoute currentRoute = routes.get("beta-root");
    currentRoute.setLocation("https://beta.myserver.com/v1073");

    /* Refresh the route */
    routeLocator.getRoutes();

    logger.warn("Current Route:" + currentRoute.getLocation());
    return null;
}

有任何建议如何解决这个问题?

解决方法:

您真正需要做的是更改requestURI,而不是您的服务器位置.您可以轻松地完成以下操作.

首先,您的过滤器的顺序应该大于PreDecorationFilter在Dalston版本中目前为5的顺序. (您需要检查您正在使用的版本中的值).
PreDecorationFilter处理请求标头并将必要的信息填充到RequestContext中.此RequestContext将用于定义请求的实际URL. requestURI是您需要更改的密钥.在这种情况下,您可以根据标题附加或修改requestURI.以下是您的预过滤器的片段.

@Override
public int filterOrder() {
    return 6;
}

@Override
public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    // override request URI
    ctx.set("requestURI", "/v1073" + ctx.get("requestURI"));
    return null;
}

您的原始实现似乎有一些问题.首先,您正在尝试更改ZuulProperties路线中的位置.所有请求都共享此对象.如果仅针对特定请求进行更改,则可能具有不同标头的其他请求可能会路由到错误的位置.

其次,您在ZuulRoute对象中设置位置属性,如下所示.

currentRoute.setLocation("https://beta.myserver.com/v1073");

最初的位置属性值是您的service-id -beta-root – 与您的配置.如果您使用具有“http”或“httpsprefix”的特定网址进行更改,则originalRibbonRoutingFilter将无效.相反,SimpleRoutingHostFilter将处理您的请求.这意味着您的未修改请求将由RibbonRoutingFiltera处理,修改后的请求将由SimpleHostRoutingFilter`处理.

更新:根据Http标头路由不同的主机

如果要基于http标头路由到不同的主机,有几种方法可以实现.

案例1:如果您使用Ribbon(和RibbonRoutingFilter)

以下功能仅适用于Edgware.SR1及更高版本.从Eddware.SR1中,您可以在RequestContext中为loadbalancer指定名为FilterConstants.LOAD_BALANCER_KEY的指定值.该值将传递到Ribbon负载均衡器.您可以在预过滤器中放置所需的任何值(任何对象).如果要根据特殊的http标头更改路由,可以在自定义预过滤器中执行此操作.
然后为Ribbon.LOAD_BALANCER_KEY定义自己的IRule实现将提供给您的IRule实现.因此,您可以根据您设置的LOAD_BALANCER_KEY值从Ribbon所具有的服务器列表中选择特定服务器.

您可以找到简要文档here.

您可以在the test case in PR找到示例代码.(RibbonRoutingFilterLoadBalancerKeyIntegrationTests.java)

案例2:如果您正在使用SimpleHostRoutingFilter(没有功能区)

如果在zuul的路由属性中指定url而不是serviceId,那么请求将由SimpleHostRoutingFilter路由而不使用Ribbon.

SimpleHostRoutingFilter只需使用以下代码的主机地址

RequestContext.getCurrentContext().getRouteHost();

该值由PreDecorationFilter设置.因此,您可以在预过滤器中更改此信息.

>制作自己的自定义预过滤器,其序号值介于PreDecorationFilter和SimpleHostRoutingFilter之间.
>在过滤器内部,检查路由主机.如果您要根据HTTP标头更改任何已知主机,请通过RequestContext.getCurrentContext()更改路由主机.基于Http标头的setRouteHost.

在第二种方法的情况下,我没有尝试自己做.我认为这只是理论上的解决方案.
第二种方法的问题是它正在使用SimpleHostRoutingFilter. SimpleHostRoutingFilter不会为请求生成任何HystrixCommand,因此您不能使用Hystrix在Zuul内部提供的任何断路器功能.如果您正在使用Edgware发行版,我认为第一种方法更好.

标签:spring-cloud-netflix,spring,netflix-zuul,canary-deployment
来源: https://codeday.me/bug/20190828/1752418.html