Giải Quyết Vấn Đề Quản Lý Vi Dịch Vụ Spring Cloud Bằng Trung Tâm Đăng Ký Eureka

Lớp khởi động:

@MapperScan("com.example.order.mapper")
@SpringBootApplication
public class ServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceApplication.class, args);
    }
    
    @Bean
    public HttpClient httpClient() {
        return HttpClient.create();
    }
}

Lớp dịch vụ:

@Service
public class OrderService {

    @Autowired
    private OrderRepository orderRepo;

    @Autowired
    private HttpClient client;
    public Order fetchOrderDetails(Long orderId) {
        // 1. Tra cứu đơn hàng
        Order order = orderRepo.findById(orderId);
        // Kiểm tra null
        if (order == null) {
            return null;
        }
        // Lấy định danh người dùng
        String userKey = order.getUserKey();
        // Gọi API dịch vụ người dùng
        String endpoint = "http://user-service/api/users/" + userKey;
        User userDetails = client.get(endpoint, User.class);
        // Kết hợp dữ liệu
        order.setUserDetails(userDetails);
        return order;
    }
}

Cách tiếp cận hiện tại sử dụng HttpClient với địa chỉ cố định (ip:port) không phù hợp khi triển khai đa thể thực thi, thiếu cơ chế phân phối tải. Như hình minh họa:

Vấn Đề Chính:

  1. Người gọi không biết địa chỉ cụ thể của dịch vụ cung cấp
  2. Ngay cả khi biết địa chỉ, làm thế nào chọn giữa nhiều thể thực thi?
  3. Không tự động cập nhật trạng thái khi dịch vụ gặp sự cố hoặc mới được triển khai

Nguyên Lý Trung Tâm Đăng Ký:

  1. Tất cả dịch vụ đăng ký thông tin (tên dịch vụ, địa chỉ ip, cổng, phương thức khả dụng) vào trung tâm khi khởi động
  2. Trung tâm lưu trữ bản đồ tên dịch vụ đến danh sách địa chỉ thể thực thi
  3. Người gọi tra cứu thông tin dịch vụ qua tên, nhận danh sách địa chỉ từ trung tâm
  4. Áp dụng chiến lược phân phối tải để chọn thể thực thi
  5. Dịch vụ định kỳ gửi tín hiệu sống (heartbeat) tới trung tâm, nếu vượt quá thời gian cho phép sẽ bị xóa khỏi danh sách

Lưu ý: Một dịch vụ có thể vừa đóng vai trò cung cấp vừa là người gọi, vì vậy Eureka tích hợp cả chức năng đăng ký và phát hiện dịch vụ trong eureka-client

Triển Khai Eureka Và Gọi Dịch Vụ Xa:

Cấu trúc dự án:

1. Thiết lập Trung Tâm Đăng Ký

Tạo module eureka-registration trong project cha:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

Lớp khởi động:

@SpringBootApplication
@EnableEurekaServer
public class RegistrationServer {
    public static void main(String[] args) {
        SpringApplication.run(RegistrationServer.class, args);
    }
}

Tệp cấu hình application.yml:

server:
  port: 8761
spring:
  application:
    name: registration-center
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

2. Đăng Ký Dịch Vụ

Thêm phụ thuộc vào module user-service:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Cấu hình application.yml:

spring:
  application:
    name: user-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

3. Phát Hiện Dịch Vụ

Thêm phụ thuộc vào module order-service:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Cấu hình application.yml:

spring:
  application:
    name: order-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

Áp dụng cân bằng tải (trong lớp ServiceApplication):

@MapperScan("com.example.order.mapper")
@SpringBootApplication
public class ServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceApplication.class, args);
    }

    @Bean
    @LoadBalanced
    public HttpClient createHttpClient() {
        return HttpClient.create();
    }
}

Cập nhật phương thức fetchOrderDetails trong OrderService:

@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepo;
    @Autowired
    private HttpClient client;
    public Order fetchOrderDetails(Long orderId) {
        Order order = orderRepo.findById(orderId);
        if (order == null) return null;
        String userKey = order.getUserKey();
        String endpoint = "http://user-service/api/users/" + userKey;
        User userDetails = client.get(endpoint, User.class);
        order.setUserDetails(userDetails);
        return order;
    }
}

Spring sẽ tự động lấy danh sách thể thực thi từ trung tâm đăng ký dựa trên tên dịch vụ và áp dụng cân bằng tải.

Thẻ: Spring Cloud eureka Load Balancing

Đăng vào ngày 23 tháng 9 lúc 16:05