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