Auto-configure routes with Zuul and Eureka - spring-boot

Through reading various books / tutorials, it appears that it is possible to auto-configure routes in Zuul when using it in combination with Eureka service discovery. That means that I don't have to explicitly add routes to Zuul's application.properties.
So I understand this correctly? Or do I still need to add routes explicitly to Zuul in order it to work as a gateway?
I would like it to automatically create routes from the application name's that are registered with Eureka. Is this possible?
(Note: I have actually tried this, but when I go to http://localhost:8762/routes I just get an error page.)

Sure. In most microservices implementations, internal microservices endpoints are not exposed outside. A set of public services will be exposed to the clients using an API gateway.
The zuul proxy internally uses the Eureka Server for service discovery.
I would like it to automatically create routes from the application name's that are registered with Eureka. Is this possible?
Sure. I will show you gateway example.
1. Create your service project (user-service)
create application.properties file
# --- Spring Config
spring:
application:
name: OVND-USER-SERVICE
# Eureka client
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URL:http://localhost:8761/eureka/}
2. Setting up Zuul project (Gateway-service)
1.#EnableZuulproxy to tell Spring Boot that this is a Zuul proxy
#SpringBootApplication
#EnableZuulProxy
#EnableDiscoveryClient
public class GatewayServiceApplication {
2.create an application.properties file
# =======================================
# Gateway-service Server Configuration
# =======================================
# --- Spring Config
spring:
application:
name: gateway-service
server:
port: ${PORT:8080}
# Eureka client
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URL:http://localhost:8761/eureka/}
zuul:
host:
routes:
## By default, all requests to user service for example will start with: "/user/"
## What will be sent to the user service is what comes after the path defined,
## So, if request is "/user/v1/user/tedkim", user service will get "/v1/user/tedkim".
user-service:
path: /user/**
service-id: OVND-USER-SERVICE
another-service:
path: /another/**
service-id: OVND-ANOTHER-SERVICE
Eureka website ( localhost:8761 )

Yes. You can integrate Zuul with Eureka and configure the routes based on application names registered in Eureka. Just add the following configuration to Zuul application:
zuul:
ignoredServices: "*"
routes:
a-service: /a-service/**
b-service: /b-service/**
c-service: /c-service/**
d-service: /d-service/**

Related

Path Definition For Each Route in Cloud Gateway

I would like to add a path to each route that I define in spring.cloud.gateway.routes without defining context path, server.servlet.context-path, of each microservice.
E.g.: My gateway runs at port 9090, and my microservice runs at port 8071. The configuration for the microservice in the gateway is like this:
spring:
cloud:
gateway:
routes:
- id: auth
uri: 'http://localhost:8071'
If I hit http://localhost:9090/lorem/ipsum, I can ping the microservice, and see the response. But, I would like to ping the microservice from the gateway as http://localhost:9090/auth/lorem/ipsum.
If I define Path key in predicates, it pings http://localhost:8071/auth/lorem/ipsum, which fails, because the URL in the microservice is not /auth/lorem/ipsum but /lorem/ipsum.
spring:
cloud:
gateway:
routes:
- id: auth
uri: 'http://localhost:8071'
predicates:
- Path=/auth/**
Is there a way to define a path for each microservice or do I have to set server.servlet.context-path for each microservice to achieve what I would like to do?
Spring boot version: 2.6.1 & Spring cloud version: 2021.0.0

How Eureka Server and Spring Cloud API Gateway communicates with each other?

In Spring Boot Microservices architecture, we generally register our each microservice (its many instances) into Eureka server by doing eureka.client.register-with-eureka=true, eureka.client.fetch-registry=true and eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka. So Eureka acts as service registry for these services (service-name, hostname and its IP).
Spring Cloud API Gateway acts as a single point of entry for any microservice call. It can work as a proxy service to route a request to the concerned microservice, abstracting the producer details. It has route information only, then how Spring Cloud API gateway comes to know which microservice instance to call to? How API Gateway and Eureka communicates and load balance?
spring:
application:
name: api-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/users/**
- id: order-service
uri: lb://department-service
predicates:
- Path=/departments/**
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
With the Discovery Locator enabled in API Gateway, you do not have to manually configure the routes unless absolutely needed.
The way API Gateway knows which Eureka Service to route the incoming request to is as follows:
Assuming,
Orders Service runs on http://localhost:8080
API Gateway runs on http://localhost:8082
Eureka Service name for Orders Service - order-service
Then if order-service getOrders endpoint: http://localhost:8080/orders, then with Discovery Locator enabled the request needs to be routed through the API gateway with the following URL: https://localhost:8082/order-service/orders, i.e., {ApiGatewayHost}/{EurekaServiceId}/{ActualEndpoint}.
Register Gatway to Eureka Server

Invalid redirect uri parameters for google oauth2 in spring boot microservice docker implementaion

I'm using spring stack (Spring Boot 2.0.0.RELEASE) for creating a site that delegues user authentication/registration to Google via OAuth2. It is implemented as a few Spring Cloud microservices with a Zuul gateway running on port 8080.
Google Auth Server
Zuul Gateway(:8080)
/ \
/ \
/ \
Other OAuth2 Client Microservice(:8000)
Microservices
I use Google as an OAuth2 server, and use spring-security-oauth2 as a client, which is implemented as a separate microservice. If all my cloud is deployed at localhost everything works fine. But if my microservices are deployed at different machines, e.g. Docker, OAuth2 login doesn't work. getting invalid redirect Uri parameter error.
Zuul configuration for Docker:
zuul:
ignoredServices: '*'
host:
connection-timeout-millis: 20000
socket-timeout-millis: 20000 routes:
authserver_oauth:
path: /oauth2/**
serviceId: authserver
stripPrefix: false
sensitiveHeaders:
Eureka Configuration for Docker:
eureka:
instance:
prefer-ip-address: false
client:
serviceUrl:
defaultZone: http://eureka-server:8761/eureka/
Authserver configuration:
spring:
security:
oauth2:
client:
registration:
google:
clientId: ***
clientSecret: ***
redirectUriTemplate: "{baseUrl}/oauth2/callback/{registrationId}"
scope:
- email
- profile
When I debug for Oauth2 condition I am getting unequal uri for request and response:
authorizationResponse.getRedirectUri()
(java.lang.String) http://authserver:8080/oauth2/callback/google
authorizationRequest.getRedirectUri()
(java.lang.String) http://localhost:8080/oauth2/callback/google
I had a similar issue with Spring boot 2.2.2RELEASE with a cloud environment (NGINX, Docker, Cubernettes) where customising NGINX configuration was not an option at all. Tried methods like setting the x-forwarded-for property, mocking the prod with docker, NGINX setup (https://juplo.de/how-to-redirect-to-spring-security-oauth2-behind-a-gateway-proxy-hiding-the-app-behind-a-reverse-proxy-gateway/) but nothing works. Finally I updated my Spring boot version to 2.4.1 and it worked without any other configuration.

Combining SpringBoot, Zuul and Eureka but bind Services to Localhost

I have set up Zuul for routing and Eureka for service discovery, which works fine. Before setting up Eureka, I used server.address=127.0.0.1 to bind my actual service to localhost so that they could only be accessed from within the Api gateway.
When combining Zuul and Eureka, server.address=127.0.0.1 does not work anymore. I cannot access my actual REST endpoints, neither from within my network nor from the outside.
application.properties of my Eureka service discovery:
spring.application.name=service-discovery
server.port=8761
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
application.properties of my Zuul API gateway:
spring.application.name=api-gateway
zuul.prefix=/api
server.port=8080
ribbon.eureka.enabled=true
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
zuul.routes.library.path=/library/**
zuul.routes.library.serviceId=library
application.properties of my actual REST service:
spring.application.name=library
server.servlet.context-path=/library
server.port=8090
server.address=127.0.0.1
ribbon.eureka.enabled=true
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
When I remove server.address=127.0.0.1 from the REST service's properties file, I can of course access the resource - But also from without localhost, which is not what I want.
So what I try to achieve is that my little microservices can only be accessed from within localhost (after the request has passed the Zuul API gateway). Furthermore I want to use Eureka for service discovery and for having the chance to provide second instances of serives.
Registering the actual microservices with eureka.instance.hostname=localhost or eureka.instance.ip-address=127.0.0.1 to the Eureka server, combined with a binding of the microservice to localhost (server.address=127.0.0.1) did the job.
These are the application.properties files:
application.properties of my Eureka service discovery:
spring.application.name=service-discovery
server.port=8761
server.address=127.0.0.1
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
application.properties of my Zuul API gateway:
spring.application.name=api-gateway
zuul.prefix=/api
server.port=8080
ribbon.eureka.enabled=true
eureka.client.registerWithEureka=false
zuul.routes.library.path=/library/**
zuul.routes.library.serviceId=library
zuul.routes.library.stripPrefix=false
application.properties of my actual REST service:
spring.application.name=library
server.servlet.context-path=/library
server.port=8090
server.address=127.0.0.1
ribbon.eureka.enabled=true
eureka.client.registerWithEureka=true
eureka.instance.hostname=localhost
eureka.instance.ip-address=127.0.0.1
The "library" microservice is now only available from localhost but still registered at Eureka and behind the Zuul API gateway.

Zuul Routing when using eureka services

I have a reasonably simple Spring Cloud Netflix setup. We are using Zuul as a reverse proxy and Eureka for service discovery and registry. we have legacy services we are slowly choking out. We have many simple services that have their endpoints configured like this:
{host}:{port}/{service-name}/**
so now when each service is registered with eureka, and subsequently has a route added to Zuul, the zuul endpoint looks like this:
{zuul-host}:{zuul-port}/{service-name}/{service-name}/**
I want to stop Zuul from striping the prefix off the routed URIs for eureka services so that my zuul endpoints look like this:
{zuul-host}:{zuul-port}/{service-name}/**
and forward to:
{zuul-host}:{zuul-port}/{service-name}/**
I would like this to be done in a way such that I do not have to add configs for each and every service.
I would have assumed that zuul.strip-prefix would have done the trick, but that doesn't appear to be the case.
current Zuul application.yml:
zuul:
routes:
oldservice:
path: /oldservice/**
url: http://oldservice-host:9080/api/v1/oldservice
strip-prefix: false
eureka:
client:
serviceUrl:
defaultZone: http://eureka-host:8761/eureka/
Anyone have a suggestion for how I can configure zuul in this way?
Since you are registering your service with eureka why not use the service-id for routing like below.
the service-id is the id that your service gets registered in Eureka with.
zuul:
routes:
path: /oldservice/**
service-id: oldservice
strip-prefix: false
eureka:
client:
serviceUrl:
defaultZone: http://eureka-host:8761/eureka/
For your current scenario I moved the strip-prefix inside the routes I have it like that in my system you can try that.
zuul:
routes:
oldservice:
path: /oldservice/**
url: http://oldservice-host:9080/api/v1/oldservice
strip-prefix: false
eureka:
client:
serviceUrl:
defaultZone: http://eureka-host:8761/eureka/

Resources