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

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

Related

How to load balance request to list of URIs in Spring Cloud Gateway

I don't have eureka, load balancer and so on. I want to load balance the request to list of URIs on which instances of backend run.
spring:
cloud:
gateway:
routes:
- id: myService-endpoints
uri: myServiceIp1, myServiceIp2
predicates:
- Path=/myservice/**
myServiceIp1 and myServiceIp2 are my backend service IPs. How can I achieve load balancing in this scenario?
If you are not using service registry, you can still use load-balancing in your app. You will just need to use the SimpleDiscoveryClient that allows you to set your service instance URIs via a property file, like so:
spring.cloud.discovery.client.simple.instances.service1[0].uri=http://s11:8080
Then you can just follow the guides for setting up load-balanced routes in Gateway, like so:
spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**

Using the auth filter in an api gateway Spring boot

I made 2 microservices running on a cluster in Kubernetes , I was able to make an API gateway using spring cloud to call those microservices , and I made a JWT Authorization and Authentication filters in another project .
My question is, how can I integrate these filters in my API gateway to authorize the access to my microservices
spring:
cloud:
gateway:
routes:
- id: r1
uri: http://192.168.49.2:30288/
predicates:
- Path= /api1/**
- id: r2
uri: http://192.168.49.2:30289/
predicates:
- Path= /api2/**
discovery:
enabled: false
server:
port: 8888

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

Auto-configure routes with Zuul and Eureka

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/**

How to get the service endpoint registered behind the Application name in Eureka Server?

I have some web services registered at Spring Boot Eureka Server. Is there any way I can check the endpoints registered at Eureka Server, with respect to all the application?
e.g: Eureka server
Service1 means Request will be routed to service endpoint: localhost:9080/service1
Service2 means Request will be routed to service endpoint: localhost:9088/service2
Service3 means Request will be routed to service endpoint: localhost:9085/service3
You can check the Eureka dashboard at http://host-name:8761 (Change the port if you're using a different one).
Secondly, Eureka doesn't route any request. It is just a service registry and keeps the records of the Microservices and its instances. You need an API Gateway (ZUUL) or similar to do the routing along with client side load balancers (ribbon, etc.).
You can configure the zuul endpoints in the application.yml (or properties) file like below to access your service endpoints.
zuul:
ignoredServices: "*"
routes:
service1:
path: /service1/**
service2:
path: /service2/**
If you want to access the service1, then your endpoint will be something like http://localhost:8765/service1/{custom-path}
Note: 8765 is the default zuul port. Change it accordingly.

Resources