# config/shared/mq.yaml —— 消息中间件配置(2026-08-10 起为空配置,保留文件) # # ══ 为什么是空的 ══ # 事件总线已由 RocketMQ 切到 Redis pub/sub,见 config/shared/system-config.yaml 的 # `event.event-publish-type: redis`。切换后: # - `defMsgToptic` / `ssoEventReceiver` 这两个 @Bean 位于 jnpf-common-mq 的 # MqAutoConfiguration$MqExistsdConfiguration,其 @ConditionalOnProperty 要求 # event-publish-type=mq,**redis 档下不再注册**; # - 于是原来的 `spring.cloud.function.definition` 与 `spring.cloud.stream.bindings` # 全部指向不存在的函数。Spring Cloud Stream 4.x 对缺失 Bean 只 WARN 跳过不报错, # 但**留着会让 RocketMQ binder 照样去连 namesrv**(消费者绑定先于函数解析建立), # 在没有 MQ 容器的环境里就是启动期无谓重连 + 日志噪音。故整体清空。 # # ══ 为什么不删这个文件 ══ # 14 个服务的 application.yml 都把它列在 `spring.config.import` 里,且是 # **非 optional 的 `file:`**(补丁 #8 的刻意设计:缺文件启动即失败,防静默半配置)。 # 删文件等于要同时改 14 处 import 列表,收益为零、回滚面变大。保留空文件是最小改动。 # # ══ 要改回 RocketMQ 怎么办 ══ # `git log --oneline -- config/shared/mq.yaml` 找到本次提交,revert 即可拿回完整的 # binder 配置(含 RabbitMQ / Kafka 的原厂注释样例);同时把 system-config.yaml 的 # event-publish-type 改回 mq、并恢复 docker-compose.yml 里的三个 mq 服务。 # # ══ 为什么还要显式写一个空的 function.definition ══ # 光清空 bindings **不够**。jnpf-common-mq 的 MqAutoConfiguration$MqExistsdConfiguration 里 # 三个 @Bean 的条件并不一致(2026-08-10 javap 实查,属 JNPF 上游的不一致): # defMsgToptic @Bean + @ConditionalOnProperty(event-publish-type=mq) ← 受门控 # ProjectEventMQSender @Bean + @ConditionalOnProperty(event-publish-type=mq) ← 受门控 # ssoEventReceiver @Bean + **仅 @ConditionalOnMissingBean** ← 不受门控! # 于是 redis 档下 ssoEventReceiver 这个 Consumer> 照样注册(类级条件只要求 # StreamBridge 在 classpath 上)。而 Spring Cloud Stream 4.x 在 function.definition 未设时 # 会**自动发现**函数式 bean 并为其建立入站绑定 → 去连 name-server(已被清空)→ # 实测每 30s 一次 `DefaultMQPushConsumer init failed ... connect to null failed`。 # 两条走不通的弯路(2026-08-10 都实测踩过,别再试): # ① `definition: ""` —— 空串被当成「未设置」,SCS 照样回退到自动发现。现象很有迷惑性: # cx-audit 干净而 cx-lims/visualdev/system/oauth 每 30s 报错一次,因为 audit 当时有两个 # 函数式 bean(ssoEventReceiver + auditEventReceiver),自动发现遇歧义会放弃; # 其余服务只有 ssoEventReceiver 一个,正好被自动绑上。 # (2026-08-11 起 auditEventReceiver 已随 MQ 消费者一并删除,audit 也只剩 ssoEventReceiver # 一个——**这条豁免不再成立**,autodetect: false 对它同样是必需的,别按上面的现象推断。) # ② `definition: <不存在的函数名>` —— 更糟:SCS **不会**因为函数 bean 不存在就跳过入站绑定, # 而是照样按这个名字建 `<占位名>-in-0` 绑定去连 broker。实测日志里出现 # `errorChannel '….eventBusDisabledPlaceholder-in-0.errors'`,报错照旧。 # (jnpf-audit.yaml 原注释里「缺失 Bean 的项框架 WARN 跳过」在入站绑定场景不成立。) # # 正解是关掉自动发现这件事本身:StreamFunctionProperties.autodetect。 spring: cloud: stream: function: autodetect: false # ⚠️ 审计事件(原 AUDIT_EVENT topic)与本文件已无关系: # 2026-08-11 起 AuditEventPublisher 的第一级 MQ(streamBridge.send("AUDIT_EVENT", …)) # 与服务端消费者 auditEventReceiver 一并移除,降级链现为 **Feign 同步 → 本地 spool 落盘** 两级。 # 移除理由:切 redis 后第一级每次必然失败再由 Feign 接管,它已不是降级级次、只是每条事件 # 多一次异常构造。仍在 audit-sender 守护线程池内执行,不阻塞业务线程。 # 详见 jnpf-biz-common/jnpf-audit-sdk/.../AuditEventPublisher.java。