<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>spring-cloud-gateway on </title>
    <link>/tags/spring-cloud-gateway/</link>
    <description>Recent content in spring-cloud-gateway on </description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Thu, 30 Apr 2026 10:00:00 +0800</lastBuildDate><atom:link href="/tags/spring-cloud-gateway/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>全链路 Feature Flag 的升级顺序：先 backend 还是先 frontend？</title>
      <link>/posts/full-stack-flag-upgrade-order/</link>
      <pubDate>Thu, 30 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/full-stack-flag-upgrade-order/</guid>
      <description>本文是 《Spring Boot 3.5 + Java 25 + React：在 K8s 里跑通一套跨链路 OpenFeature flag》 的续篇，聚焦三个场景中的第三个——全链路共享 flag 在升级过程中的顺序选择。
对应的 demo 代码仓库：sb3-k8s-hot-reload（私有）。
从一篇文章引发的真实问题讲起 上一篇写完后，有人在评论区提了一个非常实际的问题：
&amp;ldquo;你说的全链路 flag（full-stack shared flag）确实好理解——后端在 gateway 评估，前端通过 /experience/shared-flags 拿到同样的值。但实际加一个新 flag 的时候，先改哪一边？&amp;rdquo;
这个问题戳中了全链路 flag 最微妙的地方。
假设你的团队要上线一个&amp;quot;会员折扣算法 v2&amp;quot;功能：
后端：pricing-service 要用新算法计算价格 前端：UI 要在会员用户上展示&amp;quot;v2 折扣体验&amp;quot; 目标：u-vip-* 用户看到新体验，其他用户保持原样 先升级前端还是先升级后端？ 这不是一个语义问题，这是一个部署时序问题。部署时序错了，用户就会看到不一致的行为。
三种升级路径的风险拆解 路径一：前后端同时发布（&amp;ldquo;理想情况&amp;rdquo;） 前后端同时发布在理想状态下看起来很干净，但有几个现实坑点：
CI/CD 不同步：后端在 order-service/，前端在 ui/，通常走不同的 PR、不同的 review、不同的 merge。让两个独立流水线在精确的同一分钟上线几乎不可靠。 回滚不对称：如果上线后 10 分钟发现后端有 bug，你 kubectl rollout undo 回滚了后端，前端已经在跑新逻辑——此时前端看到的行为和后端完全脱节。 A/B 验证困难：你想先让 10% 用户尝鲜，但 flag 还没在 flagd 里配好（或者配了但 defaultVariant 不是目标值），新前端就已经在跑了。 所以&amp;quot;同时发布&amp;quot;更多是一种理想态，不是你可以依赖的策略。</description>
    </item>
    
    <item>
      <title>Spring Boot 3.5 &#43; Java 25 &#43; React：在 K8s 里跑通一套跨链路 OpenFeature flag</title>
      <link>/posts/spring-boot-openfeature-flagd-cross-stack/</link>
      <pubDate>Sun, 26 Apr 2026 15:00:00 +0800</pubDate>
      
      <guid>/posts/spring-boot-openfeature-flagd-cross-stack/</guid>
      <description>本文对应的 demo 项目：sb3-k8s-hot-reload（私有）。代码组织在 gateway/ order-service/ pricing-service/ ui/ k8s/ scripts/ 下，一条 ./scripts/e2e-demo.sh 从 kind 集群创建到端到端验证全跑完。
起点：一个朴素的约束 接到的题目是这样的：
在 Spring Boot 3.5 + Java 25 + Kubernetes（kind 本地）里，不用 Spring Cloud Config Server，不用 Netflix 套件（Eureka / Zuul / Ribbon / Hystrix）的前提下，验证一下&amp;quot;运行时配置变更不重启服务&amp;quot;这件事到底有哪些解、各自取舍是什么。后续要能支持 feature flag。
约束被排除的两块是有理由的：Config Server 在 K8s 原生场景里往往不再是首选（ConfigMap/Secret 已经在那里），Netflix 套件在 Spring Cloud 2023 起官方也已停止维护。但 Spring Cloud 不等于 Spring Cloud Config——spring-cloud-context、spring-cloud-kubernetes 这些仍然在维护，并且在 K8s 场景里依然是常见选择。
把约束精确化之后，问题就清晰了：在允许 spring-cloud-context 的前提下，K8s 上把&amp;quot;配置热加载&amp;quot;和&amp;quot;feature flag&amp;quot;分别做对，应该选什么。
热加载方案的选型矩阵 我把 2026 年还能找到、也比较贴近这个题目的可选项先压成一张表：</description>
    </item>
    
    <item>
      <title>没有 Service Mesh，用 API Gateway 做用户级灰度</title>
      <link>/posts/spring-cloud-gateway-canary-release/</link>
      <pubDate>Tue, 14 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/spring-cloud-gateway-canary-release/</guid>
      <description>本文基于的项目：https://github.com/meirongdev/shop（私有）。相关实现主要在 services/api-gateway。
从一个具体问题开始 buyer-bff 要升级一版，改动涉及订单接口的返回结构。上线前我们想让两三个内部测试账号先跑一段时间，其他人继续走旧版。出问题时能立刻回切，整个过程不要重启任何服务。
前提：环境里没有 Istio、没有 Linkerd，也没有 Argo Rollouts。Kubernetes 只有原生的 Service 和 Ingress。
在这种约束下，灰度发布能放在哪一层？
Kubernetes Service 权重：原生 Service 不支持按权重或按用户分流，它只是 round-robin。 应用内开关：让每个服务各自根据用户属性判断走新旧逻辑。问题是&amp;quot;谁是灰度用户&amp;quot;的判断会散落到每个服务里重复实现，也没法在入口做统一观测。代码层面的 feature flag 不是不能用，它和 Gateway 路由解的是不同层次的问题——本文末尾会讨论两者如何互补。 Service Mesh：能干净地做这件事，但引入一整套 sidecar/control plane，对这个项目太重。 API Gateway：请求进入系统的第一跳，比较自然地成为流量决策点。只要 Gateway 能按请求属性选择 upstream，就够了。 这个项目选了第四条。下面把每一个设计选择拆开讲。
Spring Cloud Gateway 在这里担任什么角色 Shop Platform 的 api-gateway 是 Spring Cloud Gateway Server MVC（不是 WebFlux 那套），运行在虚拟线程上。它在系统里承担的事情是常规的那几件：
路径路由（/api/buyer/** → buyer-bff，/auth/** → auth-server……） 鉴权（解析 JWT、注入 X-Buyer-Id 等可信 Header） 限流（基于 Redis 的令牌桶） CORS、OpenAPI 聚合 按用户做灰度路由 ← 本文主题 灰度在这里不是外挂的新组件，而是复用 Gateway 的路由匹配能力加一个自定义谓词。</description>
    </item>
    
    <item>
      <title>微服务架构下的 OpenAPI 聚合文档实践</title>
      <link>/posts/openapi-aggregation-in-microservice-architecture/</link>
      <pubDate>Fri, 10 Apr 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/openapi-aggregation-in-microservice-architecture/</guid>
      <description>📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
🏷️ 当前文章对应的代码版本：main
背景 在一个典型的微服务架构中，每个服务都独立维护自己的 API 文档。随着服务数量增长，前端开发者和第三方集成方常常面临一个痛点：
我需要去哪里找某个接口的文档？
传统的解决方案是让开发者记住每个服务的地址，或者维护一个手动的聚合页面。但这些方案都存在明显的问题：容易过时、维护成本高、无法与 CI/CD 集成。
本文以一个云原生电商平台的实际案例，记录我们当前如何通过 Spring Cloud Gateway MVC + SpringDoc 维护一套相对省事的 OpenAPI 聚合方案。
架构概览 我们的平台采用 Gateway + Thin BFF + Domain Service 三层架构：
Client └→ api-gateway:8080 (Spring Cloud Gateway MVC, JWT validation, rate limiting) ├→ /auth/** → auth-server ├→ /buyer/** → buyer-portal (Kotlin + Thymeleaf SSR) ├→ /seller/** → seller-app (KMP WASM SPA) ├→ /api/buyer/** → buyer-bff (aggregates domain services) ├→ /api/seller/** → seller-bff (aggregates domain services) ├→ /api/loyalty/** → loyalty-service ├→ /api/activity/** → activity-service ├→ /api/webhook/** → webhook-service └→ /api/subscription/** → subscription-service 共包含：</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>
    
  </channel>
</rss>
