Spring Cloud: Zuul, Eureka Integration in SpringBoot Applications
What is Zuul: Zuul is a proxy server which uses filter to perform authentication, authorization, real-time monitoring, dynamic routing, load shedding, and static response handling. It can also be used for load testing as well.
What is Eureka: Eureka is a REST based service that is used in cloud for locating instances of services for load balancing and failover of middle-tier servers. Eureka allows two microservices to communicate with each other without knowing each other’s whereabouts. Services just need to know the service names that they need to reach.
What is Eureka Client: It is any service that wants to discover other services.
What is Eureka Instance: It is a microservice that wants to register with Eureka so that other microservices can discover and use it.
What problem we are solving: Using the above architecture we can deploy and undeploy services with zero downtime. We are also dynamically routing to multiple instances of services.
We will follow the below architecture and will deploy and undeploy services.
Create Service Discovery: For creating service discovery we will start with a sample Spring Boot project and follow the below steps.
Maven configurations: It contains actuator and eureka-server dependencies.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
App properties: We will add below properties in service discovery application.yaml properties file. Most of the properties are default. You can tune according to your needs.
server:
port: 8989
address: 127.0.0.1
spring:
application:
name: service-discovery
eureka:
environment: local
rateLimiter:
enabled: false
throttleStandardClients: false
burstSize: 10
registryFetchAverageRate: 500
fullFetchAverageRate: 100
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://yourUser:yourPassword@127.0.0.1:8989/eureka
server:
responseCacheUpdateIntervalMs: 30000
minThreadsForPeerReplication: 5
maxThreadsForPeerReplication: 20
maxTimeForReplication: 30000
minThreadsForStatusReplication: 1
maxThreadsForStatusReplication: 1
numberOfReplicationRetries: 5
peerEurekaStatusRefreshTimeIntervalMs: 30000
waitTimeInMsWhenSyncEmpty: 30000
peerNodeConnectTimeoutMs: 200
peerNodeReadTimeoutMs: 200
peerNodeTotalConnections: 1000
peerNodeTotalConnectionsPerHost: 500
instance:
leaseRenewalIntervalInSeconds: 30
To enable Eureka Server we will add @EnableEurekaServer to ServiceDiscoverApplication class
package com.test.servicediscovery;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class ServiceDiscoveryApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceDiscoveryApplication.class, args);
}
}
Now start the server. When you open http://127.0.0.1:8989/. As there are no services currently registered with service-discovery, you will see an empty table.
Now we will create a eureka client and zuul routing server.
Zuul Server: For creating Zuul Server we will start with sample spring boot project and follow the below steps.
Maven configurations: It contains actuator, zuul, and eureka-client related dependencies.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
App properties: We will add the below properties. We have added route path for product-search-service, user-service, and order-management-service. zuul.prefix will capture all the requests starting with /api and will use route information to route it to the respective service.
server:
port: 4444
spring:
application:
name: zuul-server
zuul:
sensitiveHeaders: Cookie,Set-Cookie
prefix: /api
health:
enabled: true
routes:
productSearchService:
path: "/product-search-service/**"
serviceId: product-search-service
sensitiveHeaders: Cookie,Set-Cookie
stripPrefix: true
orderManagementService:
path: "/order-management-service/**"
serviceId: order-management-service
sensitiveHeaders: Cookie,Set-Cookie
stripPrefix: true
userService:
path: "/user-service/**"
serviceId: user-service
sensitiveHeaders: Cookie,Set-Cookie
stripPrefix: true
host:
maxTotalConnections: 200
maxPerRouteConnections: 20
ribbon:
eager-load:
enabled: true
ConnectTimeout: 3000
ReadTimeout: 60000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 50000
eureka:
client:
register-with-eureka: true
fetch-registry: true
serviceUrl:
defaultZone: http://yourUser:yourPassword@127.0.0.1:8989/eureka/
registryFetchIntervalSeconds: 30
instanceInfoReplicationIntervalSeconds: 30
initialInstanceInfoReplicationIntervalSeconds: 40
eurekaServiceUrlPollIntervalSeconds: 300
eurekaServerReadTimeoutSeconds: 8
eurekaServerConnectTimeoutSeconds: 5
eurekaServerTotalConnections: 200
eurekaServerTotalConnectionsPerHost: 50
heartbeatExecutorThreadPoolSize: 2
heartbeatExecutorExponentialBackOffBound: 10
cacheRefreshExecutorThreadPoolSize: 2
cacheRefreshExecutorExponentialBackOffBound: 10
gZipContent: true
preferSameZoneEureka: true
filterOnlyUpInstances: true
healthcheck:
enabled: true
instance:
preferIpAddress: true
leaseRenewalIntervalInSeconds: 30
leaseExpirationDurationInSeconds: 90
To enable Zuul server add @EnableZuulProxy and to make it Eureka client add
@EnableEurekaClient annotation on ZuulServerApplication class
package com.test.zuulServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServerApplication.class, args);
}
}
Create user-service microservice: For creating the user-service let’s start with the sample springBoot project and follow the below steps.
Project structure:
Maven Configurations: It contains below dependencies.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
App properties:
server:
port: 3333
spring:
application:
name: user-service
eureka:
client:
register-with-eureka: true
fetch-registry: true
serviceUrl:
defaultZone: http://yourUser:yourPassword@127.0.0.1:8989/eureka/
registryFetchIntervalSeconds: 30
instanceInfoReplicationIntervalSeconds: 30
initialInstanceInfoReplicationIntervalSeconds: 40
eurekaServiceUrlPollIntervalSeconds: 300
eurekaServerReadTimeoutSeconds: 8
eurekaServerConnectTimeoutSeconds: 5
eurekaServerTotalConnections: 200
eurekaServerTotalConnectionsPerHost: 50
heartbeatExecutorThreadPoolSize: 2
heartbeatExecutorExponentialBackOffBound: 10
cacheRefreshExecutorThreadPoolSize: 2
cacheRefreshExecutorExponentialBackOffBound: 10
gZipContent: true
preferSameZoneEureka: true
filterOnlyUpInstances: true
healthcheck:
enabled: true
instance:
preferIpAddress: true
leaseRenewalIntervalInSeconds: 30
leaseExpirationDurationInSeconds: 90
Similar zuulServer we will add @EnableEurekaClient to register with Eureka
package com.test.userservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
Similarly, we will create order-management-service and product-search-service
Adding more instances to the cluster: Assume we got to add more instances, we can add easily changing instanceId of eureka client. InstanceId is composed of
${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
Lets add one more instance of product-search-service. We have just started the service with unique InstanceId, this service will be automatically discovered by other eureka clients in time(as you have configured).
Similarly, we can also add other instances of zuul-server and order-management-service.
Now to deregister service from service-discovery you can gracefully close the application or you can use api to manually deregister it.
When you use execute above url , you will see that one of the product-search-service is not avaliable to other eureka clients