知其然,知其所以然
Spring 全家桶 2026-10-22

灰度发布:基于请求头的路由

实测 Spring Cloud Gateway 的几种灰度方式:Header 谓词按请求头路由(顺序写反则永不命中);Weight 谓词接近 80/20 但同一用户会在两个版本之间跳;按用户 ID 尾号分桶让同一用户始终同版本;lb:// 需要 loadbalancer starter,weighted 配置下 1000 次请求恰好 800/200;request-based-sticky-session 在网关里没有看到 Set-Cookie。

Spring Cloud Gateway 灰度发布 Header Weight LoadBalancer 真实验证 动画演示
Spring 全家桶 2026-10-22

Spring Cloud Kubernetes:服务发现与 ConfigMap 刷新

在本机 kind 集群上实测 Spring Cloud Kubernetes 5.0.3:应用不在 Kubernetes 上时服务发现和 ConfigMap 都静默不生效,要 spring.main.cloud-platform=kubernetes;getInstances 来自 Endpoints,metadata 带 Service 的标签和注解;副本数变化 1 秒内可见;ConfigMap 要写 spring.config.import=kubernetes:;热加载 reload.enabled=true 还需要 actuator 依赖,否则不生效。

Spring Cloud Kubernetes 服务发现 ConfigMap 配置热加载 真实验证 动画演示
Spring 全家桶 2026-10-22

启动顺序:注册、健康检查与流量进入

实测服务启动顺序:自动注册发生在 Web 服务器启动那一刻,早于 ApplicationRunner 与 readiness;3 秒预热期间 Nacos 里已有实例,调用方 121 次请求被 503;register-enabled=false 加手工注册、auto-registration.enabled=false、instance-enabled=false 加 setStatus 三条路在我的环境里都没走通;把预热放进 phase 0 的 SmartLifecycle 后调用方 0 次失败。

Spring Cloud 启动顺序 服务注册 预热 readiness Nacos 真实验证 动画演示
Spring 全家桶 2026-10-22

Dubbo 对比:RPC 与 HTTP 的差别

实测 Apache Dubbo 3.3.6 与 HTTP/1.1 的差别:小请求上 dubbo 协议的请求(334 字节)比 HTTP(191 字节)还大,载荷变大后比 JSON 小约 29%;8 线程吞吐 33826 对 19332 次/秒;50 个并发线程 dubbo 与 tri 只用 1 个 TCP 连接而 HTTP/1.1 用 50 个;dubbo 默认超时重试使服务端执行 3 次。

Spring Cloud Dubbo RPC HTTP 序列化 真实验证 动画演示
Spring 全家桶 2026-10-22

超时叠加:Feign、Gateway 与下游各自的超时怎么叠

实测 Gateway → Feign → 下游的超时叠加:外层 Gateway 3 秒先超时,客户端拿 504 但下游照样跑完;内层 Feign 2 秒先超时,客户端拿到 500 而不是 504;Feign 重试 5 次让 A 在客户端收到 504 之后还发出第 5 次请求;Gateway Retry 与 Feign 叠加使下游被调用 3 次、客户端等 6.3 秒。

Spring Cloud 超时 重试 Gateway OpenFeign 真实验证 动画演示
Spring 全家桶 2026-10-22

服务间认证:令牌透传

实测 Spring Cloud Gateway 的 TokenRelay:网关登录成功但路由不带令牌时下游资源服务器返回 401;加 TokenRelay 过滤器后同一个 access_token(jti 不变)被原样透传;下游默认不校验受众(aud=gw 的令牌也被接受);第二跳(A 调 B)要自己转发 Authorization 头;令牌快过期时 TokenRelay 自动刷新。

Spring Cloud Gateway TokenRelay OAuth2 JWT 令牌透传 真实验证 动画演示
Spring 全家桶 2026-10-22

Spring AMQP:监听容器并发、预取与确认模式

实测 Spring AMQP 监听容器:concurrency 决定消费者线程数,max-concurrency 在短突发里来不及扩容;默认 prefetch 250 在处理时间不均匀时让 5 条慢消息全落在一个消费者上(5.0 秒对 3.1 秒);默认 default-requeue-rejected=true 让 poison 消息 3 秒被投递 37670 次;kill -9 时 AUTO 与 MANUAL 不丢消息,NONE 丢 4 条。

Spring AMQP RabbitMQ 监听容器 并发 预取 确认模式 真实验证 动画演示
Spring 全家桶 2026-10-22

Spring AMQP 的重试与死信

实测 Spring AMQP 的重试与死信:监听重试是在消费者线程里原地进行(0.5、1.0、2.0 秒间隔),重试用完没有死信配置就丢弃;Spring Boot 4 里 max-attempts 被悄悄忽略,要改用 max-retries(总调用次数 = max-retries + 1);配死信后消息带 x-death 头进入死信队列;同步重试堵住队列 7 秒;TTL 等待队列方案不阻塞;消息转换失败不重试直接进死信。

Spring AMQP RabbitMQ 重试 死信队列 延迟队列 真实验证 动画演示
Spring 全家桶 2026-10-22

Spring Kafka:监听容器与 offset 提交方式

实测 Spring Kafka 4.0.7 的偏移量提交:BATCH 整批处理完才提交,RECORD 与 MANUAL_IMMEDIATE 每条提交,MANUAL 的 ack 只是登记要等批结束才提交,忘了 ack 则一个偏移量都不提交;kill -9 后 BATCH/MANUAL 重复处理 4 条,RECORD/MANUAL_IMMEDIATE 只重复 1 条;concurrency 超过分区数时多出来的线程闲着。

Spring Kafka 监听容器 offset提交 AckMode 并发 真实验证 动画演示
Spring 全家桶 2026-10-22

Spring Kafka 的错误处理:DefaultErrorHandler 与 DLT

实测 Spring Kafka 4.0.7 的错误处理:默认 DefaultErrorHandler 共投递 10 次(间隔约 0.5 秒)后直接丢弃消息;DeadLetterPublishingRecoverer 的默认死信 topic 是原 topic 加 -dlt;不可重试异常只投递 1 次;值反序列化器直接抛异常会把分区卡死、日志 6 秒写 3.9 GB;ErrorHandlingDeserializer 要配合 ByteArraySerializer 才能发死信;@RetryableTopic 需要 TaskScheduler,不阻塞主 topic。

Spring Kafka 错误处理 DefaultErrorHandler 死信 RetryableTopic 真实验证 动画演示
Spring 全家桶 2026-10-22

@TransactionalEventListener 做 outbox

实测 @TransactionalEventListener:普通 @EventListener 在回滚时副作用已经发生,AFTER_COMMIT 只在提交后执行;没有事务时被静默忽略(除非 fallbackExecution=true);AFTER_COMMIT 里发送失败订单已提交而消息丢失且调用方无感;AFTER_COMMIT 里写库的 REQUIRES_NEW 问题;事务性发件箱在 broker 不可用时不丢消息,relay 崩溃时会重复。

Spring TransactionalEventListener outbox 事务 事件 真实验证 动画演示
Spring 全家桶 2026-10-22

Spring Session:把 Session 放进 Redis

实测 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 Session Redis 会话共享 序列化 过期 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号