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/
Related
Hey Guys I was developing a simple project with spring boot, which has 2 services user and blogs and I am using eureka server and I tried to implement a gateway service and it also got registered on the eureka server also but I cannot access the route paths of either user or blog service can anyone please help me with this. This the application.yml file for the gateway service.
server:
port: 3030
spring:
application:
name: gateway-service
cloud:
gateway:
routes:
- id: userModule
uri: http://localhost:3001/
predicates:
- Path=/users/**
- id: blogModule
uri: http://localhost:3002/
predicates:
- Path=/blogs/**
eureka:
client:
serviceUrl:
defaultZone: http://localhost:3000/eureka
registerWithEureka:
- true
fetchRegistry:
- true
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
I have few microservices which is registered to Eureka Server(http://localhost:10100)
I am removing instance from eureka server using below REST API
Ref : https://github.com/Netflix/eureka/wiki/Eureka-REST-operations
1) Remove instance from eureka server (DELETE) (It remove instance but again re-register..)
http://localhost:10100/eureka/apps/MICRO-SERVICE-1/localhost:micro-service-1:10501
2) Update status of service to DOWN/OUT_OF_SERVICE
http://localhost:10100/eureka/apps/MICRO-SERVICE-1/localhost:micro-service-1:10501/status?value=DOWN
So even when micro-service-1 status is set to DOWN/OUT_OF_SERVICE I am able to send request to micro-service-1 (http://localhost:10501/MyService/hello)
Instead it should be unavailable but it accepting request an giving response.
So, Why microservice accepts request event though it's status is down in eureka server registry ?
Eureka Server application.yml file
server:
port: 10100
address: localhost
eureka:
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://localhost:10100/eureka/
instance:
prefer-ip-address: true
server:
enable-self-preservation: true
wait-time-in-ms-when-sync-empty: 0
Eureka Client (micro-service-1) application.yml file
server:
port: 10501
address: localhost
eureka:
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://localhost:10100/eureka/
instance:
hostname: localhost
prefer-ip-address: true
Your service has no built-in way of interpreting that you've taken it down in Eureka so calling your service by directly hitting its port will always work.
To make use of the directory's knowledge of server status and multiple instances of servers you need to call your service from an API such as ribbon that can construct a software load balancer from the directory. Alternatively make your calls through the Zuul API proxy which is essentially just a microservice built around ribbon internally.
In all these cases remember that the cloud microservices are eventually consistent. That is, changes you make may not be instantly available and will take time to propagate out to the running services.
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/**
I'm trying to achieve a discovery first spring cloud config mode.
This is my client bootstrap.yml
server:
port: 9090
spring:
application:
name: test-config
cloud:
config:
fail-fast: true
discovery:
enabled: true
serviceId: configservice
eureka:
client:
register-with-eureka: true
serviceUrl.defaultZone: http://localhost:8011/eureka/
The configuration is fetched ok, the client starts but is not registered with eureka
So when I look at the eureka dashboard i see only the config service not the client app. The documentation does not state explicitly that this does not work(if I understand it correctly).
Is this on purpose?
Is this a bug?
Is there a possibility to achieve this setup?
Does your main class include: #EnableEurekaClient?
Could you verify your yml properties are properly spaced?