In my MicroserviceZoo i have a Zuul gateway and 3 Microservices (service1,service2,service3) discovered by Eureka. Zuul shall represent them to the outside and act as api-gateway with loadbalancing (ribbon) and circuit-breaking(hystrix).
Now in the service routing i have a problem which may seem simple to fix, but i am stuck with this far too long.
What i want is that Zuul routes to service1, service2, service3 over the same API:
gateway:port/api/1/service1/public/time
should become
gateway:port/api/1/public/time
and
gateway:port/api/1/service2/public/stats
shall become
gateway:port/api/1/public/stats
..such that /api/1/public/stats routes to microservice2 (which hosts the stats method) and /api/1/public/time routes to microservice1 (which hosts the time method)
This is my current Zuul-Config (in bootstrap.yml):
zuul:
prefix: /api/1
stripPrefix: false
routes:
time:
path: /**/public/time
serviceId: service1
stats:
path: /**/public/stats
serviceId: service2
stream:
path: /**/public/stream
serviceId: service3
ignored-services: '*'
strip-prefix: false
What am i missing? How do you fine-grained route using Zuul and Eureka?
Answer:
There is no way to do this easily in Netflix Zuul, as pointed out by Spring Cloud Gateway dev Spencer Gibb
Unfortunately zuul from spring cloud can only strip prefixes. You want rewrite functionality which is only available in spring cloud gateway unless you write your own filter – spencergibb Jul 13 '19 at 20:37
The Solution is to switch to Spring Cloud Gateway, which should be easily possible for most deployments of Zuul.
there you can easily rewrite routes individually, e.g.:
spring:
cloud:
gateway:
- id: streamservice
uri: lb://streamservice
predicates:
- Path=/stream/**
filters:
- RewritePath=/api/(?<streamservice>.*), /$\{streamservice}
- id: otherservices
uri: lb://otherservices
predicates:
- Path=/otherserviceendpoint
filters:
- RewritePath=/api/(?<otherservices>.*), /$\{otherservices}
To achieve the functionality asked in the question, which implied that some services dont get handled by the gateway at all, in cloud gateway define a locator rule to only locate services (via Eureka el al discovery service ) that include "isongateway:true' as metadata in the gateways conf.yml:
spring:
cloud:
gateway:
discovery:
locator:
include-expression: metadata['isongateway']=='true'
enabled: true
so in the services, that should be located & routed by gateway you add the tag to the conf.yml:
# this is so we can exclude all services that dont have this metadata in gateway
spring:
cloud:
discovery:
client:
simple:
local:
metadata:
isongateway: true
...and now all other services are not routed by the gateway.