baiying 35c06cf598 Merge branch 'master' into feat-20260603-gray支持跨group服务 2 هفته پیش
..
src c83793cfcd gray支持跨group服务 2 هفته پیش
.gitignore 37b91fee51 1 1 ماه پیش
README.md c83793cfcd gray支持跨group服务 2 هفته پیش
pom.xml a304251768 1 2 ماه پیش

README.md

yyc-common-gray

基于 Nacos 的版本灰度跨 Group 服务发现公共组件,供 Feign + Ribbon 消费者与 Spring Cloud Gateway 复用。

能力概览

能力 场景 核心类
版本灰度(Ribbon) 微服务通过 Feign 调用同 Group 服务 GrayRibbonLoadBalancerRuleGrayFeignRequestInterceptor
跨 Group 发现(Ribbon) 消费者与提供方不在同一 Nacos Group NacosCrossGroupServerList
跨 Group 工具(Gateway) 路由 URI 编解码、直接查 Nacos 选实例 NacosGroupServiceIdCodecNacosCrossGroupInstanceSelector

引入依赖后通过 META-INF/spring.factories 自动装配,无需手动 @Import

依赖引入

<dependency>
    <groupId>net.yyc.common</groupId>
    <artifactId>yyc-common-gray</artifactId>
    <version>${yyc-common.version}</version>
</dependency>

传递依赖:yyc-common-corespring-cloud-starter-alibaba-nacos-discoveryfeign-core

适用栈:Spring Cloud Alibaba 2.2.x + Netflix Ribbon(@FeignClient + ribbon 负载均衡)。

版本灰度(Feign / Ribbon)

开关

gray:
  rule:
    enabled: true

开启后注册:

  • ribbonLoadBalancerRuleGrayRibbonLoadBalancerRule:按请求头 VERSION 与实例元数据 VERSION 匹配;无头或未匹配时随机选实例。
  • grayFeignRequestInterceptor:将当前 HTTP 请求的 VERSION 头透传到下游 Feign 调用。

约定

  • 请求头 / 元数据键名:VERSION(见 CommonConstants.VERSION)。
  • 实例需在 Nacos 注册元数据中携带对应 VERSION 字段。

注意

  • 非 Web 场景(定时任务、消息消费等)无 HttpServletRequest 时,规则会退化为随机选实例,与改造前行为一致。
  • 不要再配置 NFLoadBalancerRuleClassName(如 NacosRule),会与 ribbonLoadBalancerRule Bean 冲突。

跨 Nacos Group(Feign / Ribbon)

官方 NacosServerList 固定使用消费者自身的 spring.cloud.nacos.discovery.group,无法通过 {serviceId}.ribbon.nacos.group 指定目标 Group。本模块用 NacosCrossGroupServerList 覆盖实例拉取逻辑。

配置

为每个 @FeignClientvalue(即 Ribbon clientName / serviceId)指定目标 Group:

yyc:
  nacos:
    cross-group:
      gulop-gig-biz: cso_gig

未配置时 fallback 到 spring.cloud.nacos.discovery.group,与同 Group 服务行为一致。

示例

消费者 hnqz-upms-biz(Group cso_hnqz)调用 gulop-gig-biz(Group cso_gig):

@FeignClient(value = "gulop-gig-biz")
public interface GigUserApiClient { ... }
spring:
  cloud:
    nacos:
      discovery:
        group: cso_hnqz

yyc:
  nacos:
    cross-group:
      gulop-gig-biz: cso_gig

gray:
  rule:
    enabled: true

自动配置说明

组件 作用
NacosCrossGroupEnvironmentPostProcessor 启动早期排除 RibbonNacosAutoConfiguration,避免与自定义 @RibbonClients 重复注册
NacosCrossGroupRibbonAutoConfiguration @RibbonClients(defaultConfiguration = NacosCrossGroupRibbonClientConfiguration.class)
NacosCrossGroupRibbonClientConfiguration 注册 NacosCrossGroupServerList 替代默认 NacosServerList

激活条件:@ConditionalOnRibbonNacos(项目启用 Ribbon + Nacos 时)。

跨 Nacos Group(Gateway 共享工具)

网关侧不经过 Ribbon,使用 net.yyc.common.gray.nacos 包中的工具类(yyc-gateway-biz 等业务模块引用本 jar 即可)。

服务名编解码

Java URI 的 host 不允许 @_ 等字符,跨 Group 路由使用:

形态 示例
Nacos serviceId cso_gig@@gulop-gig-biz
路由 URI host(存储) cso-gig--gulop-gig-biz(group 中 _-

NacosGroupServiceIdCodec 提供 encodeLbUriparseFromUriHostparseFromNacosServiceId 等方法,并处理 %40%40 被 URI 解析器编码的情况。

实例选择

存在 org.springframework.cloud.gateway.filter.GlobalFilter 时,自动注册 NacosCrossGroupInstanceSelector Bean,按 group + serviceName 调用 Nacos selectInstances,并支持 VERSION 头灰度(与 Ribbon 规则语义一致)。

业务侧(如 NacosGroupGrayLoadBalancer)注入该 Bean 并传入版本头即可。

架构关系

flowchart TB
  subgraph feign [Feign 消费者]
    REQ[HTTP 请求 VERSION]
    INT[GrayFeignRequestInterceptor]
    SL[NacosCrossGroupServerList]
    RULE[GrayRibbonLoadBalancerRule]
    REQ --> INT
    INT --> RULE
    SL --> RULE
    SL -->|"yyc.nacos.cross-group.{serviceId}"| Nacos[(Nacos)]
  end

  subgraph gw [Gateway]
    CODEC[NacosGroupServiceIdCodec]
    SEL[NacosCrossGroupInstanceSelector]
    CODEC --> SEL
    SEL --> Nacos
  end

包结构

net.yyc.common.gray
├── GrayRibbonLoadBalancerConfiguration    # gray.rule.enabled 灰度规则与 Feign 拦截器
├── feign/
│   └── GrayFeignRequestInterceptor
├── rule/
│   └── GrayRibbonLoadBalancerRule
├── ribbon/
│   ├── NacosCrossGroupEnvironmentPostProcessor
│   ├── NacosCrossGroupRibbonAutoConfiguration
│   ├── NacosCrossGroupRibbonClientConfiguration
│   └── NacosCrossGroupServerList
└── nacos/
    ├── NacosGroupService
    ├── NacosGroupServiceIdCodec
    ├── NacosCrossGroupInstanceSelector
    └── NacosCrossGroupGatewayAutoConfiguration

常见问题

Q: 配置了 yyc.nacos.cross-group.gulop-gig-biz 仍拉不到实例?
A: 确认已引入本模块且未排除 NacosCrossGroupRibbonAutoConfiguration;查看日志中 Nacos cross-group server listtargetGroup 是否为预期值。

Q: Gateway 需要单独配 yyc.nacos.cross-group 吗?
A: 不需要。网关跨 Group 在路由 URI 中编码 group--service,由 NacosCrossGroupInstanceSelector 解析后查询;与 Feign 的 YAML 键是两套机制。

Q: 与 yyc-common-gateway 的关系?
A: yyc-common-gateway 提供 GrayLoadBalancerVersionGrayLoadBalancer 等 Gateway 灰度接口;本模块提供 Nacos 跨 Group 底层能力与 Ribbon 侧完整链路。网关业务模块通常同时依赖两者。

构建

cd yyc-common-parent
mvn -pl yyc-common-gray -am install

发布新版本后,通过 yyc-common-bom 统一升级各服务的 yyc-common-gray 坐标。