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:
- Người gọi không biết địa chỉ cụ thể của dịch vụ cung cấp
- Ngay cả khi biết địa chỉ, làm thế nào chọn giữa nhiều thể thực thi?
- 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ý:
- 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
- Trung tâm lưu trữ bản đồ tên dịch vụ đến danh sách địa chỉ thể thực thi
- 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
- Áp dụng chiến lược phân phối tải để chọn thể thực thi
- 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.