Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match route in spring zuul based on strict matching

Summary: ZUUL doesnt pick the right destination url for the input path since it doesnt do strict matching of the input path.

Below is my zuul routes :

zuul:
  routes: 
    auth:
      path: /v1/txn/**
      url: http://localhost:8900/v1/cardhostauth
    cardproduct: 
      path: /v1/customer/card/product/**
      url: http://localhost:8800/v1/customer/card/product
    cardcomposite:
      path: /v1/customer/**
      url: http://localhost:8400/v1/composite

For input path:"/v1/customer/card/product/" , It is expected to choose -http://localhost:8800/v1/customer/card/product but it chooses http://localhost:8400/v1/composite. My expectation was that the path pattern match happens in the order specified and is stricter but seems it doesnt work that way.

Can you let me know how ZUUL works when you have multiple routes defined for similar input path ?

Thx

P.S - I can see this issue when i run via Docker in AWS but the issue doesn't come up when i run from eclipse. Has the order of zuul route depend on the spring zuul jar (spring-cloud-starter-netflix-zuul - 2.0.0.RELEASE vs 2.0.1.RELEASE)

like image 554
Cshah Avatar asked Oct 10 '18 07:10

Cshah


People also ask

When a circuit is given a route in Zuul tripped?

When a circuit for a given route in Zuul is tripped you can provide a fallback response by creating a bean of type ZuulFallbackProvider . Within this bean you need to specify the route ID the fallback is for and provide a ClientHttpResponse to return as a fallback.

How does Zuul routing work?

Zuul is an edge service that proxies requests to multiple backing services. It provides a unified “front door” to your system, which allows a browser, mobile app, or other user interface to consume services from multiple hosts without managing cross-origin resource sharing (CORS) and authentication for each one.

Does Zuul automatically uses Hystrix?

Zuul creates a Hystrix circuit breaker for each route (serviceId). It means that one Hystrix circuit breaker will be shared between your all instances of payment-services. The circuit breaker that Zuul creates for each route is not for removing an unhealthy instance from the routing list.

What is the difference between Zuul and spring cloud gateway?

Zuul is built on servlet 2.5 (works with 3. x), using blocking APIs. It doesn't support any long lived connections, like websockets. Gateway is built on Spring Framework 5, Project Reactor and Spring Boot 2 using non-blocking APIs.


2 Answers

For picking the route based on best match, i found this thread helpful (thanks to @maximdim). Basically you can write your own custom router to pick best matching route.

https://github.com/spring-cloud/spring-cloud-netflix/issues/2408

Hope this helps. (And as it's my first answer, my apologies if it is not a good one.)

An example taken from github thread goes as follows:

public class CustomRouteLocator extends SimpleRouteLocator {
    public CustomRouteLocator(String servletPath, ZuulProperties properties) {
        super(servletPath, properties);
    }

    @Override
    protected ZuulRoute getZuulRoute(String adjustedPath) {
        // Spring's AbstractUrlHandlerMapping already found best matching path for us
        // and stored it into request attribute. See AbstractUrlHandlerMapping.exposePathWithinMapping
        RequestContext ctx = RequestContext.getCurrentContext();
        String bestMatchingPattern = (String)ctx.getRequest().getAttribute(HandlerMapping.class.getName() + ".bestMatchingPattern");
        if (bestMatchingPattern == null) {
            return super.getZuulRoute(adjustedPath);
        }

        if (!matchesIgnoredPatterns(adjustedPath)) {
            return locateRoutes().get(bestMatchingPattern);
        }
        return null;
    }
}

@maximdim:

Instead of duplicating logic to find 'best match' I simply getting it from request attribute, where Spring's HandlerMapping saves it. A bit hacky perhaps, but seems to work for me.

like image 96
Arun Kumar Attri Avatar answered Sep 29 '22 08:09

Arun Kumar Attri


Editing answer based on Zuul's official documentation: https://cloud.spring.io/spring-cloud-netflix/multi/multi__router_and_filter_zuul.html

If you need your routes to have their order preserved, you need to use a YAML file, as the ordering is lost when using a properties file. The following example shows such a YAML file:

application.yml.

 zuul:
  routes:
    users:
      path: /myusers/**
    legacy:
      path: /**

If you were to use a properties file, the legacy path might end up in front of the users path, rendering the users path unreachable.

Make sure you're using the latest stable version of Spring Cloud (currently 2.0.2)

like image 31
Fabio Manzano Avatar answered Sep 29 '22 06:09

Fabio Manzano