《Spring Boot 实战》18.3 上线、观测与回滚
给出生产级图书借阅服务的上线检查清单、金丝雀蓝绿滚动的适用条件、上线后必看的 RED 指标与业务指标、基于 SLO 的错误预算与燃烧率告警定法,以及代码、配置、特性开关、数据四类回滚的取舍,附向前兼容的数据库迁移写法、发布演练要点与事故复盘模板,最后收束全书。
category
给出生产级图书借阅服务的上线检查清单、金丝雀蓝绿滚动的适用条件、上线后必看的 RED 指标与业务指标、基于 SLO 的错误预算与燃烧率告警定法,以及代码、配置、特性开关、数据四类回滚的取舍,附向前兼容的数据库迁移写法、发布演练要点与事故复盘模板,最后收束全书。
从 Tracer/Span 门面为什么存在讲起,用本机 jar 核实的签名拆解一次 span 的生命周期,说明 ObservationHandler 链如何让一次观察同时产出指标与 span,对比 Brave 与 OpenTelemetry 两种桥接、MDC 日志关联、概率与限速采样的组合,以及 W3C traceparent 与 B3 的报文差异。
把 18.1 的架构决策落成代码:分层骨架与关键接口、跨模块契约与统一错误码、借阅上限的乐观锁加唯一约束兜底、借书事件的可靠投递,并把单元、切片、Testcontainers 集成与契约测试串成四层测试,最后给出本地起依赖到联调前端的可复现步骤。
从 MeterRegistry 注册表与 Meter.Id 的身份语义讲起,对比 Counter、Gauge、Timer、DistributionSummary 的取值差异,拆解 Observation 用低/高基数键值统一指标与追踪,说明 MeterFilter 改名、加标签、限基数的介入点,并落到 Prometheus 导出与 percentiles-histogram 对 P99 的影响。
把生产级图书借阅服务的功能性需求与非功能性需求翻译成一组可评审的架构决策记录(ADR):模块拆分、数据模型、同步与异步边界、缓存策略、多租户隔离方式与技术选型,逐条给出理由、代价与被否决方案,并附模块依赖图、需求追溯表、风险清单与容量预算粗算,作为后两节实现与上线的地基。
本节把结构迁移与数据初始化拆开:Flyway 管表结构,data.sql 管开发数据,并讲清 spring.sql.init.* 与 defer-datasource-initialization 的配合。随后按「公共脚本 + 方言脚本 + profile 覆盖 locations」组织多环境迁移,并说明生产不自动插测试数据、测试环境的迁移取舍,以及迁移该在应用启动时还是流水线独立步骤执行。
对比原生镜像的收益与代价:启动时间、常驻内存、镜像体积的量级与测量方法,构建慢、构建期内存高与无 JIT 导致的吞吐损失,说明哪类服务值得上、哪类不该上,理清与 CDS、AppCDS、Project Leyden 的关系,并给出从 JVM 模式迁移的检查清单与回滚策略。
JVM 参数不是越多越好,生产上真正该调的只有一小撮。本节用本机 JDK 21 实测默认值讲清 -Xms/-Xmx、容器里的 MaxRAMPercentage、OOM 现场转储、G1 的取舍与何时上 ZGC、-Xlog:gc* 统一日志写法、直接内存与线程栈,并给出可复现的查默认值方法。
讲清原生镜像封闭世界假设下反射、资源与动态代理为何失败,逐一核实 RuntimeHints 的五个子 hint、RuntimeHintsRegistrar 与 @RegisterReflectionForBinding 的声明方式,并对照 reflect-config.json 与新版 reachability-metadata.json,附排查命令。
压测做错比不做更危险:它会给出一个被信任的错误容量结论。本节讲清压测目标、场景与数据设计、工具选型、压测机与被测机分离、预热与稳定期、指标采集口径,拆解「连接池与并发不匹配」等假瓶颈,并给出用实测 QPS 乘安全系数倒推实例数的完整方法与示例。
拆开 process-aot 构建期的 AOT 处理:从 ProcessAotMojo 到 SpringApplicationAotProcessor、ApplicationContextAotGenerator 的调用链,讲清 target/spring-aot 下生成的源码与 native-image 配置,以及 AotDetector 如何让启动跳过反射,并给出可核实的扩展点清单。
性能优化最大的浪费是优化了不是瓶颈的地方。本节建立「先测量再优化」的方法论:如何采集吞吐、P95/P99、错误率、GC 与 CPU 基线,用 JFR、async-profiler、jstack 与 EXPLAIN ANALYZE 定位瓶颈,并给出一份症状到下一步的排查表。
本节讲透 Flyway 脚本本身:V{版本}__{描述}.sql 命名规范里那个常被写错的双下划线、整数与时间戳两类版本号怎么选、版本化迁移与 R__ 可重复迁移的适用场景,以及「脚本一旦执行就不能改」背后的 checksum 校验机制与真实报错。针对社区版没有 undo 的现实,给出前滚修复与备份的应对方式,并完整演示 V1 建表、V2 加字段、R__ 建视图。
@EnableMethodSecurity 如何借 AOP 织入方法安全、@PreAuthorize 的表达式求值上下文、与 @Transactional 同时存在时的拦截器顺序,以及 SecurityContext 在 @Async 与虚拟线程里为何丢失,并给出两种补回上下文的方案。
从 Spring Boot 3.4 起支持的结构化日志讲起,核实 logging.structured.format.console/file 的 ecs、gelf、logstash 取值,讲运行时改日志级别的 /actuator/loggers、日志切分与保留、敏感信息脱敏,并论证告警应基于指标而非日志关键字,最后给出日志、指标、追踪的分工表与一条真实排障路径。
沿一次表单登录拆开认证链:ProviderManager 如何按 supports() 挑选 AuthenticationProvider、DaoAuthenticationProvider 的模板方法、SecurityContextHolder 的存储策略、上下文在请求间的保存,以及 AuthorizationManager 取代 AccessDecisionManager 后的授权决策。
讲清 Spring Boot 4.x 的链路追踪栈:为什么 Sleuth 已被 Micrometer Tracing 取代,OTel 与 Brave 桥接包怎么选,management.tracing 的采样率与传播格式如何配置,traceId 如何进入日志 MDC,@Observed 与 Observation API 的用法,以及 HTTP 客户端与 Kafka 的上下文传播。
从 DelegatingFilterProxy 的延迟查找讲到 FilterChainProxy 的匹配:拆开 WebSecurityConfiguration 产出的 springSecurityFilterChain bean、HttpSecurity DSL 如何装配过滤器、FilterOrderRegistration 的排序规则,以及多条 SecurityFilterChain 的选取。
从 Actuator 端点暴露策略讲起,说明生产上为何只暴露必要端点与 env、heapdump 的风险,再拆解 Micrometer 的 MeterRegistry 模型与四类计量器,用 book-loan 演示自定义指标、公共标签、MeterFilter 与 percentiles-histogram,最后给出 Prometheus 抓取配置与开箱指标读法。
本节从 ddl-auto: update 的风险讲起,说明为什么表结构需要版本化迁移;点明 Spring Boot 4.x 的关键变更——Flyway 必须显式引入 spring-boot-starter-flyway。内容涵盖 spring.flyway.* 常用配置、默认脚本位置、首次启动日志与历史表结构,并给出与 Liquibase 的选型对比。