Spring Boot消息队列与事件驱动详解

1. 消息队列概述

消息队列是分布式系统中重要的通信机制,通过异步消息传递实现系统解耦、提高可靠性和扩展性。Spring Boot提供了完整的消息队列解决方案。废话不多说,接下来直接手撕代码!满满的干货

1.1 消息队列优势

  • 系统解耦:服务间通过消息通信,降低耦合度
  • 异步处理:提高系统响应速度和吞吐量
  • 削峰填谷:处理突发流量,保护下游系统
  • 可靠性:消息持久化,确保消息不丢失
  • 扩展性:支持水平扩展和负载均衡

1.2 消息队列模式

  • 点对点模式:一对一消息传递
  • 发布订阅模式:一对多消息广播
  • 请求响应模式:同步消息处理
  • 事件驱动模式:基于事件的异步处理

1.3 核心依赖

<dependencies>
    <!-- Spring Boot AMQP -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    
    <!-- Spring Boot Kafka -->
    <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
    </dependency>
    
    <!-- Spring Boot Redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
    <!-- Spring Boot WebSocket -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
</dependencies>

2. RabbitMQ消息队列

2.1 RabbitMQ配置

# application.yml
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    connection-timeout: 15000
    publisher-confirm-type: correlated
    publisher-returns: true
    listener:
      simple:
        acknowledge-mode: manual
        concurrency: 5
        max-concurrency: 10
        prefetch: 1

2.2 消息生产者

package com.example.demo.messaging;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;

@Service
public class MessageProducer {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Autowired
    private MessageConverter messageConverter;
    
    // 发送简单消息
    public void sendMessage(String message) {
        rabbitTemplate.convertAndSend("direct.exchange", "routing.key", message);
    }
    
    // 发送对象消息
    public void sendObjectMessage(Object message) {
        rabbitTemplate.convertAndSend("direct.exchange", "routing.key", message);
    }
    
    // 发送带确认的消息
    public void sendMessageWithConfirm(String message) {
        rabbitTemplate.convertAndSend("direct.exchange", "routing.key", message, msg -> {
            msg.getMessageProperties().setMessageId(UUID.randomUUID().toString());
            return msg;
        });
    }
    
    // 发送延迟消息
    public void sendDelayedMessage(String message, long delay) {
        rabbitTemplate.convertAndSend("delayed.exchange", "routing.key", message, msg -> {
            msg.getMessageProperties().setDelay((int) delay);
            return msg;
        });
    }
    
    // 发送批量消息
    public void sendBatchMessages(List<String> messages) {
        for (String message : messages) {
            rabbitTemplate.convertAndSend("direct.exchange", "routing.key", message);
        }
    }
}

2.3 消息消费者

package com.example.demo.messaging;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
import java.io.IOException;

@Component
public class MessageConsumer {
    
    // 简单消息消费
    @RabbitListener(queues = "simple.queue")
    public void handleSimpleMessage(String message) {
        System.out.println("收到消息: " + message);
    }
    
    // 对象消息消费
    @RabbitListener(queues = "object.queue")
    public void handleObjectMessage(@Payload Object message) {
        System.out.println("收到对象消息: " + message);
    }
    
    // 带确认的消息消费
    @RabbitListener(queues = "confirm.queue")
    public void handleConfirmMessage(@Payload String message, 
                                    @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
                                    Channel channel) throws IOException {
        try {
            System.out.println("处理消息: " + message);
            // 处理业务逻辑
            processMessage(message);
            // 手动确认消息
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            System.err.println("消息处理失败: " + e.getMessage());
            // 拒绝消息并重新入队
            channel.basicNack(deliveryTag, false, true);
        }
    }
    
    // 延迟消息消费
    @RabbitListener(queues = "delayed.queue")
    public void handleDelayedMessage(String message) {
        System.out.println("收到延迟消息: " + message);
    }
    
    private void processMessage(String message) {
        // 实现消息处理逻辑
    }
}

2.4 消息配置

package com.example.demo.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {
    
    // 交换机配置
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange("direct.exchange");
    }
    
    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange("topic.exchange");
    }
    
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange("fanout.exchange");
    }
    
    // 队列配置
    @Bean
    public Queue simpleQueue() {
        return QueueBuilder.durable("simple.queue").build();
    }
    
    @Bean
    public Queue objectQueue() {
        return QueueBuilder.durable("object.queue").build();
    }
    
    @Bean
    public Queue confirmQueue() {
        return QueueBuilder.durable("confirm.queue").build();
    }
    
    @Bean
    public Queue delayedQueue() {
        return QueueBuilder.durable("delayed.queue")
                .withArgument("x-message-ttl", 60000)
                .build();
    }
    
    // 绑定配置
    @Bean
    public Binding simpleBinding() {
        return BindingBuilder.bind(simpleQueue()).to(directExchange()).with("routing.key");
    }
    
    @Bean
    public Binding objectBinding() {
        return BindingBuilder.bind(objectQueue()).to(directExchange()).with("object.routing.key");
    }
    
    @Bean
    public Binding confirmBinding() {
        return BindingBuilder.bind(confirmQueue()).to(directExchange()).with("confirm.routing.key");
    }
    
    // 消息转换器
    @Bean
    public Jackson2JsonMessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    
    // RabbitTemplate配置
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(messageConverter());
        template.setMandatory(true);
        template.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            System.err.println("消息发送失败: " + replyText);
        });
        template.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.println("消息发送成功");
            } else {
                System.err.println("消息发送失败: " + cause);
            }
        });
        return template;
    }
    
    // 监听器容器配置
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(messageConverter());
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        factory.setConcurrentConsumers(5);
        factory.setMaxConcurrentConsumers(10);
        factory.setPrefetchCount(1);
        return factory;
    }
}

3. Kafka消息队列

3.1 Kafka配置

# application.yml
spring:
  kafka:
    bootstrap-servers: localhost:9092
    consumer:
      group-id: my-group
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      enable-auto-commit: false
      max-poll-records: 500
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
      acks: all
      retries: 3
      batch-size: 16384
      linger-ms: 5
      buffer-memory: 33554432

3.2 Kafka生产者

package com.example.demo.kafka;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import java.util.UUID;

@Service
public class KafkaProducer {
    
    @Autowired
    private KafkaTemplate<String, Object> kafkaTemplate;
    
    // 发送简单消息
    public void sendMessage(String topic, String message) {
        kafkaTemplate.send(topic, message);
    }
    
    // 发送带键的消息
    public void sendMessageWithKey(String topic, String key, String message) {
        kafkaTemplate.send(topic, key, message);
    }
    
    // 发送对象消息
    public void sendObjectMessage(String topic, Object message) {
        kafkaTemplate.send(topic, message);
    }
    
    // 发送带回调的消息
    public void sendMessageWithCallback(String topic, String message) {
        ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topic, message);
        
        future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
            @Override
            public void onSuccess(SendResult<String, Object> result) {
                System.out.println("消息发送成功: " + result.getRecordMetadata().offset());
            }
            
            @Override
            public void onFailure(Throwable ex) {
                System.err.println("消息发送失败: " + ex.getMessage());
            }
        });
    }
    
    // 发送批量消息
    public void sendBatchMessages(String topic, List<String> messages) {
        for (String message : messages) {
            kafkaTemplate.send(topic, message);
        }
    }
}

3.3 Kafka消费者

package com.example.demo.kafka;

import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import java.util.List;

@Component
public class KafkaConsumer {
    
    // 简单消息消费
    @KafkaListener(topics = "simple-topic", groupId = "my-group")
    public void handleSimpleMessage(String message) {
        System.out.println("收到消息: " + message);
    }
    
    // 带键的消息消费
    @KafkaListener(topics = "key-topic", groupId = "my-group")
    public void handleMessageWithKey(@Payload String message, 
                                   @Header(KafkaHeaders.RECEIVED_MESSAGE_KEY) String key) {
        System.out.println("收到消息 - Key: " + key + ", Value: " + message);
    }
    
    // 对象消息消费
    @KafkaListener(topics = "object-topic", groupId = "my-group")
    public void handleObjectMessage(@Payload Object message) {
        System.out.println("收到对象消息: " + message);
    }
    
    // 手动确认消息
    @KafkaListener(topics = "manual-topic", groupId = "my-group")
    public void handleManualMessage(@Payload String message, Acknowledgment ack) {
        try {
            System.out.println("处理消息: " + message);
            // 处理业务逻辑
            processMessage(message);
            // 手动确认消息
            ack.acknowledge();
        } catch (Exception e) {
            System.err.println("消息处理失败: " + e.getMessage());
        }
    }
    
    // 批量消息消费
    @KafkaListener(topics = "batch-topic", groupId = "my-group")
    public void handleBatchMessages(@Payload List<String> messages) {
        System.out.println("收到批量消息,数量: " + messages.size());
        for (String message : messages) {
            System.out.println("处理消息: " + message);
        }
    }
    
    private void processMessage(String message) {
        // 实现消息处理逻辑
    }
}

4. 事件驱动架构

4.1 事件定义

package com.example.demo.event;

import java.time.LocalDateTime;
import java.util.UUID;

public abstract class DomainEvent {
    
    private final String eventId;
    private final LocalDateTime occurredOn;
    private final String eventType;
    
    public DomainEvent() {
        this.eventId = UUID.randomUUID().toString();
        this.occurredOn = LocalDateTime.now();
        this.eventType = this.getClass().getSimpleName();
    }
    
    public String getEventId() { return eventId; }
    public LocalDateTime getOccurredOn() { return occurredOn; }
    public String getEventType() { return eventType; }
}

// 用户创建事件
public class UserCreatedEvent extends DomainEvent {
    private final Long userId;
    private final String username;
    private final String email;
    
    public UserCreatedEvent(Long userId, String username, String email) {
        super();
        this.userId = userId;
        this.username = username;
        this.email = email;
    }
    
    public Long getUserId() { return userId; }
    public String getUsername() { return username; }
    public String getEmail() { return email; }
}

// 订单创建事件
public class OrderCreatedEvent extends DomainEvent {
    private final Long orderId;
    private final Long userId;
    private final String orderNumber;
    
    public OrderCreatedEvent(Long orderId, Long userId, String orderNumber) {
        super();
        this.orderId = orderId;
        this.userId = userId;
        this.orderNumber = orderNumber;
    }
    
    public Long getOrderId() { return orderId; }
    public Long getUserId() { return userId; }
    public String getOrderNumber() { return orderNumber; }
}

4.2 事件发布器

package com.example.demo.event;

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
public class DomainEventPublisher {
    
    private final ApplicationEventPublisher eventPublisher;
    
    public DomainEventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }
    
    @Transactional
    public void publishEvent(DomainEvent event) {
        eventPublisher.publishEvent(event);
    }
    
    @Transactional
    public void publishUserCreated(Long userId, String username, String email) {
        UserCreatedEvent event = new UserCreatedEvent(userId, username, email);
        publishEvent(event);
    }
    
    @Transactional
    public void publishOrderCreated(Long orderId, Long userId, String orderNumber) {
        OrderCreatedEvent event = new OrderCreatedEvent(orderId, userId, orderNumber);
        publishEvent(event);
    }
}

4.3 事件处理器

package com.example.demo.event;

import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.concurrent.CompletableFuture;

@Component
public class DomainEventHandler {
    
    // 处理用户创建事件
    @EventListener
    @Async
    public CompletableFuture<Void> handleUserCreated(UserCreatedEvent event) {
        System.out.println("处理用户创建事件: " + event.getUserId());
        
        // 发送欢迎邮件
        sendWelcomeEmail(event.getEmail());
        
        // 初始化用户配置
        initializeUserSettings(event.getUserId());
        
        return CompletableFuture.completedFuture(null);
    }
    
    // 处理订单创建事件
    @EventListener
    @Async
    public CompletableFuture<Void> handleOrderCreated(OrderCreatedEvent event) {
        System.out.println("处理订单创建事件: " + event.getOrderId());
        
        // 发送订单确认邮件
        sendOrderConfirmation(event.getUserId(), event.getOrderNumber());
        
        // 更新库存
        updateInventory(event.getOrderId());
        
        return CompletableFuture.completedFuture(null);
    }
    
    private void sendWelcomeEmail(String email) {
        // 实现欢迎邮件发送
    }
    
    private void initializeUserSettings(Long userId) {
        // 实现用户设置初始化
    }
    
    private void sendOrderConfirmation(Long userId, String orderNumber) {
        // 实现订单确认邮件发送
    }
    
    private void updateInventory(Long orderId) {
        // 实现库存更新
    }
}

5. WebSocket实时通信

5.1 WebSocket配置

package com.example.demo.websocket;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic", "/queue");
        config.setApplicationDestinationPrefixes("/app");
    }
    
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws")
                .setAllowedOriginPatterns("*")
                .withSockJS();
    }
}

5.2 WebSocket控制器

package com.example.demo.websocket;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.beans.factory.annotation.Autowired;
import java.security.Principal;

@Controller
public class WebSocketController {
    
    @Autowired
    private SimpMessagingTemplate messagingTemplate;
    
    // 广播消息
    @MessageMapping("/broadcast")
    @SendTo("/topic/messages")
    public String broadcastMessage(String message) {
        return "广播消息: " + message;
    }
    
    // 点对点消息
    @MessageMapping("/private")
    public void sendPrivateMessage(String message, Principal principal) {
        String username = principal.getName();
        messagingTemplate.convertAndSendToUser(username, "/queue/private", "私有消息: " + message);
    }
    
    // 群组消息
    @MessageMapping("/group")
    public void sendGroupMessage(String message, String groupId) {
        messagingTemplate.convertAndSend("/topic/group/" + groupId, "群组消息: " + message);
    }
}

5.3 WebSocket服务

package com.example.demo.websocket;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class WebSocketService {
    
    @Autowired
    private SimpMessagingTemplate messagingTemplate;
    
    private final Map<String, String> userSessions = new ConcurrentHashMap<>();
    
    // 用户上线
    public void userOnline(String username, String sessionId) {
        userSessions.put(username, sessionId);
        messagingTemplate.convertAndSend("/topic/online", "用户 " + username + " 上线了");
    }
    
    // 用户下线
    public void userOffline(String username) {
        userSessions.remove(username);
        messagingTemplate.convertAndSend("/topic/online", "用户 " + username + " 下线了");
    }
    
    // 发送系统通知
    public void sendSystemNotification(String message) {
        messagingTemplate.convertAndSend("/topic/notification", message);
    }
    
    // 发送用户通知
    public void sendUserNotification(String username, String message) {
        messagingTemplate.convertAndSendToUser(username, "/queue/notification", message);
    }
    
    // 获取在线用户数
    public int getOnlineUserCount() {
        return userSessions.size();
    }
}

6. 消息队列监控

6.1 消息监控

package com.example.demo.monitoring;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.HashMap;

@Service
public class MessageQueueMonitor {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    // 获取队列信息
    public Map<String, Object> getQueueInfo(String queueName) {
        Map<String, Object> info = new HashMap<>();
        
        try {
            // 获取队列消息数
            long messageCount = rabbitTemplate.execute(channel -> {
                return channel.messageCount(queueName);
            });
            
            // 获取消费者数
            long consumerCount = rabbitTemplate.execute(channel -> {
                return channel.consumerCount(queueName);
            });
            
            info.put("queueName", queueName);
            info.put("messageCount", messageCount);
            info.put("consumerCount", consumerCount);
            info.put("status", "healthy");
            
        } catch (Exception e) {
            info.put("queueName", queueName);
            info.put("status", "error");
            info.put("error", e.getMessage());
        }
        
        return info;
    }
    
    // 获取所有队列信息
    public Map<String, Object> getAllQueuesInfo() {
        Map<String, Object> allInfo = new HashMap<>();
        
        String[] queues = {"simple.queue", "object.queue", "confirm.queue"};
        for (String queue : queues) {
            allInfo.put(queue, getQueueInfo(queue));
        }
        
        return allInfo;
    }
}

6.2 消息统计

package com.example.demo.monitoring;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicLong;

@Component
public class MessageStatistics {
    
    private final Counter messageSentCounter;
    private final Counter messageReceivedCounter;
    private final Counter messageErrorCounter;
    private final AtomicLong messageProcessingTime;
    
    @Autowired
    public MessageStatistics(MeterRegistry meterRegistry) {
        this.messageSentCounter = Counter.builder("messages.sent")
                .description("Number of messages sent")
                .register(meterRegistry);
        
        this.messageReceivedCounter = Counter.builder("messages.received")
                .description("Number of messages received")
                .register(meterRegistry);
        
        this.messageErrorCounter = Counter.builder("messages.errors")
                .description("Number of message processing errors")
                .register(meterRegistry);
        
        this.messageProcessingTime = meterRegistry.gauge("messages.processing.time", new AtomicLong(0));
    }
    
    public void incrementSentMessages() {
        messageSentCounter.increment();
    }
    
    public void incrementReceivedMessages() {
        messageReceivedCounter.increment();
    }
    
    public void incrementErrorMessages() {
        messageErrorCounter.increment();
    }
    
    public void recordProcessingTime(long time) {
        messageProcessingTime.set(time);
    }
}

7. 消息队列最佳实践

7.1 消息设计

package com.example.demo.bestpractice;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.HashMap;

public class MessageTemplate {
    
    @JsonProperty("messageId")
    private String messageId;
    
    @JsonProperty("messageType")
    private String messageType;
    
    @JsonProperty("timestamp")
    private LocalDateTime timestamp;
    
    @JsonProperty("payload")
    private Object payload;
    
    @JsonProperty("headers")
    private Map<String, Object> headers;
    
    public MessageTemplate() {
        this.timestamp = LocalDateTime.now();
        this.headers = new HashMap<>();
    }
    
    public MessageTemplate(String messageType, Object payload) {
        this();
        this.messageType = messageType;
        this.payload = payload;
    }
    
    // 添加头部信息
    public MessageTemplate addHeader(String key, Object value) {
        this.headers.put(key, value);
        return this;
    }
    
    // 获取头部信息
    public Object getHeader(String key) {
        return this.headers.get(key);
    }
    
    // getter和setter方法
    public String getMessageId() { return messageId; }
    public void setMessageId(String messageId) { this.messageId = messageId; }
    
    public String getMessageType() { return messageType; }
    public void setMessageType(String messageType) { this.messageType = messageType; }
    
    public LocalDateTime getTimestamp() { return timestamp; }
    public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; }
    
    public Object getPayload() { return payload; }
    public void setPayload(Object payload) { this.payload = payload; }
    
    public Map<String, Object> getHeaders() { return headers; }
    public void setHeaders(Map<String, Object> headers) { this.headers = headers; }
}

7.2 消息处理策略

package com.example.demo.bestpractice;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class MessageProcessingStrategy {
    
    private final AtomicInteger retryCount = new AtomicInteger(0);
    private final int maxRetries = 3;
    
    // 重试策略
    @RabbitListener(queues = "retry.queue")
    public void handleMessageWithRetry(String message) {
        try {
            processMessage(message);
            retryCount.set(0); // 重置重试计数
        } catch (Exception e) {
            int currentRetry = retryCount.incrementAndGet();
            if (currentRetry <= maxRetries) {
                System.out.println("消息处理失败,重试第 " + currentRetry + " 次: " + e.getMessage());
                // 重新发送消息到重试队列
                resendMessage(message);
            } else {
                System.err.println("消息处理失败,已达到最大重试次数: " + e.getMessage());
                // 发送到死信队列
                sendToDeadLetterQueue(message, e);
            }
        }
    }
    
    // 幂等性处理
    @RabbitListener(queues = "idempotent.queue")
    public void handleIdempotentMessage(String message) {
        String messageId = extractMessageId(message);
        
        if (isMessageProcessed(messageId)) {
            System.out.println("消息已处理,跳过: " + messageId);
            return;
        }
        
        try {
            processMessage(message);
            markMessageAsProcessed(messageId);
        } catch (Exception e) {
            System.err.println("消息处理失败: " + e.getMessage());
        }
    }
    
    // 批量处理
    @RabbitListener(queues = "batch.queue", containerFactory = "batchListenerContainerFactory")
    public void handleBatchMessages(List<String> messages) {
        System.out.println("批量处理消息,数量: " + messages.size());
        
        for (String message : messages) {
            try {
                processMessage(message);
            } catch (Exception e) {
                System.err.println("批量消息处理失败: " + e.getMessage());
            }
        }
    }
    
    private void processMessage(String message) {
        // 实现消息处理逻辑
    }
    
    private void resendMessage(String message) {
        // 实现消息重新发送
    }
    
    private void sendToDeadLetterQueue(String message, Exception e) {
        // 实现死信队列发送
    }
    
    private String extractMessageId(String message) {
        // 实现消息ID提取
        return null;
    }
    
    private boolean isMessageProcessed(String messageId) {
        // 实现消息处理状态检查
        return false;
    }
    
    private void markMessageAsProcessed(String messageId) {
        // 实现消息处理状态标记
    }
}

8. 总结

Spring Boot消息队列与事件驱动提供了完整的异步通信解决方案:

  1. 消息队列:RabbitMQ、Kafka等消息中间件
  2. 事件驱动:领域事件、事件发布、事件处理
  3. 实时通信:WebSocket、STOMP协议
  4. 监控运维:消息监控、性能统计、错误处理
  5. 最佳实践:消息设计、处理策略、幂等性、批量处理

通过合理使用这些技术,可以构建出高可用、高性能的分布式系统。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小凯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值