实测 Spring Kafka 4.0.7 的偏移量提交:BATCH 整批处理完才提交,RECORD 与 MANUAL_IMMEDIATE 每条提交,MANUAL 的 ack 只是登记要等批结束才提交,忘了 ack 则一个偏移量都不提交;kill -9 后 BATCH/MANUAL 重复处理 4 条,RECORD/MANUAL_IMMEDIATE 只重复 1 条;concurrency 超过分区数时多出来的线程闲着。
实测 Spring Kafka 4.0.7 的错误处理:默认 DefaultErrorHandler 共投递 10 次(间隔约 0.5 秒)后直接丢弃消息;DeadLetterPublishingRecoverer 的默认死信 topic 是原 topic 加 -dlt;不可重试异常只投递 1 次;值反序列化器直接抛异常会把分区卡死、日志 6 秒写 3.9 GB;ErrorHandlingDeserializer 要配合 ByteArraySerializer 才能发死信;@RetryableTopic 需要 TaskScheduler,不阻塞主 topic。
实测 @TransactionalEventListener:普通 @EventListener 在回滚时副作用已经发生,AFTER_COMMIT 只在提交后执行;没有事务时被静默忽略(除非 fallbackExecution=true);AFTER_COMMIT 里发送失败订单已提交而消息丢失且调用方无感;AFTER_COMMIT 里写库的 REQUIRES_NEW 问题;事务性发件箱在 broker 不可用时不丢消息,relay 崩溃时会重复。
实测 Spring Session 4.0.5(Redis):默认仓库只有一个 hash,TTL 等于超时时间;cookie 名是 SESSION;值是 Java 序列化;Boot 4 的属性前缀是 spring.session.data.redis,老的 spring.session.redis 静默失效;spring.session.timeout 优先于 server.servlet.session.timeout;不可序列化的属性在请求结束时才 500;带 cookie 的请求每次固定 6 条 Redis 命令,即使不碰会话也续期。
实测 Spring Batch 6.0.5:Boot 启动时自动运行 Job,无参数的 Job 第二次启动因 JobInstanceAlreadyCompleteException 而启动失败;chunk=1 提交 5000 次耗时 2247 ms,chunk=100 提交 50 次 169 ms;处理器返回 null 即过滤;写第 250 条失败只回滚当前 chunk,已提交的 200 条保留;同参数的 Job 不能重复运行。
实测 Spring Batch 6.0.5 的容错:默认任何异常让步骤失败并回滚当前 chunk;processor 异常用 skip 就地跳过;超出 skipLimit 当前 chunk 整块回滚;writer 失败会回滚后逐条重写(writer 调用 13 次);retryLimit(n) 总尝试 n+1 次;重启时不可重启的读取器从头读,表里多出 200 行重复,而 JdbcCursorItemReader 从第 201 条继续。
实测多实例下的 @Scheduled 与 ShedLock 7.10.1(MySQL 锁表):不加锁两个实例 10 秒合计执行 18 次;加 @SchedulerLock 后同一时刻只有一个实例执行,最短间隔受 lockAtLeastFor 限制;任务比 lockAtMostFor 久时出现并发重叠;持有锁的实例被 kill -9 后另一个实例要等约 lockAtMostFor 才恢复;locked_by 默认是主机名。
实测 Spring Integration 7.0.6 的消息通道与端点:DirectChannel 轮询分发并在发送线程执行,默认 failover;PublishSubscribeChannel 默认一个订阅者失败后面的收不到;QueueChannel 的吞吐受 poller 间隔限制(6 条 1566 ms 对 30 ms);异步通道里的异常只出现在 errorChannel;@MessagingGateway 的 replyTimeout 在同步通道上不起作用;IntegrationFlow DSL 的 filter / transform / route。
实测 Spring Boot 4 的 spring.config.import 与配置文件加载顺序:location 是替换、additional-location 是追加;被导入的文件覆盖声明它的文件,多个 import 后面的赢;configtree 只有在内容里仅一个换行时才去掉末尾换行;默认位置分 classpath 与 file 两组,同组内 profile 专属文件整体高于普通文件,file 整组高于 classpath 整组。
实测 Spring Boot 4 的 @ConfigurationProperties:宽松绑定接受的写法(环境变量多一个下划线就绑定不上);列表被高优先级来源整体替换而 Map 合并;Duration、DataSize、boolean、枚举的转换规则;嵌套对象要加 @Valid 才校验,没有 hibernate-validator 时 @Validated 悄悄失效;只有 getter 的字段配了值会启动失败;record 的嵌套对象与集合缺失时是 null;绑定只发生一次。
实测 Spring Boot 4 的 profile:激活方式(命令行 > 系统属性 > 环境变量 > 配置文件)与 include、additionalProfiles、default 的行为;9 种 @Profile 写法的逐个对照(数组是「或」,带逗号的不是,名称区分大小写,混用 & 和 | 要加括号);profile 组的展开顺序;多个 profile 里后写的赢;写在 @PropertySource 里的 spring.profiles.active 读得到却不激活。
实测 SpringApplication.run 的启动阶段:Starting、EnvironmentPrepared、ContextInitialized、Prepared、ContextRefreshed、Started、runner、Ready 的顺序与每一步时 Bean 定义数;@Component 监听器收不到前四个事件;runner 抛异常和 Bean 初始化失败时的事件与退出码;内嵌 Tomcat 的端口在 runner 之前就开了,慢 runner 期间 readiness 是 REFUSING_TRAFFIC。