Introduction to Client-Side Load Balancing
Client-side load Balancing is a technique where the client, instead of a central server, decides which instance of a service to send the request to. This approach can help distribute the load better among service instances and increase fault tolerance. Spring Cloud provides support for client-side load balancing through Spring Cloud LoadBalancer.
Prerequisites
- JDK 17 or later
- Maven or Gradle
- Docker
- IDE (IntelliJ IDEA, Eclipse, etc.)
Step 1: Set Up Eureka Server
1.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Eureka Server
1.2 Configure application.properties
Set up the application properties for the Eureka Server.
server.port=8761 spring.application.name=eureka-server eureka.client.register-with-eureka=false eureka.client.fetch-registry=false
Explanation:
server.port=8761
: Sets the port for the Eureka Server.spring.application.name=eureka-server
: Names the application.eureka.client.register-with-eureka=false
: Indicates that the Eureka Server itself should not try to register with another Eureka Server.eureka.client.fetch-registry=false
: Indicates that the Eureka Server should not attempt to fetch registry information from another Eureka Server.
1.3 Enable Eureka Server
Add the @EnableEurekaServer
annotation to the main application class.
package com.example.eurekaserver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
Step 2: Set Up service-a
2.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Spring Web
- Eureka Discovery Client
2.2 Configure application.properties
Set up the application properties for service-a
.
server.port=0 spring.application.name=service-a eureka.client.service-url.default-zone=http://localhost:8761/eureka/
Explanation:
server.port=0
: Lets the application choose a random available port.spring.application.name=service-a
: Names the application.eureka.client.service-url.default-zone=http://localhost:8761/eureka/
: Specifies the Eureka Server URL for service registration.
2.3 Enable Eureka Client
Add the @EnableDiscoveryClient
annotation to the main application class.
package com.example.servicea; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class ServiceAApplication { public static void main(String[] args) { SpringApplication.run(ServiceAApplication.class, args); } }
Explanation:
@EnableDiscoveryClient
: Indicates that this application should register with a Eureka Server for service discovery.
2.4 Create a Controller
Create a controller to handle requests.
package com.example.servicea; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ServiceAController { @GetMapping("/service-a") public String getServiceA() { return "Response from Service A"; } }
Explanation:
@RestController
: Marks this class as a REST controller.@GetMapping("/service-a")
: Maps GET requests to/service-a
to this method.
Step 3: Set Up service-b
(Client)
3.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Spring Web
- Eureka Discovery Client
- Spring Cloud LoadBalancer
3.2 Configure application.properties
Set up the application properties for service-b
.
server.port=8081 spring.application.name=service-b eureka.client.service-url.default-zone=http://localhost:8761/eureka/
Explanation:
server.port=8081
: Sets the port for the client service.spring.application.name=service-b
: Names the application.eureka.client.service-url.default-zone=http://localhost:8761/eureka/
: Specifies the Eureka Server URL for service registration.
3.3 Enable Eureka Client
Add the @EnableDiscoveryClient
annotation to the main application class.
package com.example.serviceb; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class ServiceBApplication { public static void main(String[] args) { SpringApplication.run(ServiceBApplication.class, args); } }
Explanation:
@EnableDiscoveryClient
: Indicates that this application should register with a Eureka Server for service discovery.
3.4 Create a RestTemplate Bean
Create a configuration class to define a RestTemplate bean with load balancing.
package com.example.serviceb; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class AppConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
Explanation:
@Bean
: Marks this method as a bean producer.@LoadBalanced
: Adds client-side load balancing to the RestTemplate.
3.5 Create a Controller
Create a controller to handle requests and use the RestTemplate to call service-a
.
package com.example.serviceb; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class ServiceBController { @Autowired private RestTemplate restTemplate; @GetMapping("/service-b") public String callServiceA() { return restTemplate.getForObject("http://service-a/service-a", String.class); } }
Explanation:
@RestController
: Marks this class as a REST controller.@GetMapping("/service-b")
: Maps GET requests to/service-b
to this method.RestTemplate restTemplate
: Injects the RestTemplate with load balancing.restTemplate.getForObject("http://service-a/service-a", String.class)
: Uses the service nameservice-a
to call the endpoint, and the load balancer will distribute the request among available instances.
Step 4: Run the Services
- Start the Eureka Server: Run the
EurekaServerApplication
class. - Start multiple instances of
service-a
:- Use the following command to start the first instance:
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dserver.port=8082"
- Use the following command to start the second instance:
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dserver.port=8083"
- Use the following command to start the first instance:
- Start
service-b
: Run theServiceBApplication
class.
Step 5: Test the Load Balancing
Open your browser or use a tool like Postman to test the endpoint:
service-b
:http://localhost:8081/service-b
Make multiple requests to this endpoint. You should see responses from different instances of service-a
, indicating that the load balancer is distributing the requests.
Conclusion
You have successfully set up client-side load balancing in a Spring Boot microservices architecture using Eureka for service discovery and Spring Cloud LoadBalancer. This setup allows you to distribute requests among multiple instances of a microservice, increasing fault tolerance and scalability. This example can be expanded to include more microservices and more complex load balancing and routing logic.
Comments
Post a Comment