<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>cloud-native on </title>
    <link>/tags/cloud-native/</link>
    <description>Recent content in cloud-native on </description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Sat, 16 May 2026 10:00:00 +0800</lastBuildDate><atom:link href="/tags/cloud-native/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Kubernetes 最佳实践阅读笔记：核心实践与 Gateway API 等新特性补充</title>
      <link>/reading/github/kubernetes-best-practices/</link>
      <pubDate>Sat, 16 May 2026 10:00:00 +0800</pubDate>
      
      <guid>/reading/github/kubernetes-best-practices/</guid>
      <description>原文链接 diegolnasc/kubernetes-best-practices 前言 这份 GitHub 仓库是一份覆盖面相当广的 K8s 实践手册，从集群基础配置、安全、网络到 GitOps 都有涉及，对于想系统梳理 K8s 知识体系的工程师来说很有参考价值。
但该仓库最后更新停留在较早期的内容，遗漏了 K8s 近几个版本中已经稳定（或接近稳定）的重要特性，最典型的就是 Gateway API。本文以仓库内容为骨架，加入我自己的实践理解，同时补充这些新特性，力求给出一份更完整的参考。
一、集群基础：规划要在最前面 网络 CIDR 规划 集群建好之后最难改的就是网络。在创建集群之前必须认真计算三块地址段：
节点子网：根据最大节点数预留，留足余量 Pod CIDR：每个节点 maxPods 数量决定每个节点需要多大的子网块。例如每节点最多 110 个 Pod，则每节点需要 /25（128 个地址），256 个节点就需要 /17 Service CIDR：独立规划，避免与内网路由冲突 对于托管 K8s（GKE/EKS/AKS），云厂商通常会额外保留部分地址，规划时要读清楚文档，留出 1.5~2 倍余量。
私有集群 节点和 API Server 不应暴露在公网。控制面通过私有端点访问，节点出流量经过 NAT 网关。这一点在公有云环境下几乎是标配，但在自建集群（K3s/kubeadm）里容易被忽视。
Infrastructure as Code 所有集群配置（节点池、网络、IAM）都应该用 Terraform / Pulumi 管理，而不是在控制台手点。没有 IaC 的集群，两周后就没人知道某个配置是怎么来的。
二、安全 Pod Security Standards 替代 PSP Pod Security Policy 在 K8s 1.21 被废弃，1.25 彻底移除。现在的替代方案是 Pod Security Admission（PSA），通过 Namespace 标签控制：</description>
    </item>
    
    <item>
      <title>Java 微服务在 K8s 上的运行时基线（2026）：镜像、探针、滚动与可观测</title>
      <link>/posts/java-microservice-k8s-runtime-baseline/</link>
      <pubDate>Thu, 30 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/java-microservice-k8s-runtime-baseline/</guid>
      <description>为什么需要一份&amp;quot;运行时基线&amp;quot; 很多团队在做 Java 微服务上 Kubernetes 时，JVM 调优和业务代码规范写得很细，但介于两者之间的一层——镜像怎么打、探针怎么配、Pod 停机和应用停机怎么对齐、滚动策略怎么跟服务形态匹配——往往散在 Helm chart、Dockerfile 和某个老员工的脑子里。
这篇是对这一层的整理。它不是一份&amp;quot;最佳实践&amp;quot;，更像是一份&amp;quot;基线&amp;quot;：给一份新服务起步时不会出大问题的最小集，再加上一份知道未来要往哪儿收敛的方向。文中会明确区分&amp;quot;当前常见做法&amp;quot;和&amp;quot;推荐改进方向&amp;quot;，方便对号入座。
适用范围：Java 25 + Spring Boot 3.5（Spring MVC） 这条主流栈。Reactive（WebFlux + R2DBC）的运行时模型不在这里讨论。
镜像构建：从能跑到敢跑 一个最小可运行的 Dockerfile 通常长这样：
FROM eclipse-temurin:25-jdk-noble WORKDIR /app COPY ./target/app.jar . EXPOSE 3000 ENTRYPOINT [&amp;#34;java&amp;#34;, &amp;#34;-jar&amp;#34;, &amp;#34;app.jar&amp;#34;] 它能跑，但离&amp;quot;敢长期跑&amp;quot;还差几件事。可以按下面这张表去 review：
关注点 常见现状 推荐方向 Base image temurin:25-jdk-noble 长期看可以切到 *-jre-jammy 或 distroless，缩小攻击面 用户身份 root 启动 Pod 层加 securityContext: runAsNonRoot: true，Dockerfile 里 USER 1000 文件系统 可写根分区 readOnlyRootFilesystem: true，临时写入挂 emptyDir 日志路径 写文件到容器内某个目录 短期保留，长期改 stdout JSON（见后文） 漏洞扫描 没有 在 CI 里加 trivy/grype，至少阻断 high+critical SBOM 没有 syft 生成 SBOM 并归档，方便后续供应链审计 JDK vs JRE 的取舍：开发期镜像用 JDK 方便用 jcmd、jstack、jmap 排障；生产镜像可以换成 JRE 缩小体积。也有团队选择用同一个 JDK 镜像跑遍所有环境，理由是出问题时直接进 Pod 排查更快——这是个权衡，不是非此即彼。</description>
    </item>
    
    <item>
      <title>用 Maven Archetype 管理微服务 Scaffold：为什么我这里暂时没用 Spring Initializr</title>
      <link>/posts/maven-archetype-microservices-scaffold/</link>
      <pubDate>Tue, 21 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/maven-archetype-microservices-scaffold/</guid>
      <description>📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
背景 在 Shop Platform 里，每新增一个服务，开发者要做的第一件事不是写业务代码，而是把平台基线搬进去：父 POM 继承、内部 starter 依赖、application.yml 里的 OpenTelemetry / Spring Boot Actuator / 日志格式、Testcontainers 测试基座、K8s deployment / service / HPA 模板……这些内容对每个服务都是一样的。
如果这些样板靠手抄，结果通常有两种：要么漏掉某一项，要么各个服务的写法开始出现细微差异，最终在 code review 和 ArchUnit 检查时才发现，修复成本往往比一开始就收敛要高。
我们需要一种机制：把平台标准前置到生成阶段，而不是等代码写完再回头治理。 Maven Archetype 是解决这个问题的工具。
为什么不用 Spring Initializr Spring Initializr 的定位是&amp;quot;从零开始创建 Spring Boot 项目&amp;quot;。它解决的是：一个开发者刚接触 Spring Boot，需要一个可以直接跑起来的骨架。对于独立项目或者小型 monolith，它工作得很好。
但是在 Shop Platform 这个场景里，它有结构性的局限：
1. 无法感知内部依赖体系
Spring Initializr 生成的 pom.xml 引用的是 Spring 官方依赖坐标。它不知道我们有 shop-common-core、shop-starter-http-client、shop-starter-kafka 这些内部 starter，也不知道父 POM 是 dev.meirong.shop:shop-platform。要把这些全部接入，要么手工改生成结果，要么自己部署一套 Initializr 服务。</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 下数据库实践记录：HikariCP 调优、N&#43;1 防护、事务管理与 Testcontainers 集成</title>
      <link>/posts/spring-boot-database-best-practices/</link>
      <pubDate>Sun, 12 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/spring-boot-database-best-practices/</guid>
      <description>📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
2026-04 实践更新 当前主线仓库里，MySQL 领域服务的集成测试基线已经基本统一为 @ServiceConnection；少数仍保留 @DynamicPropertySource 的测试，主要是因为除了数据库容器之外还需要额外挂接自定义属性，而不是数据库接线本身没有迁移完成。
在 Shop Platform 的 15 个服务中，11 个领域服务各自拥有独立的 MySQL 8.4 数据库。Spring Boot 3.5 结合 Spring Data JPA 3.5 提供了比较完善的数据库集成能力，但默认配置未必直接适合当前生产环境。需要额外说明的是：当前仓库已经稳定落地的是 ddl-auto: validate、Flyway 迁移、@ServiceConnection 集成测试，以及部分服务显式关闭 OSIV；像 Hikari 数值和 @EntityGraph 更适合作为“可参考实践”，不应直接写成“仓库现状”。
下面从六个维度整理一下 Spring Boot 3.5 下数据库实践里更常遇到的点。
HikariCP 连接池调优 为什么需要调优 Spring Boot 默认的 HikariCP 配置是 maximum-pool-size: 10。这个值适合当起点，但对容器化环境来说，既可能偏小，也可能偏大。
一个更稳妥的压测起点 spring: datasource: hikari: maximum-pool-size: 10 # 先作为压测起点 minimum-idle: 2 # 最小空闲连接 connection-timeout: 5000 # 获取连接超时（ms） idle-timeout: 300000 # 空闲连接超时（5 分钟） max-lifetime: 1200000 # 连接最大生命周期（20 分钟） 怎么确定 maximum-pool-size HikariCP 作者 Brett Wooldridge 的公式：</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 下 Redis 实战记录：从连接池调优到 Bloom Filter 自动配置</title>
      <link>/posts/spring-boot-redis-best-practices/</link>
      <pubDate>Sat, 11 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/spring-boot-redis-best-practices/</guid>
      <description>📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
2026-04 实践更新 当前主线代码已经把 buyer-bff / auth-server / activity-service / api-gateway 的 Redis 访问统一切到 RedissonClient；其中网关限流仍然保留 Lua 原子脚本，但执行器也已经从 StringRedisTemplate 切到 RScript。本文下面的示例已按仓库当前实现同步。
Redis 在 Shop Platform 中承担的角色远不止&amp;quot;缓存&amp;quot;——它是限流的令牌桶状态（Gateway Lua + RScript）、抢红包的原子存储（activity-service Redis List）、反作弊的状态机（Anti-CheatGuard）、幂等检查的 Bloom Filter（shop-starter-idempotency），以及游客购物车的存储（buyer-bff）。
本文从五个维度整理 Spring Boot 3.5 下 Redis 的一些实践记录。
Lettuce 连接池调优 Spring Boot 3.5 默认使用 Lettuce 作为 Redis 客户端。Lettuce 基于 Netty，连接本身是线程安全的；对大多数普通 GET / SET / HSET / EVAL 场景来说，共享连接就已经够用。连接池更适合拿来解决阻塞命令、事务、Pub/Sub 或需要 dedicated connection 的场景，而不是“高并发就一定要开池”。
什么时候才需要连接池 如果你确实要跑阻塞命令、事务，或者要为特定操作准备专用连接，可以再启用连接池：
spring: data: redis: host: ${REDIS_HOST:redis} port: ${REDIS_PORT:6379} lettuce: pool: max-active: 20 # 最大连接数 max-idle: 10 # 最大空闲连接 min-idle: 5 # 最小空闲连接 max-wait: 2000ms # 获取连接最大等待时间 参数 说明 常见起点 max-active 连接池最大连接数 CPU 核心数 × 2 ~ × 4 max-idle 最大空闲连接数 max-active 的 50%-80% min-idle 最小空闲连接数 max-active 的 20%-30% max-wait 获取连接超时 1-3 秒（过长说明连接池不够） 连接池依赖 Spring Boot 不会自动引入连接池，需要手动添加 commons-pool2：</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 下 Kafka 实战记录：从消费者并发模型到序列化选型</title>
      <link>/posts/spring-boot-kafka-best-practices/</link>
      <pubDate>Fri, 10 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/spring-boot-kafka-best-practices/</guid>
      <description>📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
在 Shop Platform 的事件驱动架构中，Apache Kafka 3.9（KRaft 模式）是服务间异步通信的核心基础设施。Spring Boot 3.5 结合 Spring Kafka 3.3 提供了开箱即用的 Kafka 集成，但要把 Kafka 用得稳、用得好，还需要理解底层的并发模型、序列化策略、offset 语义以及错误处理机制。
本文从六个维度整理 Spring Boot 3.5 下 Kafka 的一些实践记录。文中的“现状判断”都以 shop 项目的实际实现为准，额外的代码片段会明确视为建议写法，而不是仓库已经落地的事实。
生产者调优：acks、retries 和 linger.ms acks 配置 acks 决定了生产者需要等待多少个 broker 副本确认后才认为发送成功：
acks 值 含义 可靠性 延迟 acks=0 不等待任何确认 最低（可能丢消息） 最低 acks=1 Leader 确认即可 中（Leader 宕机丢消息） 低 acks=all 所有 ISR 副本确认 最高 高 Kafka 生产者文档里的默认值仍是 acks=1。对于事件驱动架构中承载业务事实的事件（如订单事件、钱包事件），更稳妥的做法仍然是显式写成 acks=all：
spring: kafka: producer: acks: all 参考：Apache Kafka Producer Configs - acks、Confluent: Understanding Kafka acks</description>
    </item>
    
    <item>
      <title>Kubernetes VPA InPlace Resize：原理、实战与避坑</title>
      <link>/posts/kubernetes-vpa-inplace-resize/</link>
      <pubDate>Thu, 09 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/kubernetes-vpa-inplace-resize/</guid>
      <description>背景 如果你在 Kubernetes 里用过 Vertical Pod Autoscaler（VPA），大概率遇到过一个很现实的问题：推荐值有了，但真正生效时，Pod 先被驱逐，再由控制器拉起新实例。
对无状态服务来说，这种做法还能接受。但对数据库、消息队列、长任务、状态服务，甚至一些对尾延迟敏感的 API 服务来说，重建 Pod 本身就是一次明显的扰动。
如果你还没有把 requests / limits、QoS 和 throttling 这些基础概念串起来，可以先看我之前的这篇：Kubernetes CPU 资源管理与 QoS 机制。
Kubernetes 1.35（2025 年 12 月发布）把这个能力补齐了：
In-Place Pod Resize 已经 GA VPA 的 InPlaceOrRecreate 更新模式进入 beta 也就是说，VPA 现在可以优先尝试在原地修改运行中 Pod 的 CPU 和内存资源，而不是直接把 Pod 赶走。
先区分三件事 很多讨论会把 HPA、VPA 和 in-place resize 混在一起，其实它们解决的是三层不同的问题。
能力 调整对象 会不会重建 Pod 典型用途 HPA 副本数 不一定 跟随流量扩缩容 VPA 单个 Pod 的 requests / limits 旧模式通常会 让资源更贴合真实负载 In-Place Resize 运行中 Pod 的资源定义 目标是不重建 降低垂直调容带来的扰动 一句话总结：</description>
    </item>
    
    <item>
      <title>Stripe 支付接入基线：PaymentIntent 抽象、Mock/真实网关切换与后续 Webhook 演进</title>
      <link>/posts/stripe-payment-integration/</link>
      <pubDate>Thu, 09 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/stripe-payment-integration/</guid>
      <description>📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
电商系统接入支付时，第一步通常不是“把所有 webhook 和退款补偿一次做完”，而是先把支付入口、provider 边界和返回模型抽清楚。Shop Platform 当前已经完成的是这条基线：buyer-bff 统一调用 wallet-service，wallet-service 再按支付方式路由到 Stripe / PayPal / Klarna / 内部 Wallet。
更准确地说，当前仓库已经具备：
统一的 WalletApi.PAYMENT_INTENT / PAYMENT_METHODS 合约 PaymentProviderService 里的 provider routing Stripe 真/假网关切换（StripePaymentGateway / MockPaymentGateway） buyer-bff 对 clientSecret / redirectUrl 的透传 但还没有把 Stripe webhook、Stripe Refund API、事件幂等表、Payment Element 前端确认链路真正提交进来。所以这篇文章也应该按“已落地基线 + 明确演进方向”来写，而不是把未来设计写成现状。
当前支付架构 flowchart TD Client[&#34;客户端 / SSR Portal&#34;] BFF[&#34;buyer-bff&#34;] Wallet[&#34;wallet-service&#34;] Provider[&#34;PaymentProviderService&#34;] Stripe[&#34;StripeGateway&#34;] Paypal[&#34;PayPal Orders API&#34;] Klarna[&#34;Klarna Sessions API&#34;] Internal[&#34;WalletApplicationService&#34;] Client --&gt;|&#34;checkout / payment intent&#34;</description>
    </item>
    
    <item>
      <title>电商 Guest-First 购物体验：无需注册也能完整下单</title>
      <link>/posts/shop-guest-first-shopping/</link>
      <pubDate>Wed, 08 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/shop-guest-first-shopping/</guid>
      <description>📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
2026-04 实践更新 当前主线代码里，游客购物车已经从 StringRedisTemplate 统一切到 RedissonClient 的 RBucket&amp;lt;String&amp;gt;，但仍然保留“JSON 可读 + TTL 续期”的设计。下面示例已按当前实现同步。
在电商平台中，注册/登录常常是转化链路里的明显阻力之一。Baymard 长期跟踪 checkout 可用性时，也一直把“被迫注册账号”列为常见流失原因之一。Baymard Institute, Cart Abandonment Rate
Shop Platform 目前已经在 buyer-portal 这条链路上初步支持 Guest-First（游客优先）：用户可以不注册先创建游客订单、保存 order_token 并回查状态。需要补充说明的是，KMP buyer-app 目前仍要求登录后再触发结账，所以这里更接近“逐步 guest-first”，而不是所有前端入口都已经完全等价。
整体流程 flowchart TD Visit[&#34;访问网站&#34;] Browse[&#34;浏览商品&#34;] AddCart[&#34;加入购物车&#34;] Checkout[&#34;结账&#34;] Pay{&#34;支付&#34;} Guest[&#34;auth-server 签发 guest JWT&#34;] RedisCart[&#34;Redis 购物车TTL 48 小时&#34;] GuestOrder[&#34;创建 GUEST 订单带 order_token&#34;] Track[&#34;通过 order_token 追踪订单&#34;] Login[&#34;注册/登录&#34;] Merge[&#34;购物车合并Redis → DB&#34;] SignedIn[&#34;登录态购物车&#34;] Visit --&gt; Browse --&gt; AddCart --&gt; Checkout --&gt; Pay Pay --&gt;|&#34;</description>
    </item>
    
    <item>
      <title>Spring Boot 微服务中的 Feature Toggle 实战：OpenFeature Property Provider &#43; K8s ConfigMap 热更新</title>
      <link>/posts/spring-boot-feature-toggle-openfeature/</link>
      <pubDate>Tue, 07 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/spring-boot-feature-toggle-openfeature/</guid>
      <description>在生产环境中推过新功能的人，几乎都遇到过同一个问题：&amp;ldquo;这个功能怎么在不开完整服务的前提下，先让一小部分人用起来？&amp;rdquo;
Feature Toggle（特性开关）是回答这个问题的一种常见思路。但在 Spring Boot 微服务体系里，怎么实现一套不绑定具体供应商、能随代码一起版本管理、还能在生产环境动态切换的特性开关，仍然是很多团队需要摸索的事情。
本文结合 shop 项目中的 shop-starter-feature-toggle 模块，完整讲一遍从实现到部署的 Feature Toggle 落地路径。
为什么不用 LaunchDarkly / Unleash 直接上手 在开始之前，先明确一个关键问题：为什么不用现成的 SaaS Feature Flag 平台？
LaunchDarkly、Unleash、Split 等确实是成熟的产品，但在实际落地时往往面临几个门槛：
引入外部依赖：需要在生产环境部署或购买 SaaS，增加运维和成本复杂度 供应商锁定：一旦业务代码深度耦合某个平台的 SDK，切换供应商的成本很高 对于 POC 和中小项目来说过度工程化：很多团队只需要&amp;quot;开/关&amp;quot;级别的开关，不需要复杂的受众定位、A/B 测试等功能 OpenFeature 提供了第三条路。
OpenFeature：供应商无关的特性开关标准 OpenFeature 定义了一套供应商无关的特性 flag API。它的架构很简单：
flowchart LR App[&#34;Spring Boot 应用&#34;] SDK[&#34;OpenFeature SDK(供应商无关 API)&#34;] Provider[&#34;Property Provider(从 Spring Config 读取)&#34;] Config[&#34;K8s ConfigMap或 YAML 文件&#34;] App --&gt; SDK SDK --&gt; Provider Provider --&gt; Config 核心原则：
业务代码只依赖 OpenFeature SDK，不依赖任何具体 Provider Provider 可替换：当前用 Spring Property Provider，未来可以换成 Unleash、LaunchDarkly、flagd 等，业务代码改动通常可以控制在较小范围 标准化评估结果：ProviderEvaluation 统一返回 value、variant、reason、errorCode，便于监控和调试 参考：OpenFeature 规范、OpenFeature Concepts、OpenFeature Java SDK</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 &#43; Java 25 &#43; Cloud Native 系列（七）：架构质量Quality Gates</title>
      <link>/posts/shop-platform-architecture-quality-gates/</link>
      <pubDate>Mon, 06 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/shop-platform-architecture-quality-gates/</guid>
      <description>在这个系列的前几篇文章中，我们看了 Shop Platform 的各个技术层面：API Gateway、BFF 聚合、领域服务、事件驱动、活动引擎。但有一个问题始终没有回答——如何保证 15+ 个服务、多个开发者在长时间演进中不把这些设计搞乱？
靠 Code Review 口头约定往往不够。人总是会犯错，尤其是当 deadline 临近的时候。按我目前的理解，一个更稳妥的办法是：把架构约束尽量变成可自动执行的测试用例。
📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
上一篇：（六）插件化活动引擎
2026-04 实践更新 当前主线仓库里，ArchUnit、WireMock consumer contract tests、@HttpExchange 客户端基线、以及 JWKS 认证链都已经进入可验证状态；本文里的质量Quality Gates思路仍然适用，但哪些Quality Gates“只是方向”、哪些已经落地，请以 main 分支和 docs/ROADMAP-2026.md 为准。
质量Quality Gates全景 Shop Platform 的架构质量保障由三个支柱组成：
┌─────────────────────────────────────────────────────────┐ │ 架构质量Quality Gates │ │ │ │ ① ArchUnit 规则 → 验证已有代码是否符合约定 │ │ (19 条规则) │ │ │ │ ② Maven Archetype → 新服务从标准化骨架出发 │ │ (6 个模板) │ │ │ │ ③ WireMock contract → BFF 与领域服务接口兼容 │ │ (13 个 contract tests) │ └─────────────────────────────────────────────────────────┘ ArchUnit：用代码验证架构 ArchUnit 是一个 Java 库，可以在单元测试中验证类之间的依赖关系、命名约定、注解使用等架构约束。它的核心价值在于：把架构规则变成编译和 CI 中自动执行的测试，而不是文档里容易漂移的约定。</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 &#43; Java 25 &#43; Cloud Native 系列（六）：插件化活动引擎</title>
      <link>/posts/shop-platform-activity-engine/</link>
      <pubDate>Sun, 05 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/shop-platform-activity-engine/</guid>
      <description>在之前的文章中，我们看了 API Gateway、BFF 聚合、领域服务和事件驱动架构。本文继续整理 Shop Platform 里我觉得比较有意思的一块——activity-service 的插件化游戏引擎。
📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
上一篇：（五）事件驱动架构
2026-04 实践更新 当前主线代码里，RedEnvelopePlugin 和 AntiCheatGuard 都已经从 StringRedisTemplate 统一迁到 RedissonClient；本文讨论的 Lua 原子性和反作弊思路不变，但 Redis 客户端层已经与早期版本不同。
为什么需要活动引擎 电商平台经常需要举办营销活动来吸引用户：
砸金蛋/抽奖：用户消耗次数参与，随机获得奖品 抢红包：限时限量，用户拼手速抢金额 集卡：集齐一套卡片兑换大奖 虚拟养成：每天浇水/喂养，成熟后收获奖品 如果每个活动都独立开发一个新服务：
代码大量重复（参与记录、奖品发放、反作弊逻辑） 每次上线新活动都要走完整的发版流程 活动下线后代码变成死代码 这次项目里我更倾向用插件化引擎：一个服务、一套运行框架，新增活动时先实现一个插件接口，再让 Spring 负责发现和注册。
GamePlugin SPI 接口设计 核心接口 public interface GamePlugin { /** 声明支持的游戏类型 */ GameType supportedType(); /** 游戏激活时的初始化（如生成红包金额） */ default void initialize(ActivityGame game) {} /** 核心玩法：参与一次 */ ParticipateResult participate(ParticipateContext ctx); /** 游戏结束时的清理（如 Redis 数据回收） */ default void settle(ActivityGame game) {} /** 扩展表前缀（插件自带数据表时使用） */ default Optional&amp;lt;String&amp;gt; extensionTablePrefix() { return Optional.</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 &#43; Java 25 &#43; Cloud Native 系列（五）：事件驱动架构</title>
      <link>/posts/shop-platform-event-driven/</link>
      <pubDate>Sat, 04 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/shop-platform-event-driven/</guid>
      <description>在之前的文章中，我们看了同步请求链路上的 Gateway → BFF → 领域服务。但微服务架构中并不是所有交互都适合同步发生。事件驱动架构让服务之间通过异步消息协作，在不少场景下用最终一致性换取更低耦合和更好的链路弹性。
📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
上一篇：（四）领域服务设计
2026-04 实践更新 当前主线仓库已经把 IdempotencyGuard + Redis Bloom Filter、补偿任务重试、以及关键 Kafka consumer 的幂等保护补齐到 Phase 1 基线；本文整体设计仍然准确，但“待补齐”的幂等链路请以当前 main 分支实现为准。
为什么用事件驱动 在 Shop Platform 中，异步事件主要用来承接那些不必阻塞用户请求、但又需要可靠传播的业务事实。例如：
flowchart TD Order[&#34;用户下单order-service&#34;] Stock[&#34;扣库存marketplace-service&#34;] Points[&#34;发积分loyalty-service&#34;] Email[&#34;发邮件通知notification-service&#34;] Webhook[&#34;推送外部订阅webhook-service&#34;] Order --&gt;|&#34;同步 需要立即确认&#34;| Stock Order -.-&gt;|&#34;异步 可以延迟&#34;| Points Order -.-&gt;|&#34;异步&#34;| Email Order -.-&gt;|&#34;异步&#34;| Webhook 如果全部走同步 HTTP 调用：
下单接口响应时间 = 最慢下游服务的响应时间 任意下游服务不可用 → 下单失败 服务间耦合紧，新增消费者需要修改生产者 事件驱动的方式：
flowchart LR OS[&#34;order-service写入订单 + outbox同一事务&#34;] Pub[&#34;Outbox Publisher&#34;] Kafka[&#34;Kafkaorder.events.v1&#34;] L[&#34;</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 &#43; Java 25 &#43; Cloud Native 系列（四）：领域服务设计</title>
      <link>/posts/shop-platform-domain-services/</link>
      <pubDate>Fri, 03 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/shop-platform-domain-services/</guid>
      <description>在前两篇文章中，我们看了 API Gateway 的路由分发和 BFF 的聚合编排。这一篇继续往里走，看看业务承载最集中的一层——领域服务层。
📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
上一篇：（三）BFF 聚合层
2026-04 实践更新 领域服务侧当前已经和早期文章发布时相比前进了一步：Problem Details、@ServiceConnection、补偿任务持久化、Kafka 幂等守卫都已落地；本文中的领域边界划分仍然成立，但涉及“后续会做”的部分请以主线仓库现状为准。
领域服务清单 Shop Platform 核心业务按边界拆成 11 个领域服务，每个服务独立开发、独立部署、拥有自己的数据库 schema；此外 auth-server 自己维护 shop_auth，但它更偏认证边界，本文重点放在业务域服务。
服务 数据库 核心业务 profile-service shop_profile 用户档案、地址簿、卖家档案 marketplace-service shop_marketplace 商品目录、SKU、库存、评价 order-service shop_order 订单状态机、购物车、退款 wallet-service shop_wallet 钱包余额、充值、Stripe 支付 promotion-service shop_promotion 促销引擎、优惠券 loyalty-service shop_loyalty 积分账户、签到、兑换 activity-service shop_activity 插件化游戏引擎 search-service — Meilisearch 集成、Feature Toggle notification-service shop_notification 邮件通知、Channel SPI webhook-service shop_webhook 开放平台 Webhook、HMAC 签名 subscription-service shop_subscription 订阅计划、自动续费 其中 search-service 没有关系型数据库——它的数据存储在 Meilisearch 搜索引擎中。</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 &#43; Java 25 &#43; Cloud Native 系列（三）：BFF 聚合层</title>
      <link>/posts/shop-platform-bff-aggregation/</link>
      <pubDate>Thu, 02 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/shop-platform-bff-aggregation/</guid>
      <description>在上一篇中，我们看了 API Gateway 如何作为统一入口处理 JWT 校验和路由分发。请求经过 Gateway 后，到达的就是本文的主角——BFF（Backend for Frontend）聚合层。
📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
上一篇：（二）API Gateway 架构
2026-04 实践更新 当前主线代码里，buyer-bff / seller-bff 都已经完成了 typed @HttpExchange 客户端改造；BuyerAggregationService / SellerAggregationService 不再直接持有一堆 raw RestClient 调用链，而是通过 HttpServiceProxyFactory 注入声明式客户端。本文下面与客户端装配相关的表述已按当前实现校正。
BFF 模式：为什么需要聚合层 在微服务架构中，前端页面往往需要从多个领域服务获取数据。如果没有 BFF，前端直接调用每个领域服务会面临：
前端 ←→ profile-service (获取用户档案) ←→ wallet-service (获取钱包余额) ←→ promotion-service (获取可用优惠) ←→ marketplace-service (获取推荐商品) ←→ loyalty-service (获取积分账户) 问题显而易见：前端需要知道每个服务的地址、认证方式、数据格式；任何服务变动都会影响前端代码；更重要的是，前端暴露了内部服务拓扑，安全和治理成本都会明显上升。
graph LR FE1[&#34;前端&#34;] P[&#34;profile-service&#34;] W[&#34;wallet-service&#34;] PM[&#34;promotion-service&#34;] M[&#34;marketplace-service&#34;] L[&#34;loyalty-service&#34;] FE1 -.-&gt; P FE1 -.-&gt; W FE1 -.-&gt; PM FE1 -.</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 &#43; Java 25 &#43; Cloud Native 系列（二）：API Gateway 架构</title>
      <link>/posts/shop-platform-api-gateway/</link>
      <pubDate>Wed, 01 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/shop-platform-api-gateway/</guid>
      <description>在上一篇总览文章中，我们看到了 Shop Platform 的整体架构分层。API Gateway 作为整个系统当前统一的外部入口，承载了身份验证、流量控制、路由分发、文档聚合等多项职责。
📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
上一篇：（一）Shop Platform 总览
2026-04 实践更新 当前主线代码已经从 HS256 共享密钥切到 RS256 + JWKS，并把网关限流的 Lua 执行器统一到 RedissonClient + RScript。下面相关代码片段已按仓库当前实现同步。
为什么选 Spring Cloud Gateway Server MVC Spring Cloud Gateway 最初基于 WebFlux（Reactor）构建，是一个响应式网关。但在 2024–2025 年间，Spring Cloud 团队推出了 Spring Cloud Gateway Server MVC——一个基于 Servlet/MVC 的网关实现。
我们选择 MVC 而非 WebFlux，主要考虑了三点：
1. 统一编程模型
项目里 15+ 个后端服务全部是 Spring Boot MVC + Virtual Threads。如果网关用 WebFlux，就意味着团队需要同时维护两套编程模型：一套响应式（网关），一套同步阻塞（所有下游服务）。调试、日志追踪、异常处理的风格都不一样，增加了认知负担。
2. Virtual Threads 目前能满足需求
Virtual Threads 让每个 I/O 阻塞操作都运行在轻量级虚拟线程上，网关的并发能力不再完全依赖非阻塞 I/O 模型。对于 API Gateway 这种典型的 I/O 密集型应用（读 JWT、查 Redis、转发请求），它在当前项目的流量模型里已经提供了可接受的吞吐量，同时保留了同步代码的可读性。</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 &#43; Java 25 &#43; Cloud Native 系列（一）：Shop Platform 总览</title>
      <link>/posts/shop-platform-cloud-native-overview/</link>
      <pubDate>Sat, 21 Mar 2026 15:00:00 +0800</pubDate>
      
      <guid>/posts/shop-platform-cloud-native-overview/</guid>
      <description>为什么要做这个项目 在实际工作中，每当要推一套新的技术方向时，团队最常遇到的问题不是&amp;quot;知不知道这个技术&amp;quot;，而是——&amp;ldquo;这东西跑起来是什么样子？出了问题怎么排查？和现有的模块能不能配合？&amp;rdquo;
光读官方文档和博客往往很难回答这些问题。于是我决定做一个尽量完整跑通的 POC 项目——一个电商平台原型，把当时想亲手验证的技术选型尽量放进同一个可运行工程里，看看它们在微服务场景中能不能协同工作。
这个项目就是 Shop Platform，也是本系列文章的主角。
2026-04 实践更新 目前主线仓库已经完成一批最初文章发布时仍在演进中的平台项：auth-server → RS256 + JWKS、api-gateway → JWKS 校验 + Redisson Lua 限流、buyer-bff / seller-bff → 全量 @HttpExchange typed clients、镜像构建 → AppCDS 三阶段构建。还刻意保持延期的，主要是 DistributedLockExecutor 抽象、搜索增强、AI 推荐等下一阶段能力。
系列会围绕几个方向展开：
总览（本文）：项目背景、整体架构、技术栈速览 各层专题：API 网关、认证信任链、BFF 聚合、领域服务、事件总线、可观测、活动引擎…… 工程实践：ArchUnit 架构测试、Maven Archetype 脚手架、Feature Toggle、KMP 跨端…… 项目是什么 Shop Platform 是一个云原生微服务电商平台 POC，支持：
买家/游客浏览商品、加购物车、结账下单 卖家管理商品、订单、促销 钱包真实货币支付（Stripe 接入） 积分、优惠券、活动（签到/抽奖/集卡/虚拟养成） 搜索、Webhook 开放平台、订阅续费 项目目的是技术验证，不是生产级业务实现。功能覆盖面是为了让各个技术模块都能找到真实的应用场景，而不是为了做完整的业务产品。
整体架构 整体分为五个层次：
flowchart TD Client[&#34;客户端层Buyer Portal / Buyer App / Seller Portal&#34;</description>
    </item>
    
  </channel>
</rss>
