SpringCloud Common 核心抽象深度解析

作者:薪火铺子(薪火铺子)
如果本文对你有帮助,欢迎关注【薪火铺子】,回复「深入理解SpringCloud与实战」获取全套学习笔记

一、问题背景

Spring Cloud 是一个生态体系,它不仅仅包含 Netflix、Alibaba 等具体实现,更核心的是 Spring Cloud Commons —— 一套为所有实现提供公共抽象的模块。

为什么需要 Spring Cloud Common?

  • 屏蔽不同实现(Nacos、Consul、Eureka)的差异
  • 提供统一的编程模型
  • 实现可插拔的组件架构

二、Spring Cloud Commons 概述

2.1 模块结构

spring-cloud-commons
├── spring-cloud-commons-core        # 核心抽象
├── spring-cloud-loadbalancer        # 负载均衡抽象
├── spring-cloud-netflix-commons      # Netflix 实现
├── spring-cloud-alibaba-commons      # Alibaba 实现
└── spring-cloud-consul-discovery    # Consul 实现

2.2 核心价值

特性 说明
抽象接口 DiscoveryClient、LoadBalancer 等
SPI 机制 META-INF/spring.factories / spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
配置绑定 ConfigurationProperties 规范化
生命周期 SpringFactoryLoader 工厂加载

三、核心抽象接口

3.1 ServiceInstance 服务实例抽象

public interface ServiceInstance {
    // 实例唯一标识
    String getInstanceId();
    
    // 服务实例ID
    String getServiceId();
    
    // 主机名
    String getHost();
    
    // 端口
    int getPort();
    
    // 是否启用HTTPS
    boolean isSecure();
    
    // 元数据信息
    Map<String, String> getMetadata();
    
    // 统一资源标识符
    URI getUri();
}

这是服务发现最核心的抽象,所有注册中心实现(Nacos/Consul/Eureka)都需要将本地服务信息转换为 ServiceInstance

3.2 ServiceInstancesListSupplier 实例列表供应器

public interface ServiceInstancesListSupplier extends Supplier<Collection<ServiceInstance>> {
    // 获取服务名称
    String getService();
    
    // 获取默认空实现
    static ServiceInstancesListSupplier getNoServiceInstances(LoadBalancerProperties properties) {
        return new EmptyServiceInstancesListSupplier();
    }
}

3.3 DiscoveryClient 服务发现抽象

public interface DiscoveryClient extends Ordered {
    // 获取描述信息
    String description();
    
    // 获取服务实例列表
    List<ServiceInstance> getInstances(String serviceId);
    
    // 获取所有服务名称
    List<String> getServices();
    
    // 排序顺序
    int getOrder();
}
实现类关系图

«interface»

DiscoveryClient

+description() : String

+getInstances(serviceId) : List<ServiceInstance>

+getServices() : List<String>

NacosDiscoveryClient

-NamingService namingService

+getInstances(serviceId)

+getServices()

ConsulDiscoveryClient

-ConsulClient client

+getInstances(serviceId)

+getServices()

EurekaDiscoveryClient

-InstanceInfoRegistry registry

+getInstances(serviceId)

+getServices()

3.4 LoadBalancerClient 负载均衡抽象

public interface LoadBalancerClient {
    // 选择一个服务实例
    ServiceInstance choose(String serviceId);
    
    // 执行请求(重构方法)
    <T> T execute(String serviceId, LoadBalancerRequest<T> request);
    
    // 重建 URI
    URI reconstructURI(ServiceInstance instance, URI original);
}

3.5 LoadBalancerRequestTransformer 请求转换器

@FunctionalInterface
public interface LoadBalancerRequestTransformer {
    // 转换请求
    HttpRequest transformRequest(HttpRequest request, ServiceInstance instance);
}

四、SPI 机制深度解析

4.1 SpringFactoriesLoader vs SpringFactoryLoader

Spring Boot 2.7+ 使用新的 SPI 机制:

旧方式(2.7 之前):

META-INF/spring.factories

新方式(2.7+):

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

4.2 自动配置加载流程

BeanFactory AutoConfigurationRegistry SpringFactoriesLoader Spring Boot App BeanFactory AutoConfigurationRegistry SpringFactoriesLoader Spring Boot App Spring Boot 3.x / 2.7+ 迁移到 AutoConfiguration.imports 加载 spring.factories 注册 AutoConfiguration @Conditional 条件过滤 注册候选 Bean

4.3 Nacos 实现示例

// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.alibaba.cloud.nacos.ribbon.RibbonNacosAutoConfiguration
com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration

五、EnableDiscoveryClient 注解演进

5.1 注解定义

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface EnableDiscoveryClient {
    // 自动注册(可选)
    boolean autoRegister() default true;
}

5.2 自动注册原理

AutoServiceRegistration ServiceRegistryRegistry AutoServiceRegistrationConfiguration BootstrapApplicationListener AutoServiceRegistration ServiceRegistryRegistry AutoServiceRegistrationConfiguration BootstrapApplicationListener 检查 autoRegister 配置 是否启用自动注册 注册 AutoServiceRegistration 调用 start() 注册服务

5.3 AutoServiceRegistration 接口

public interface AutoServiceRegistration {
    // 开始注册
    void start();
    
    // 停止注册
    void stop();
    
    // 获取注册状态
    Registration getRegistration();
    
    // 获取管理对象
    AutoServiceRegistrationProperties getProperties();
}

六、LoadBalancer 负载均衡抽象

6.1 ReactorLoadBalancer 响应式抽象

public interface ReactorLoadBalancer<T> extends Ordered {
    // 响应式选择实例
    Mono<T> choose(Request request);
    
    // 获取负载均衡器标识
    default String getServiceId() {
        return "";
    }
}

6.2 Request 上下文抽象

public interface Request {
    // 获取客户端请求
    HttpRequest getClientRequest();
    
    // 获取负载均衡上下文
    Object getContext();
}

6.3 负载均衡器实现选择

RoundRobin

Random

WeightedResponseTime

自定义

发起请求

配置了哪些 LB

RoundRobinLoadBalancer

RandomLoadBalancer

WeightedResponseTimeLoadBalancer

CustomLoadBalancer

choose 实例

七、PropertySourceLocator 配置源定位

7.1 接口定义

public interface PropertySourceLocator {
    // 返回有序的配置源列表
    List<PropertySource<?>> locateCollection(
        Environment environment,
        PropertySource... compositePropertySources
    );
}

7.2 配置加载顺序

PropertySources PropertySourceLocator BootstrapContext Environment PropertySources PropertySourceLocator BootstrapContext Environment Bootstrap 阶段 Application 阶段 加载远程配置 添加 bootstrap 配置源 添加 application 配置源 合并到 Environment

八、实战演示

8.1 自定义服务发现实现

// 1. 实现 DiscoveryClient
@Component
public class CustomDiscoveryClient implements DiscoveryClient {
    
    @Override
    public List<ServiceInstance> getInstances(String serviceId) {
        // 从本地缓存或 HTTP 接口获取
        return discoverClient.getInstances(serviceId);
    }
    
    @Override
    public List<String> getServices() {
        return discoverClient.getServices();
    }
    
    @Override
    public String description() {
        return "Custom Discovery Client";
    }
    
    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }
}

// 2. 注册为 Bean(自动生效)
@Configuration
@ConditionalOnClass(DiscoveryClient.class)
@ConditionalOnMissingBean(DiscoveryClient.class)
public class CustomDiscoveryAutoConfiguration {
    @Bean
    public DiscoveryClient customDiscoveryClient() {
        return new CustomDiscoveryClient();
    }
}

// 3. META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// com.example.CustomDiscoveryAutoConfiguration

8.2 自定义负载均衡器

// 1. 实现 ReactorLoadBalancer
public class CustomLoadBalancer<T> implements ReactorLoadBalancer<T> {
    
    private final String serviceId;
    private final ObjectProvider<ServiceInstancesListSupplier> supplierProvider;
    
    public CustomLoadBalancer(
            String serviceId,
            ObjectProvider<ServiceInstancesListSupplier> supplierProvider) {
        this.serviceId = serviceId;
        this.supplierProvider = supplierProvider;
    }
    
    @Override
    public Mono<T> choose(Request request) {
        ServiceInstancesListSupplier supplier = supplierProvider.getIfAvailable();
        return supplier.get(request)
            .flatMap(instances -> selectServer(instances, request));
    }
    
    private Mono<T> selectServer(List<ServiceInstance> instances, Request request) {
        // 自定义选择逻辑
        if (instances.isEmpty()) {
            return Mono.empty();
        }
        // ... 自定义算法
        return Mono.just((T) instances.get(0));
    }
    
    @Override
    public int getOrder() {
        return LOWEST_PRECEDENCE;
    }
}

// 2. 配置类
@Configuration
@LoadBalancerClient(name = "custom-service", configuration = CustomLoadBalancerConfiguration.class)
public class CustomLoadBalancerConfiguration {
    // 配置自定义负载均衡器
}

8.3 自定义配置属性

// 定义配置属性
@ConfigurationProperties(prefix = "custom.discovery")
public class CustomDiscoveryProperties {
    private String url;
    private int timeout = 3000;
    private Map<String, String> metadata = new HashMap<>();
    
    // getters and setters
}

// 注册为 Bean
@EnableConfigurationProperties(CustomDiscoveryProperties.class)
public class CustomDiscoveryAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public CustomDiscoveryClient customDiscoveryClient(
            CustomDiscoveryProperties properties) {
        return new CustomDiscoveryClient(properties);
    }
}

九、避坑指南

坑 1:SPI 文件位置错误

问题:Spring Boot 3.x 不识别 META-INF/spring.factories

解决

# 正确位置
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

# 错误写法(3.x 不支持)
META-INF/spring.factories

坑 2:@ConditionalOnCloudPlatform 条件不满足

问题:自动配置未生效

解决:检查 spring.cloud 配置是否正确

spring:
  cloud:
    discovery:
      enabled: true

坑 3:多个 DiscoveryClient 实现冲突

问题:出现多个 Bean 冲突

解决:使用 @ConditionalOnMissingBean 或调整 @Order

@Bean
@ConditionalOnMissingBean(DiscoveryClient.class)
public DiscoveryClient customDiscoveryClient() {
    return new CustomDiscoveryClient();
}

坑 4:EnableDiscoveryClient 遗漏

问题:服务未自动注册到注册中心

解决:确保主启动类添加注解

@SpringBootApplication
@EnableDiscoveryClient
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

坑 5:元数据传递不一致

问题:Nacos/Consul 元数据格式不统一

解决:使用统一的 MetadataService 抽象

// 统一的元数据访问
@Service
public class UnifiedMetadataService {
    public Map<String, String> getMetadata(ServiceInstance instance) {
        if (instance instanceof HasMetadata) {
            return ((HasMetadata) instance).getMetadata();
        }
        return Collections.emptyMap();
    }
}

十、@LoadBalancerClient 注解详解

10.1 注解定义

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoadBalancerClient {
    // 服务名称
    String name() default "";
    
    // 自定义配置类
    Class<?>[] configuration() default {};
}

10.2 使用方式

// 1. 声明式使用
@Configuration
@LoadBalancerClient(name = "user-service", 
                    configuration = UserServiceLBConfig.class)
public class LoadBalancerConfig {
    // 为 user-service 指定自定义负载均衡器
}

// 2. Feign 客户端使用
@FeignClient(name = "user-service")
public interface UserClient {
    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
    User getUser(@PathVariable("id") Long id);
}

// 3. RestTemplate 使用
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}

// 使用
@Service
public class UserService {
    @Autowired
    private RestTemplate restTemplate;
    
    public User getUser(Long id) {
        // 会自动负载均衡到 user-service
        return restTemplate.getForObject(
            "http://user-service/user/" + id, 
            User.class
        );
    }
}

10.3 注解生效原理

LoadBalancerClient LoadBalancerClientFactory LoadBalancerInterceptor RestTemplate/Feign LoadBalancerClient LoadBalancerClientFactory LoadBalancerInterceptor RestTemplate/Feign 发起请求 http://user-service/user/1 获取 user-service 的 LB @LoadBalancerClient 配置 UserServiceLBConfig choose("user-service") 应用自定义负载均衡策略 选中实例 IP:Port reconstructURI 转发到实际地址

十一、ServiceRegistry 注册器抽象

11.1 ServiceRegistry 接口

public interface ServiceRegistry<R extends Registration> {
    /**
     * 注册服务
     */
    void register(R registration);
    
    /**
     * 注销服务
     */
    void deregister(R registration);
    
    /**
     * 关闭注册器
     */
    void close();
    
    /**
     * 设置状态
     */
    void setStatus(R registration, String status);
    
    /**
     * 获取状态
     */
    String getStatus(R registration);
    
    /**
     * 获取注册信息
     */
    R getRegistration();
}

11.2 各实现类关系

«interface»

ServiceRegistry

+register()

+deregister()

+setStatus()

NacosServiceRegistry

+register()

+deregister()

+setStatus()

ConsulServiceRegistry

+register()

+deregister()

+setStatus()

EurekaServiceRegistry

+register()

+deregister()

+setStatus()

ZookeeperServiceRegistry

+register()

+deregister()

+setStatus()

11.3 Nacos 注册器实现

public class NacosServiceRegistry implements ServiceRegistry<Registration> {
    
    private final NamingService namingService;
    
    @Override
    public void register(Registration registration) {
        String serviceId = registration.getServiceId();
        String host = registration.getHost();
        int port = registration.getPort();
        
        // 构建实例信息
        Instance instance = new Instance();
        instance.setIp(host);
        instance.setPort(port);
        instance.setWeight(registration.getMetadata().get("weight"));
        instance.setMetadata(registration.getMetadata());
        
        try {
            // 注册到 Nacos
            namingService.registerInstance(serviceId, instance);
        } catch (NacosException e) {
            throw new RuntimeException(e);
        }
    }
    
    @Override
    public void deregister(Registration registration) {
        String serviceId = registration.getServiceId();
        String host = registration.getHost();
        int port = registration.getPort();
        
        try {
            namingService.deregisterInstance(serviceId, host, port);
        } catch (NacosException e) {
            throw new RuntimeException(e);
        }
    }
}

11.4 服务状态管理

public class NacosServiceRegistry implements ServiceRegistry<Registration> {
    
    @Override
    public void setStatus(R registration, String status) {
        // UP/DOWN/OUT_OF_SERVICE/UNKNOWN
        String serviceId = registration.getServiceId();
        
        // 特殊状态处理
        if ("DOWN".equals(status)) {
            // 标记为不健康
            updateInstanceStatus(serviceId, registration, false);
        } else if ("UP".equals(status)) {
            // 恢复健康
            updateInstanceStatus(serviceId, registration, true);
        }
    }
    
    @Override
    public String getStatus(R registration) {
        String serviceId = registration.getServiceId();
        String instanceId = registration.getInstanceId();
        
        try {
            List<Instance> instances = namingService.selectInstances(
                serviceId, true
            );
            
            for (Instance instance : instances) {
                if (instance.getInstanceId().equals(instanceId)) {
                    return "UP";
                }
            }
            return "DOWN";
        } catch (NacosException e) {
            return "UNKNOWN";
        }
    }
}

11.5 自定义注册器实现

// 1. 实现 ServiceRegistry
public class CustomServiceRegistry implements ServiceRegistry<Registration> {
    
    private final CustomRegistryClient registryClient;
    
    @Override
    public void register(Registration registration) {
        registryClient.register(
            registration.getServiceId(),
            registration.getHost(),
            registration.getPort(),
            registration.getMetadata()
        );
    }
    
    @Override
    public void deregister(Registration registration) {
        registryClient.deregister(registration.getServiceId());
    }
    
    @Override
    public void close() {
        // 清理资源
    }
    
    @Override
    public void setStatus(Registration registration, String status) {
        registryClient.updateStatus(
            registration.getServiceId(), 
            status
        );
    }
    
    @Override
    public String getStatus(Registration registration) {
        return registryClient.getStatus(registration.getServiceId());
    }
    
    @Override
    public Registration getRegistration() {
        // 返回当前注册信息
        return null;
    }
}

// 2. 自动配置
@Configuration
@ConditionalOnClass(ServiceRegistry.class)
@ConditionalOnProperty(name = "spring.cloud.discovery.custom.enabled", 
    havingValue = "true")
public class CustomServiceRegistryAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean(ServiceRegistry.class)
    public ServiceRegistry customServiceRegistry(
            CustomRegistryProperties properties) {
        return new CustomServiceRegistry(properties.getClient());
    }
}

// 3. META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// com.example.CustomServiceRegistryAutoConfiguration

11.6 常用元数据配置

spring:
  cloud:
    nacos:
      discovery:
        # 服务元数据
        metadata:
          version: v1.0
          env: prod
          weight: 1.0
          healthy: true
        # 是否启用临时实例(ephemeral)
        ephemeral: true
        # 集群名称
        cluster-name: DEFAULT
        # 命名空间
        namespace: public
        
    consul:
      discovery:
        # 服务元数据
        tags:
          - version=v1.0
          - env=prod
        # 健康检查配置
        health-check:
          interval: 10s
          path: /actuator/health
        # 权重
        instance-weight: 1

十二、总结

Spring Cloud Commons 是整个 Spring Cloud 生态的基石,核心价值在于:

维度 内容
抽象层 DiscoveryClient、LoadBalancer、ServiceInstance
SPI 机制 AutoConfiguration、SPI 扩展点
配置绑定 ConfigurationProperties 统一管理
生命周期 BootstrapContext、ApplicationContextInitializer
客户端注解 @LoadBalancerClient 指定服务负载均衡配置
注册器抽象 ServiceRegistry 统一注册接口
核心价值 统一编程模型、可插拔实现

理解 Commons 层的设计思想,是掌握 Spring Cloud 各组件原理的前提。无论是 Nacos、Consul 还是 Eureka,它们的底层都遵循 Commons 定义的抽象接口,这种设计让业务代码与具体实现解耦,实现平滑切换。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐