在Spring Cloud Netflix Zuul中以编程方式设置路由
作者:互联网
我创建了两个AWS Beanstalk环境,每个环境都有自己的应用程序版本.这些env的URL是https://beta.myserver.com/v1073和https://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