docs: 去重默认开启口径落文档 + 异构发送方对接契约 + tag 用法教学
README:idempotent 默认 true 全文对齐(快速开始加 spring.redis、能力表、注解属性表、 troubleshooting 加「只有第一条能消费」条目);新增「Redis Stream 消息结构」一节 (五字段信封、enc=plain/gzip、key 逐条唯一契约、rocketmq 端 KEYS 属性补注); 新增 tag 小节(broker 过滤 vs redis-stream 全收)。 CLAUDE.md:装配链路第 2 条改为「默认调用 store、Redis 不可达在消费期暴露」口径。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -46,7 +46,7 @@ mq-spring-boot-starter 聚合 jar,业务方只引这一个(恒含 idemp
|
||||
各模块 `META-INF/spring.factories` 注册 AutoConfiguration。装配开关是**唯一的** `mq.type`:
|
||||
|
||||
1. **driver 二选一**:`RedisStreamMqDriverAutoConfiguration` / `RocketMqDriverAutoConfiguration` 都用 `@ConditionalOnProperty(name="mq.type", havingValue=...)` 按 `mq.type` 条件装配,各自产出一个 `MqDriver` bean。没配 `mq.type` 则两个都不装,`MqTemplate`/`@MqListener` 全部不生效。
|
||||
2. **去重 store 不按 mq.type 门控**:`MqIdempotentRedisAutoConfiguration`(idempotent-redis 模块)只按 Redis 在场门控(`@ConditionalOnClass/OnBean(StringRedisTemplate)` + `@AutoConfigureAfter(RedisAutoConfiguration)`),这是 rocketmq 部署也能用上去重的关键。注意 classpath 有 lettuce 时 Spring Boot 会用 localhost 默认值自动造 `StringRedisTemplate`,所以该条件几乎恒真——真正的启动安全网是**懒连接 + core 仅在 `idempotent=true` 时才调用 store**(该装配与 store 构造都刻意不 PING Redis,与下述 fail-fast 探测相反)。逃生开关 `mq.idempotent.enabled=false`。
|
||||
2. **去重 store 不按 mq.type 门控**:`MqIdempotentRedisAutoConfiguration`(idempotent-redis 模块)只按 Redis 在场门控(`@ConditionalOnClass/OnBean(StringRedisTemplate)` + `@AutoConfigureAfter(RedisAutoConfiguration)`),这是 rocketmq 部署也能用上去重的关键。注意 classpath 有 lettuce 时 Spring Boot 会用 localhost 默认值自动造 `StringRedisTemplate`,所以该条件几乎恒真——真正的启动安全网只剩**懒连接**(该装配与 store 构造都刻意不 PING Redis,与下述 fail-fast 探测相反)——`@MqListener` 的 `idempotent` 自 2026-07-14 起**默认 `true`**,消费链默认就会调用 store,Redis 不可达在消费期(而非启动期)以连接异常暴露。逃生开关 `mq.idempotent.enabled=false`(关掉后去重不生效、启动仅打 WARN)。
|
||||
3. **core 依赖 driver**:`MqCoreAutoConfiguration` 里 `MqTemplate` 和 `MqListenerRegistry` 都是 `@ConditionalOnBean(MqDriver.class)` —— 有 driver 才有门面。driver 与 idempotent-redis 的 AutoConfiguration 都用 `@AutoConfigureBefore(MqCoreAutoConfiguration.class)` 保证自己先装。
|
||||
4. **注解扫描**:`MqListenerAnnotationBeanPostProcessor`(一个 `BeanPostProcessor`)扫描所有 bean 的方法,把 `@MqListener` 方法收集成 `MqListenerEndpoint` 列表。
|
||||
5. **启动订阅**:`MqListenerRegistry` 实现 `SmartLifecycle`(`phase = Integer.MAX_VALUE - 100`,最后启动),在 `start()` 里为每个 endpoint 组装 `MqConsumeDispatcher`,包成 `MqSubscription` 交给 `driver.subscribe()`。
|
||||
|
||||
Reference in New Issue
Block a user