client side load balancing happens

client side load balancing happens

Client-side load balancing is a technique where the client is responsible for distributing requests across multiple instances of a microservice. This approach allows the client to make intelligent decisions about which instance to call based on various factors such as response times, instance health, etc. In Spring Boot microservices, client-side load balancing is commonly achieved using Spring Cloud LoadBalancer or Netflix Ribbon.

client side load balancing happens

Key Concepts:

  • 1. Service Discovery: The client needs to know the available instances of the service. This is usually achieved through a service registry like Eureka, Consul, or Zookeeper.
  • 2. Load Balancer: The client library (e.g., Spring Cloud LoadBalancer or Ribbon) that distributes the requests among the instances.
  • 3. RestTemplate/WebClient: Spring’s utilities that can be enhanced with load-balancing capabilities.

Example using Spring Cloud LoadBalancer

We have two instances of a User Service running on different ports. An Order Service uses client-side load balancing to communicate with User Service instances.

User Service
```java
// UserServiceApplication.java
@SpringBootApplication
@RestController
@RequestMapping("/users")
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable String id) {
        return new User(id, "John Doe", "john.doe@example.com", System.currentTimeMillis());
    }
}

// User.java
public class User {
    private String id;
    private String name;
    private String email;
    private long timestamp; // To distinguish which instance responded

    // Constructors, Getters, and Setters
}
```

Order Service
```java
// OrderServiceApplication.java
@SpringBootApplication
@RestController
@RequestMapping("/orders")
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/{orderId}")
    public Order getOrderById(@PathVariable String orderId) {
        ResponseEntity<User> response = restTemplate.getForEntity("http://user-service/users/123", User.class);
        User user = response.getBody();
        return new Order(orderId, "Product 1", user);
    }
}

// Order.java
public class Order {
    private String orderId;
    private String productName;
    private User user;

    // Constructors, Getters, and Setters
}

// RestTemplateConfig.java
@Configuration
public class RestTemplateConfig {
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
```

Configuration (application.yml)
```yaml
spring:
  application:
    name: order-service
server:
  port: 8081

# Instance 1 of user service
---
spring:
  profiles: instance1
  application:
    name: user-service
server:
  port: 8082

# Instance 2 of user service
---
spring:
  profiles: instance2
  application:
    name: user-service
server:
  port: 8083

# Order service
---
spring:
  application:
    name: order-service
server:
  port: 8081
```

Explanation

  • 1. User Service:
    • Provides an endpoint `/users/{id}` to get user details.
    • Running two instances on different ports (8082 and 8083).
  • 2. Order Service:
    • Uses `RestTemplate` with `@LoadBalanced` annotation to enable client-side load balancing.
    • The `getOrderById` method calls the User Service to get user details and then creates an Order object using the retrieved user information.
    • The `@LoadBalanced` RestTemplate ensures that the requests are distributed across available instances of the User Service.

Advantages:

  • Scalability: Easily handles traffic by distributing requests among multiple instances.
  • Resilience: If one instance fails, requests are automatically routed to healthy instances.
  • Flexibility: Clients can make intelligent decisions about which instance to use based on custom logic.