Zuul如何实现基于HTTP方式的动态路由,通过'serviceId'解析目标主机?
How to make Zuul dynamic routing based on HTTP method and resolve target host by 'serviceId'?
如何基于HTTP方式做Zuul动态路由(GET/POST/PUT...)?
例如,当您需要将 POST 请求路由到 不同的主机 而不是 '[=18 中描述的默认主机时=]zuul.routes.*'...
zuul:
routes:
first-service:
path: /first/**
serviceId: first-service
stripPrefix: false
second-service:
path: /second/**
serviceId: second-service
stripPrefix: false
即当我们请求 'GET /first' 时,Zuul 将请求路由到 'first-service',但是如果我们请求 'POST /first' 然后 Zuul 将请求路由到 'second-service'.
要实现基于 HTTP 方法的动态路由,我们可以创建自定义“route”类型 ZuulFilter
并通过 [ 解析 'serviceId' =12=]。例如:
@Component
public class PostFilter extends ZuulFilter {
private static final String REQUEST_PATH = "/first";
private static final String TARGET_SERVICE = "second-service";
private static final String HTTP_METHOD = "POST";
private final DiscoveryClient discoveryClient;
public PostOrdersFilter(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
@Override
public String filterType() {
return "route";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String method = request.getMethod();
String requestURI = request.getRequestURI();
return HTTP_METHOD.equalsIgnoreCase(method) && requestURI.startsWith(REQUEST_PATH);
}
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
List<ServiceInstance> instances = discoveryClient.getInstances(TARGET_SERVICE);
try {
if (instances != null && instances.size() > 0) {
context.setRouteHost(instances.get(0).getUri().toURL());
} else {
throw new IllegalStateException("Target service instance not found!");
}
} catch (Exception e) {
throw new IllegalArgumentException("Couldn't get service URL!", e);
}
return null;
}
}
是对的。在这里,我只提出一种更简单的方法(没有服务发现)。假设你有那条路线:
zuul:
routes:
first:
path: /first/**
# No need for service id or url
然后你可以在'route'类型过滤器中路由'/first'路由的请求,只需将位置设置为请求上下文。
@Component
public class RoutingFilter extends ZuulFilter {
@Override
public String filterType() {
return ROUTE_TYPE;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
/* Routing logic goes here */
URL location = getRightLocationForRequest();
ctx.setRouteHost(location);
return null;
}
}
如何基于HTTP方式做Zuul动态路由(GET/POST/PUT...)? 例如,当您需要将 POST 请求路由到 不同的主机 而不是 '[=18 中描述的默认主机时=]zuul.routes.*'...
zuul:
routes:
first-service:
path: /first/**
serviceId: first-service
stripPrefix: false
second-service:
path: /second/**
serviceId: second-service
stripPrefix: false
即当我们请求 'GET /first' 时,Zuul 将请求路由到 'first-service',但是如果我们请求 'POST /first' 然后 Zuul 将请求路由到 'second-service'.
要实现基于 HTTP 方法的动态路由,我们可以创建自定义“route”类型 ZuulFilter
并通过 [ 解析 'serviceId' =12=]。例如:
@Component
public class PostFilter extends ZuulFilter {
private static final String REQUEST_PATH = "/first";
private static final String TARGET_SERVICE = "second-service";
private static final String HTTP_METHOD = "POST";
private final DiscoveryClient discoveryClient;
public PostOrdersFilter(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
@Override
public String filterType() {
return "route";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String method = request.getMethod();
String requestURI = request.getRequestURI();
return HTTP_METHOD.equalsIgnoreCase(method) && requestURI.startsWith(REQUEST_PATH);
}
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
List<ServiceInstance> instances = discoveryClient.getInstances(TARGET_SERVICE);
try {
if (instances != null && instances.size() > 0) {
context.setRouteHost(instances.get(0).getUri().toURL());
} else {
throw new IllegalStateException("Target service instance not found!");
}
} catch (Exception e) {
throw new IllegalArgumentException("Couldn't get service URL!", e);
}
return null;
}
}
zuul:
routes:
first:
path: /first/**
# No need for service id or url
然后你可以在'route'类型过滤器中路由'/first'路由的请求,只需将位置设置为请求上下文。
@Component
public class RoutingFilter extends ZuulFilter {
@Override
public String filterType() {
return ROUTE_TYPE;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
/* Routing logic goes here */
URL location = getRightLocationForRequest();
ctx.setRouteHost(location);
return null;
}
}