SpringCloud Common 核心抽象深度解析
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();
}
实现类关系图
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 自动配置加载流程
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 自动注册原理
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 负载均衡器实现选择
七、PropertySourceLocator 配置源定位
7.1 接口定义
public interface PropertySourceLocator {
// 返回有序的配置源列表
List<PropertySource<?>> locateCollection(
Environment environment,
PropertySource... compositePropertySources
);
}
7.2 配置加载顺序
八、实战演示
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 注解生效原理
十一、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 各实现类关系
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 定义的抽象接口,这种设计让业务代码与具体实现解耦,实现平滑切换。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)