微服务之间如何通信
·
微服务之间的通信是微服务架构的核心,主要有同步和异步两大类通信方式。下面我详细解释各种通信机制:
1. 同步通信方式
1.1 RESTful HTTP API(最常用)
java
// 服务A调用服务B的REST API
@Service
public class OrderService {
// 使用 RestTemplate
@Autowired
private RestTemplate restTemplate;
public UserDTO getUserInfo(Long userId) {
// 直接HTTP调用
ResponseEntity<UserDTO> response = restTemplate.getForEntity(
"http://user-service/api/users/" + userId,
UserDTO.class
);
return response.getBody();
}
}
// 配置 RestTemplate
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced // 支持服务发现
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
1.2 OpenFeign(声明式REST客户端)
java
// 1. 定义Feign客户端接口
@FeignClient(name = "user-service", path = "/api/users")
public interface UserServiceClient {
@GetMapping("/{userId}")
UserDTO getUserById(@PathVariable("userId") Long userId);
@PostMapping
UserDTO createUser(@RequestBody UserDTO user);
@GetMapping("/search")
List<UserDTO> searchUsers(@RequestParam("keyword") String keyword);
}
// 2. 在业务服务中使用
@Service
public class OrderService {
@Autowired
private UserServiceClient userServiceClient;
public Order createOrder(OrderRequest request) {
// 像调用本地方法一样调用远程服务
UserDTO user = userServiceClient.getUserById(request.getUserId());
// 业务逻辑...
return order;
}
}
// 3. 启用Feign客户端
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
1.3 gRPC(高性能RPC框架)
protobuf
// 1. 定义proto文件 (user.proto)
syntax = "proto3";
service UserService {
rpc GetUser (UserRequest) returns (UserResponse);
}
message UserRequest {
int64 user_id = 1;
}
message UserResponse {
int64 user_id = 1;
string name = 2;
string email = 3;
}
java
// 2. 服务端实现
@GrpcService
public class UserGrpcService extends UserServiceGrpc.UserServiceImplBase {
@Override
public void getUser(UserRequest request, StreamObserver<UserResponse> responseObserver) {
User user = userRepository.findById(request.getUserId());
UserResponse response = UserResponse.newBuilder()
.setUserId(user.getId())
.setName(user.getName())
.setEmail(user.getEmail())
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
// 3. 客户端调用
@Service
public class OrderService {
@GrpcClient("user-service")
private UserServiceGrpc.UserServiceBlockingStub userStub;
public UserDTO getUserInfo(Long userId) {
UserRequest request = UserRequest.newBuilder()
.setUserId(userId)
.build();
UserResponse response = userStub.getUser(request);
return convertToDTO(response);
}
}
2. 异步通信方式
2.1 消息队列(Message Queue)
java
// 使用 RabbitMQ 进行异步通信
@Component
public class OrderEventPublisher {
@Autowired
private RabbitTemplate rabbitTemplate;
// 发布订单创建事件
public void publishOrderCreated(Order order) {
OrderCreatedEvent event = new OrderCreatedEvent(
order.getId(),
order.getUserId(),
order.getTotalAmount()
);
rabbitTemplate.convertAndSend(
"order.exchange",
"order.created",
event
);
}
}
// 其他服务监听事件
@Component
public class NotificationEventListener {
@RabbitListener(queues = "order.created.queue")
public void handleOrderCreated(OrderCreatedEvent event) {
// 发送通知
notificationService.sendOrderConfirmation(event.getUserId(), event.getOrderId());
}
}
@Component
public class InventoryEventListener {
@RabbitListener(queues = "order.created.queue")
public void handleOrderCreated(OrderCreatedEvent event) {
// 扣减库存
inventoryService.deductStock(event.getOrderId());
}
}
2.2 事件驱动架构(Event-Driven)
java
// 使用 Spring Cloud Stream (基于 Kafka)
// 1. 定义事件
public class OrderCreatedEvent {
private Long orderId;
private Long userId;
private BigDecimal amount;
private LocalDateTime createdAt;
}
// 2. 事件生产者
@Service
public class OrderService {
@Autowired
private StreamBridge streamBridge;
@Transactional
public Order createOrder(Order order) {
order = orderRepository.save(order);
// 发布领域事件
OrderCreatedEvent event = new OrderCreatedEvent(
order.getId(), order.getUserId(), order.getTotalAmount()
);
streamBridge.send("orderCreated-out-0", event);
return order;
}
}
// 3. 事件消费者
@Component
public class OrderEventProcessor {
@Bean
public Consumer<OrderCreatedEvent> orderCreated() {
return event -> {
// 处理订单创建事件
inventoryService.updateStock(event);
notificationService.sendConfirmation(event);
analyticsService.trackOrder(event);
};
}
}
3. 通信模式对比
3.1 同步 vs 异步
特性 |同步通信 |异步通信
响应 |立即响应 |延迟响应
耦合度 |紧耦合 |松耦合
性能 |请求阻塞 |非阻塞
复杂性 |简单 |复杂
数据一致性 |强一致性 |最终一致性
3.2 通信协议选择
场景 |推荐协议 |优点
内部服务调用 |gRPC |高性能、代码生成
对外API |REST |通用、易调试
事件通知 |消息队列 |解耦、削峰填谷
实时数据 |WebSocket |双向通信、低延迟
4. 服务发现与负载均衡
4.1 服务注册与发现
#vim application.yaml
# application.yml
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
java
// 服务自动注册到Nacos
@SpringBootApplication
@EnableDiscoveryClient // 启用服务发现
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
// 服务调用时自动发现
@Service
public class OrderService {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
@LoadBalanced // 开启客户端负载均衡
private RestTemplate restTemplate;
public void serviceDiscoveryExample() {
// 手动服务发现
List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
// 自动负载均衡调用
UserDTO user = restTemplate.getForObject(
"http://user-service/api/users/1", // 使用服务名而不是IP
UserDTO.class
);
}
}
5. 通信的容错处理
5.1 熔断器模式(Circuit Breaker)
java
// 使用 Resilience4j 实现熔断
@Service
public class UserServiceClient {
@CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback")
@RateLimiter(name = "userService")
@Retry(name = "userService", fallbackMethod = "getUserFallback")
public UserDTO getUserById(Long userId) {
return userServiceClient.getUserById(userId);
}
// 降级方法
public UserDTO getUserFallback(Long userId, Exception e) {
// 返回默认用户或缓存数据
return new UserDTO(userId, "默认用户", "default@example.com");
}
}
5.2 超时与重试配置
#vim application.yaml
# application.yml
resilience4j:
circuitbreaker:
instances:
userService:
failure-rate-threshold: 50
wait-duration-in-open-state: 10s
permitted-number-of-calls-in-half-open-state: 3
sliding-window-size: 10
retry:
instances:
userService:
max-attempts: 3
wait-duration: 2s
# Feign客户端配置
feign:
client:
config:
default:
connect-timeout: 5000
read-timeout: 10000
logger-level: basic
6. 实际架构示例
6.1 电商订单处理流程
java
// 订单创建的整体通信流程
@Service
@Transactional
public class OrderService {
@Autowired
private UserServiceClient userService;
@Autowired
private ProductServiceClient productService;
@Autowired
private InventoryServiceClient inventoryService;
@Autowired
private OrderEventPublisher eventPublisher;
public Order createOrder(OrderCreateRequest request) {
// 1. 同步调用:验证用户
UserDTO user = userService.getUserById(request.getUserId());
// 2. 同步调用:验证商品和库存
ProductDTO product = productService.getProduct(request.getProductId());
inventoryService.checkStock(request.getProductId(), request.getQuantity());
// 3. 创建订单(本地事务)
Order order = buildOrder(request, user, product);
order = orderRepository.save(order);
// 4. 异步事件:扣减库存(最终一致性)
eventPublisher.publishInventoryDeductEvent(
new InventoryDeductEvent(order.getId(), request.getProductId(), request.getQuantity())
);
// 5. 异步事件:发送通知
eventPublisher.publishOrderCreatedEvent(
new OrderCreatedEvent(order.getId(), user.getId(), order.getTotalAmount())
);
return order;
}
}
6.2 通信架构图
text
┌─────────────┐ REST/gRPC ┌─────────────┐
│ 订单服务 │─────────────────▶│ 用户服务 │
│ Order │ │ User │
│ Service │ │ Service │
└─────────────┘ └─────────────┘
│ │
│ Message Queue │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 消息队列 │ │ 商品服务 │
│ RabbitMQ/ │◀────────────────│ Product │
│ Kafka │ │ Service │
└─────────────┘ └─────────────┘
│
│ 异步事件
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 库存服务 │ │ 通知服务 │ │ 分析服务 │
│ Inventory │ │ Notification│ │ Analytics │
│ Service │ │ Service │ │ Service │
└─────────────┘ └─────────────┘ └─────────────┘
7. 最佳实践
7.1 通信设计原则
java
// ✅ 好的实践:面向接口编程
public interface UserService {
UserDTO getUserById(Long userId);
UserDTO createUser(UserDTO user);
}
// ✅ 好的实践:使用DTO进行数据传输
public class UserDTO {
private Long id;
private String name;
private String email;
// 不要暴露内部实体类的敏感字段
}
// ❌ 避免:直接传递实体类
public class User { // JPA实体
private Long id;
private String password; // 敏感信息!
private String salt;
// ...
}
7.2 错误处理策略
java
// 统一的错误响应
public class ApiResponse<T> {
private boolean success;
private String code;
private String message;
private T data;
private Long timestamp;
}
// 全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(FeignException.class)
public ResponseEntity<ApiResponse<?>> handleFeignException(FeignException e) {
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.body(ApiResponse.error("SERVICE_UNAVAILABLE", "依赖服务暂时不可用"));
}
}
8. 性能优化
8.1 连接池配置
yaml
# HTTP连接池配置
feign:
httpclient:
enabled: true
max-connections: 200
max-connections-per-route: 50
# gRPC配置
grpc:
client:
user-service:
address: 'static://localhost:9090'
enable-keep-alive: true
keep-alive-time: 30s
keep-alive-timeout: 5s
8.2 缓存策略
java
@Service
public class UserServiceClient {
@Cacheable(value = "users", key = "#userId")
public UserDTO getUserById(Long userId) {
// 只有缓存未命中时才进行远程调用
return userServiceClient.getUserById(userId);
}
}
总结
微服务通信的核心要点:
同步通信:
RESTful API:通用、易调试
gRPC:高性能、强类型
Feign:声明式、简化开发
异步通信:
消息队列:解耦、削峰填谷
事件驱动:最终一致性、可扩展
关键保障:
服务发现:动态定位服务实例
负载均衡:合理分配请求
容错处理:熔断、降级、重试
监控追踪:全链路可观测
选择建议:
对实时性要求高的业务:使用同步通信
对吞吐量要求高的业务:使用异步通信
核心业务:同步 + 异步混合使用
数据一致性:根据业务容忍度选择强一致性或最终一致性
掌握这些通信方式,就能根据具体业务场景选择最合适的微服务通信方案!
更多推荐



所有评论(0)