Spring Boot 项目集成模块- 2

第一部分: 负载均衡

spring-cloud-starter-loadbalancer 是 Spring Cloud 提供的客户端负载均衡器,用于在微服务架构中自动选择合适的服务实例进行调用。

🎯 作用与优势

  • 客户端负载均衡:在服务消费者端进行负载均衡决策
  • 内置健康检查:自动剔除不健康的服务实例
  • 多种负载均衡策略:轮询、随机、权重等
  • 与 OpenFeign 集成:无缝配合声明式 HTTP 客户端

✅ 整合步骤

1️⃣ 添加依赖(Maven)

xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

<!-- 通常与以下组件配合使用 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<!-- 服务发现(如 Nacos、Eureka) -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2️⃣ 启用负载均衡

在启动类上添加注解:

java 复制代码
@SpringBootApplication
@EnableDiscoveryClient  // 服务发现
@EnableFeignClients     // Feign 客户端(可选)
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3️⃣ 配置负载均衡策略(可选)

yaml 复制代码
# application.yml
spring:
  cloud:
    loadbalancer:
      # 负载均衡策略
      ribbon:
        enabled: false  # 禁用 Ribbon(Spring Cloud LoadBalancer 替代)
      # 服务名.负载均衡策略
      instances:
        user-service:
          loadbalancer:
            # 可选:ROUND_ROBIN, RANDOM, WEIGHTED_RESPONSE_TIME
            strategy: ROUND_ROBIN

4️⃣ 使用方式

方式一:RestTemplate + @LoadBalanced
java 复制代码
@Configuration
public class LoadBalancerConfig {
    
    @Bean
    @LoadBalanced  // 启用负载均衡
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@Service
public class UserService {
    
    @Autowired
    private RestTemplate restTemplate;
    
    public User getUserById(Long id) {
        // 服务名代替具体IP:PORT
        String url = "http://user-service/api/users/" + id;
        return restTemplate.getForObject(url, User.class);
    }
}
方式二:OpenFeign(推荐)
java 复制代码
@FeignClient(name = "user-service", fallback = UserFallback.class)
public interface UserClient {
    
    @GetMapping("/api/users/{id}")
    User getUserById(@PathVariable("id") Long id);
    
    @PostMapping("/api/users")
    User createUser(@RequestBody User user);
}

// 降级处理(可选)
@Component
public class UserFallback implements UserClient {
    @Override
    public User getUserById(Long id) {
        return new User("default-user", "default@example.com");
    }
}

🔄 负载均衡策略

策略 配置值 说明
轮询 ROUND_ROBIN 默认策略,依次调用
随机 RANDOM 随机选择实例
权重 WEIGHTED_RESPONSE_TIME 基于响应时间的权重

📊 与 Ribbon 的区别

特性 Ribbon Spring Cloud LoadBalancer
维护状态 已停止维护 官方推荐
健康检查 手动配置 自动健康检查
响应式支持 不支持 支持 WebFlux
性能 较重 轻量级

⚠️ 注意事项

  1. 禁用 Ribbon :确保 ribbon.enabled=false 或移除 ribbon 依赖
  2. 服务发现:需要配合服务注册中心(Nacos、Eureka 等)
  3. 健康检查:自动剔除不健康实例,提高系统稳定性

第二部分: 整合缓存

spring-boot-starter-cache 是 Spring Boot 提供的缓存启动器,用于简化缓存功能的集成和使用。

🎯 缓存的作用与优势

  • 性能提升:减少数据库查询,提高响应速度
  • 降低负载:减少重复计算和数据库压力
  • 改善用户体验:快速响应,提升系统性能
  • 支持多种缓存:Redis、Caffeine、EhCache 等

✅ 整合步骤

1️⃣ 添加依赖(Maven)

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<!-- 选择具体的缓存实现 -->
<!-- 示例:使用 Redis 作为缓存 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2️⃣ 启用缓存

在启动类上添加注解:

java 复制代码
@SpringBootApplication
@EnableCaching  // 启用缓存功能
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3️⃣ 配置缓存(可选)

yaml 复制代码
# application.yml
spring:
  cache:
    type: redis  # 缓存类型:simple, redis, caffeine, ehcache2 等
  redis:
    host: localhost
    port: 6379
    password: your-password  # 可选

✅ 缓存注解使用

@Cacheable - 缓存查询结果

java 复制代码
@Service
public class UserService {
    
    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        // 实际查询数据库的逻辑
        System.out.println("查询数据库获取用户: " + id);
        return userRepository.findById(id);
    }
    
    // 复杂的 key 生成
    @Cacheable(value = "users", key = "#user.id + '_' + #user.name")
    public User getUserByObject(User user) {
        return userRepository.findByUser(user);
    }
    
    // 条件缓存
    @Cacheable(value = "users", condition = "#id > 0", unless = "#result == null")
    public User getUserWithCondition(Long id) {
        return userRepository.findById(id);
    }
}

@CachePut - 更新缓存

java 复制代码
@Service
public class UserService {
    
    @CachePut(value = "users", key = "#user.id")
    public User updateUser(User user) {
        // 更新数据库
        User updated = userRepository.save(user);
        return updated;  // 返回值会放入缓存
    }
}

@CacheEvict - 清除缓存

java 复制代码
@Service
public class UserService {
    
    @CacheEvict(value = "users", key = "#id")
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
    
    @CacheEvict(value = "users", allEntries = true)  // 清空整个缓存
    public void clearAllUsers() {
        userRepository.deleteAll();
    }
    
    @CacheEvict(value = "users", key = "#user.id")
    public void updateUser(User user) {
        userRepository.save(user);
    }
}

@Caching - 组合多个缓存操作

java 复制代码
@Service
public class UserService {
    
    @Caching(
        evict = {
            @CacheEvict(value = "users", key = "#user.id"),
            @CacheEvict(value = "userList", allEntries = true)
        },
        put = @CachePut(value = "users", key = "#user.id")
    )
    public User updateAndInvalidate(User user) {
        return userRepository.save(user);
    }
}

🔄 缓存配置详解

缓存类型选择

缓存类型 适用场景 依赖
simple 开发测试 无额外依赖
redis 分布式缓存 spring-boot-starter-data-redis
caffeine 本地高性能缓存 com.github.ben-manes.caffeine:caffeine
ehcache 企业级缓存 org.springframework.boot:spring-boot-starter-cache + EhCache 依赖

Redis 缓存配置示例

java 复制代码
@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1))  // 缓存过期时间
                .serializeKeysWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new GenericJackson2JsonRedisSerializer()));
        
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .build();
    }
}

📊 缓存 Key 生成策略

默认 Key 生成器

java 复制代码
// 自定义 Key 生成器
@Configuration
public class CacheConfig {
    
    @Bean
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object obj : params) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };
    }
}

⚠️ 注意事项

注意事项 说明
序列化问题 使用 Redis 时,缓存对象需要实现 Serializable
缓存穿透 使用布隆过滤器或空值缓存防止
缓存雪崩 设置不同的过期时间,避免同时失效
缓存击穿 使用分布式锁保护热点数据

🧪 使用示例

java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.getUserById(id);  // 自动缓存
    }
    
    @PutMapping
    public User updateUser(@RequestBody User user) {
        return userService.updateUser(user);  // 更新缓存
    }
    
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);  // 清除缓存
    }
}

总结:Spring Boot 的缓存功能通过简单的注解即可实现强大的缓存机制,显著提升系统性能,是现代应用开发的必备功能!

第三部分:分布式事务

spring-boot-starter-jta-atomikos 是 Spring Boot 提供的 JTA(Java Transaction API)分布式事务启动器,使用 Atomikos 作为事务管理器实现,用于处理跨多个数据源的分布式事务。

🎯 分布式事务的必要性

  • 多数据源场景:跨数据库、跨服务的数据一致性
  • 微服务架构:服务间的数据同步需求
  • 数据一致性:ACID 事务特性的保证
  • 容错处理:事务失败时的回滚机制

✅ 整合步骤

1️⃣ 添加依赖(Maven)

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

<!-- 示例:多个数据源 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

2️⃣ 配置多数据源(application.yml

yaml 复制代码
spring:
  jta:
    atomikos:
      # 事务日志配置
      transaction-manager:
        max-timeout: 300000  # 最大超时时间(毫秒)
        default-timeout: 60000  # 默认超时时间(毫秒)
        enable-logging: true
      # 连接池配置
      connectionfactory:
        xa-data-source-class: com.mysql.cj.jdbc.MysqlXADataSource
      datasource:
        # 数据源1
        ds1:
          unique-resource-name: ds1
          xa-data-source-class-name: com.mysql.cj.jdbc.MysqlXADataSource
          xa-properties:
            url: jdbc:mysql://localhost:3306/database1?useSSL=false&serverTimezone=UTC
            user: root
            password: password
          min-pool-size: 5
          max-pool-size: 20
          borrow-connection-timeout: 60
          reap-timeout: 0
          max-idle-time: 60
          maintenance-interval: 60
        # 数据源2
        ds2:
          unique-resource-name: ds2
          xa-data-source-class-name: com.mysql.cj.jdbc.MysqlXADataSource
          xa-properties:
            url: jdbc:mysql://localhost:3306/database2?useSSL=false&serverTimezone=UTC
            user: root
            password: password
          min-pool-size: 5
          max-pool-size: 20
          borrow-connection-timeout: 60
          reap-timeout: 0
          max-idle-time: 60
          maintenance-interval: 60

3️⃣ 配置数据源 Bean

java 复制代码
@Configuration
public class DataSourceConfig {
    
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.ds1")
    public DataSource ds1() {
        return new AtomikosDataSourceBean();
    }
    
    @Bean
    @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.ds2")
    public DataSource ds2() {
        return new AtomikosDataSourceBean();
    }
    
    // JPA 配置
    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactory1(
            @Qualifier("ds1") DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan("com.example.entity.ds1");
        em.setPersistenceUnitName("ds1");
        
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
        em.setJpaProperties(properties);
        
        return em;
    }
    
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory2(
            @Qualifier("ds2") DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan("com.example.entity.ds2");
        em.setPersistenceUnitName("ds2");
        
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
        em.setJpaProperties(properties);
        
        return em;
    }
}

4️⃣ 配置事务管理器

java 复制代码
@Configuration
@EnableJpaRepositories(
    basePackages = "com.example.repository.ds1",
    entityManagerFactoryRef = "entityManagerFactory1",
    transactionManagerRef = "transactionManager1"
)
public class DataSource1Config {
    
    @Bean
    @Primary
    public PlatformTransactionManager transactionManager1(
            @Qualifier("entityManagerFactory1") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

@Configuration
@EnableJpaRepositories(
    basePackages = "com.example.repository.ds2",
    entityManagerFactoryRef = "entityManagerFactory2",
    transactionManagerRef = "transactionManager2"
)
public class DataSource2Config {
    
    @Bean
    public PlatformTransactionManager transactionManager2(
            @Qualifier("entityManagerFactory2") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

✅ 使用分布式事务

Service 层实现跨数据源事务

java 复制代码
@Service
@Transactional  // 全局事务
public class BusinessService {
    
    @Autowired
    private UserRepository1 userRepository1;
    
    @Autowired
    private UserRepository2 orderRepository2;
    
    @Transactional  // 使用默认事务管理器
    public void transferData(User user, Order order) {
        // 在数据源1中保存用户
        userRepository1.save(user);
        
        // 在数据源2中保存订单
        orderRepository2.save(order);
        
        // 如果任何操作失败,整个事务都会回滚
        if (someCondition) {
            throw new RuntimeException("业务逻辑错误,触发回滚");
        }
    }
    
    // 指定特定的事务管理器
    @Transactional(transactionManager = "transactionManager1")
    public void processUser(User user) {
        userRepository1.save(user);
    }
}

使用编程式事务管理

java 复制代码
@Service
public class TransactionalService {
    
    @Autowired
    private PlatformTransactionManager transactionManager;
    
    public void executeInTransaction() {
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);
        
        try {
            // 业务逻辑
            userRepository1.save(user);
            orderRepository2.save(order);
            
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
}

🔄 Atomikos 配置详解

事务日志配置

yaml 复制代码
spring:
  jta:
    atomikos:
      # 事务日志配置
      properties:
        com.atomikos.icatch.service: com.atomikos.icatch.standalone.UserTransactionServiceFactory
        com.atomikos.icatch.max-timeout: 300000
        com.atomikos.icatch.default-jta-timeout: 60000
        # 事务日志位置
        com.atomikos.icatch.log-base-dir: /tmp/atomikos
        com.atomikos.icatch.log-base-name: tmlog

📊 分布式事务类型

事务类型 适用场景 性能
2PC(两阶段提交) 强一致性要求 较低
SAGA 长事务,最终一致性 中等
TCC 高性能要求 较高

⚠️ 注意事项

注意事项 说明
XA 数据源 必须使用 XA 兼容的数据源
性能影响 分布式事务会影响系统性能
事务超时 设置合理的超时时间
日志管理 定期清理事务日志
异常处理 妥善处理事务回滚逻辑

🧪 完整示例

java 复制代码
@RestController
@RequestMapping("/api/transfer")
public class TransferController {
    
    @Autowired
    private BusinessService businessService;
    
    @PostMapping
    public ResponseEntity<String> transfer(@RequestBody TransferRequest request) {
        try {
            User user = new User(request.getUserName());
            Order order = new Order(request.getOrderAmount());
            
            businessService.transferData(user, order);
            
            return ResponseEntity.ok("转账成功");
        } catch (Exception e) {
            return ResponseEntity.status(500).body("转账失败: " + e.getMessage());
        }
    }
}

总结spring-boot-starter-jta-atomikos 提供了完整的分布式事务解决方案,适用于需要跨多个数据源保证数据一致性的场景,但需要权衡性能和一致性要求!

第四部分: Spring Boot 集成 RabbitMQ

RabbitMQ 是一个开源的消息代理和队列服务器,用于在分布式系统中存储和转发消息。Spring Boot 通过 spring-boot-starter-amqp 提供了对 RabbitMQ 的集成支持。


✅ 1. 添加依赖

Maven (pom.xml)

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

Gradle (build.gradle)

groovy 复制代码
implementation 'org.springframework.boot:spring-boot-starter-amqp'

✅ 2. 配置 RabbitMQ 连接

application.yml

yaml 复制代码
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    # 连接池配置
    connection-timeout: 15000
    # 发送确认配置
    publisher-confirm-type: correlated  # 启用发布确认
    publisher-returns: true             # 启用发布返回
    template:
      mandatory: true
    listener:
      simple:
        acknowledge-mode: manual        # 手动确认模式
        concurrency: 5                  # 最小消费者数量
        max-concurrency: 10             # 最大消费者数量
        prefetch: 1                     # 每次预取消息数量

✅ 3. 配置交换机、队列和绑定

java 复制代码
@Configuration
public class RabbitMQConfig {

    // 队列
    @Bean
    public Queue myQueue() {
        return QueueBuilder.durable("my.queue")  // 持久化队列
            .withArgument("x-message-ttl", 60000) // 消息过期时间
            .build();
    }

    // 交换机
    @Bean
    public DirectExchange directExchange() {
        return ExchangeBuilder.directExchange("my.direct.exchange")
            .durable(true)
            .build();
    }

    // 绑定
    @Bean
    public Binding binding() {
        return BindingBuilder.bind(myQueue())
            .to(directExchange())
            .with("routing.key");  // 路由键
    }

    // 死信队列配置示例
    @Bean
    public Queue deadLetterQueue() {
        return QueueBuilder.durable("dead.letter.queue").build();
    }

    @Bean
    public TopicExchange topicExchange() {
        return ExchangeBuilder.topicExchange("dlx.exchange").build();
    }

    @Bean
    public Binding dlxBinding() {
        return BindingBuilder.bind(deadLetterQueue())
            .to(topicExchange())
            .with("dlx.#");
    }
}

✅ 4. 发送消息

4.1 使用 RabbitTemplate 发送

java 复制代码
@Service
public class MessageProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    // 发送简单消息
    public void sendSimpleMessage(String message) {
        rabbitTemplate.convertAndSend("my.queue", message);
    }

    // 发送到交换机
    public void sendMessageToExchange(String routingKey, Object message) {
        rabbitTemplate.convertAndSend("my.direct.exchange", routingKey, message);
    }

    // 发送带属性的消息
    public void sendWithProperties(String message) {
        MessageProperties props = new MessageProperties();
        props.setHeader("custom-header", "value");
        props.setExpiration("60000"); // 1分钟过期
        
        Message msg = MessageBuilder
            .withBody(message.getBytes())
            .andProperties(props)
            .build();
        
        rabbitTemplate.send("my.direct.exchange", "routing.key", msg);
    }

    // 异步发送确认
    public void sendWithConfirm(String message) {
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.println("消息发送成功");
            } else {
                System.out.println("消息发送失败: " + cause);
            }
        });

        rabbitTemplate.convertAndSend("my.queue", message);
    }
}

✅ 5. 接收消息

5.1 使用 @RabbitListener 注解

java 复制代码
@Component
public class MessageConsumer {

    // 监听队列
    @RabbitListener(queues = "my.queue")
    public void handleMessage(String message, Channel channel, @Header Map<String, Object> headers) {
        try {
            System.out.println("收到消息: " + message);
            
            // 手动确认(当 acknowledge-mode: manual 时)
            long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            channel.basicAck(deliveryTag, false);
            
        } catch (Exception e) {
            System.err.println("处理消息失败: " + e.getMessage());
            try {
                // 拒绝消息并重新入队
                channel.basicNack((Long) headers.get(AmqpHeaders.DELIVERY_TAG), false, true);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    // 监听多个队列
    @RabbitListener(queues = {"queue1", "queue2"})
    public void handleMultipleQueues(String message) {
        System.out.println("从多个队列收到消息: " + message);
    }

    // 监听交换机
    @RabbitListener(bindings = @QueueBinding(
        value = @Queue("temp.queue"),
        exchange = @Exchange(value = "temp.exchange", type = ExchangeTypes.TOPIC),
        key = "temp.key"
    ))
    public void handleTopicMessage(String message) {
        System.out.println("Topic 消息: " + message);
    }

    // 接收对象消息
    @RabbitListener(queues = "object.queue")
    public void handleObjectMessage(User user) {
        System.out.println("收到用户对象: " + user.getName());
    }
}

✅ 6. 消息模型示例

6.1 简单队列模式

java 复制代码
// 生产者
public void sendToSimpleQueue(String message) {
    rabbitTemplate.convertAndSend("simple.queue", message);
}

// 消费者
@RabbitListener(queues = "simple.queue")
public void receiveFromSimpleQueue(String message) {
    System.out.println("简单队列收到: " + message);
}

6.2 发布订阅模式(Fanout Exchange)

java 复制代码
// 配置
@Bean
public FanoutExchange fanoutExchange() {
    return new FanoutExchange("fanout.exchange");
}

// 生产者
public void publishToFanout(Object message) {
    rabbitTemplate.convertAndSend("fanout.exchange", "", message);
}

// 消费者(多个队列都会收到相同消息)
@RabbitListener(queues = "fanout.queue1")
public void receiveFromFanout1(String message) {
    System.out.println("队列1收到: " + message);
}

@RabbitListener(queues = "fanout.queue2")
public void receiveFromFanout2(String message) {
    System.out.println("队列2收到: " + message);
}

6.3 路由模式(Direct Exchange)

java 复制代码
// 生产者
public void sendToDirect(String routingKey, String message) {
    rabbitTemplate.convertAndSend("direct.exchange", routingKey, message);
}

// 消费者
@RabbitListener(queues = "error.queue")
public void handleErrorMessages(String message) {
    System.out.println("错误消息: " + message);
}

@RabbitListener(queues = "info.queue")
public void handleInfoMessages(String message) {
    System.out.println("信息消息: " + message);
}

✅ 7. 高级特性

7.1 消息持久化和确认

java 复制代码
@Configuration
public class AdvancedConfig {
    
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        
        // 消息转换器
        template.setMessageConverter(new Jackson2JsonMessageConverter());
        
        // 发送确认回调
        template.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("消息发送成功: {}", correlationData);
            } else {
                log.error("消息发送失败: {}", cause);
            }
        });
        
        // 返回回调
        template.setReturnsCallback(returned -> {
            log.warn("消息被退回: {}", returned.getMessage());
        });
        
        return template;
    }
}

7.2 死信队列

java 复制代码
@Bean
public Queue normalQueue() {
    return QueueBuilder.durable("normal.queue")
        .withArgument("x-dead-letter-exchange", "dlx.exchange")  // 死信交换机
        .withArgument("x-dead-letter-routing-key", "dlx.routing") // 死信路由键
        .withArgument("x-message-ttl", 10000) // 消息10秒过期
        .withArgument("x-max-length", 100)    // 队列最大长度
        .build();
}

✅ 8. 监控和管理

8.1 消息统计

java 复制代码
@Component
public class MessageMonitor {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    // 获取队列消息数量
    public int getMessageCount(String queueName) {
        return rabbitTemplate.execute(channel -> {
            AMQP.Queue.DeclareOk declareOk = channel.queueDeclarePassive(queueName);
            return declareOk.getMessageCount();
        });
    }
}

⚠️ 注意事项

问题 解决方案
消息丢失 启用发布确认、消息持久化、手动确认
重复消费 消费端实现幂等性处理
死循环 设置 TTL、死信队列、重试次数限制
性能问题 合理设置预取数量、并发消费者数量
连接问题 配置连接池、心跳机制

✅ 9. 启动类配置

java 复制代码
@SpringBootApplication
@EnableRabbit  // 启用 RabbitMQ 注解支持
public class RabbitMQApplication {
    public static void main(String[] args) {
        SpringApplication.run(RabbitMQApplication.class, args);
    }
}

总结:Spring Boot 集成 RabbitMQ 提供了完整的异步消息处理能力,支持多种消息模式和高级特性,是构建高可用、高并发系统的理想选择!

相关推荐
方圆想当图灵1 小时前
聊聊我为什么要写一个 MCP Server: Easy Code Reader
后端
落霞的思绪1 小时前
基于Go开发的矢量瓦片服务器——pg_tileserv
开发语言·后端·golang
武子康1 小时前
大数据-177 Elasticsearch 聚合实战:指标聚合 + 桶聚合完整用法与 DSL 解析
大数据·后端·elasticsearch
巴塞罗那的风1 小时前
经典Agent架构实战之反思模型(Reflection)
后端·语言模型·golang
archko1 小时前
用rust写了一个桌面app,就不再想用kmp了
开发语言·后端·rust
华仔啊1 小时前
RabbitMQ 的 6 种工作模式你都掌握了吗?附完整可运行代码
java·后端·rabbitmq
计算机毕设MTU77571 小时前
999+套计算机毕业设计——基于HTML5+CSS的图书馆借阅管理系统的设计与实现(含源码+部署教程+数据库)
数据库·spring boot·课程设计·借阅管理系统·图书馆
星释1 小时前
Rust 练习册 109:深入探索列表关系判断
开发语言·后端·rust
老华带你飞2 小时前
作业管理|基于Java作业管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·后端