Cân Bằng Tải Trong Spring Cloud: Ribbon và LoadBalancer

Bài viết được tham khảo từ nguồn: https://www.modb.pro/db/380587

Sau năm 2020, khi các thành phần Netflix trong Spring Cloud ngừng cập nhật, Spring Cloud đã phát triển hệ thống cân bằng tải mới. Bài viết này phân tích chi tiết hai thành phần tiêu biểu là Ribbon và LoadBalancer.

So Sánh Hiện Trạng

Ribbon:

  • Ở trạng thái bảo trì, vẫn được sử dụng rộng rãi nhờ hiệu năng ổn định. Tuy nhiên, từ phiên bản Spring Cloud mới nhất đã loại bỏ phụ thuộc của Ribbon.

LoadBalancer:

  • Đang được Spring Cloud tích hợp mạnh mẽ. Với sự hỗ trợ của Spring WebFlux, LoadBalancer cho phép cân bằng tải với client phản ứng (reactive client).
  • Hỗ trợ chiến lược cân bằng tải ngẫu nhiên và sẽ dần thay thế hoàn toàn các giải pháp cũ.

Giới Thiệu & Thực Hành Ribbon

Khái niệm cơ bản:

  • Ribbon là dự án mã nguồn mở của Netflix, cung cấp cơ chế cân bằng tải phía client với các tính năng cấu hình như timeout, retry.
  • Quy trình hoạt động:
  1. Lấy danh sách service từ trung tâm đăng ký
  2. Áp dụng thuật toán (round-robin, random...) để chọn instance
  3. Gọi service qua Feign/OpenFeign

Chiến lược cân bằng tải:

  • RoundRobinRule: Luân phiên
  • RandomRule: Ngẫu nhiên
  • RetryRule: Thử lại khi lỗi
  • WeightedResponseTimeRule: Ưu tiên instance phản hồi nhanh
  • BestAvailableRule: Chọn instance có độ trễ thấp nhất
  • ZoneAvoidanceRule: Mặc định, cân nhắc vùng địa lý và độ sẵn sàng

Tùy chỉnh chiến lược:

  1. Lớp cấu hình cần đặt ở package ngoài phạm vi quét của @ComponentScan
  2. Ví dụ thay thế chiến lược mặc định bằng ngẫu nhiên:
@Configuration
public class CustomRule {
    @Bean
    public IRule customRule() {
        return new RandomRule();
    }
}
  1. Kích hoạt tại lớp khởi động:
@RibbonClient(name = "service-payment", configuration = CustomRule.class)
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Giới Thiệu & Thực Hành LoadBalancer

Ưu điểm nổi bật:

  • Hỗ trợ RestTemplate tương tự Ribbon
  • Cân bằng tải cho client phản ứng thông qua WebFlux (dựa trên Netty AIO)

Cấu hình phụ thuộc:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

Tắt Ribbon mặc định:

spring:
  cloud:
    loadbalancer:
      ribbon:
        enabled: false

Ví dụ sử dụng RestTemplate:

@Configuration
public class WebClientConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@RestController
@RequestMapping("/api")
public class ServiceController {
    @Value("${service.url}")
    private String serviceUrl;
    
    @Autowired
    private RestTemplate restTemplate;
    
    @GetMapping("/get/{id}")
    public ResponseEntity<?> getService(@PathVariable Long id) {
        return restTemplate.getForEntity(serviceUrl + "/data/" + id, String.class);
    }
}

Cân bằng tải với WebClient:

@Configuration
public class WebClientConfig {
    @Bean
    @LoadBalanced
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}

@RestController
@RequestMapping("/api")
public class ServiceController {
    @Value("${service.url}")
    private String serviceUrl;
    
    @Autowired
    private WebClient.Builder webClientBuilder;
    
    @GetMapping("/webclient/{id}")
    public Mono<String> getServiceWebClient(@PathVariable Long id) {
        return webClientBuilder.build()
            .get().uri(serviceUrl + "/data/" + id)
            .retrieve().bodyToMono(String.class);
    }
}

Tùy chỉnh chiến lược LoadBalancer:

@Configuration
public class RandomConfig {
    @Bean
    public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
        Environment env, LoadBalancerClientFactory factory) {
        String name = env.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(
            factory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }
}

@SpringBootApplication
@LoadBalancerClient(value = "service-payment", configuration = RandomConfig.class)
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Thẻ: Spring Cloud Load Balancing ribbon LoadBalancer WebFlux

Đăng vào ngày 4 tháng 7 lúc 14:49