Spring Cloud 核心源码串讲
概述
本文串联 Spring Cloud 网关、注册发现、熔断限流、RPC 调用的核心源码,展示一次 API 请求穿越完整微服务链路的全流程。
一、全链路源码全景
请求进入 Gateway
↓
1. RoutePredicateHandlerMapping.getHandlerInternal()
→ 路由匹配(路径 / Header / 权重)
↓
2. FilteringWebHandler.handle()
→ Gateway 过滤器链执行(鉴权→限流→熔断→转发)
↓
3. LoadBalancerFilter.filter()
→ 从 Nacos 获取服务实例列表
→ LoadBalancer 选择实例(轮询/权重/灰度)
↓
4. NettyRoutingFilter.filter()
→ 转发请求到下游服务
↓
5. Sentinel CtSph.entry()
→ 限流/熔断检查(FlowSlot / DegradeSlot)
↓
6. Feign InvocationHandler.invoke()
→ 动态代理调用(RPC 请求)
↓
7. 服务端处理完成 → 响应返回二、Gateway 路由源码
2.1 RoutePredicateHandlerMapping
java
// org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping
public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
@Override
protected Mono<Object> getHandlerInternal(ServerWebExchange exchange) {
// 1. 从 RouteLocator 获取所有路由定义
return this.routeLocator.getRoutes()
.filter(route -> {
// 2. 逐一匹配路由的 Predicate 条件
// path=/api/orders/** → PathRoutePredicateFactory
// header=X-Version=v2 → HeaderRoutePredicateFactory
return route.getPredicate().test(exchange);
})
.next() // 取第一个匹配的路由
.flatMap(route -> {
// 3. 设置匹配的路由到 exchange 属性
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, route);
// 4. 返回 FilteringWebHandler
return Mono.just(new FilteringWebHandler.WebHandler(route));
});
}
}2.2 FilteringWebHandler
java
// FilteringWebHandler — Gateway 过滤器链执行
public class FilteringWebHandler implements WebHandler {
// 全局过滤器 + 路由级过滤器 → 组合成过滤器链
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
// 1. 获取当前路由的过滤器
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
List<GatewayFilter> gatewayFilters = route.getFilters();
// 2. 合并全局过滤器
List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
combined.addAll(gatewayFilters);
// 3. 排序(@Order 控制顺序)
AnnotationAwareOrderComparator.sort(combined);
// 4. 创建过滤器链并执行
DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(combined);
return chain.filter(exchange);
}
}2.3 内置 Filter 列表
| 过滤器 | 作用 | 执行顺序 |
|---|---|---|
RemoveCachedBodyFilter | 清除缓存请求体 | -2147483648 |
AdaptCachedBodyGlobalFilter | 缓存请求体 | -2147482648 |
NettyWriteResponseFilter | 写入响应 | -1 |
ForwardRoutingFilter | 转发本地路由 | -2147483648 |
LoadBalancerClientFilter | 负载均衡 | 10100 |
NettyRoutingFilter | Netty 转发 | 2147483647 |
ForwardPathFilter | 路径重写 | 0 |
三、Nacos 服务注册
3.1 NacosServiceRegistry.register()
java
// com.alibaba.cloud.nacos.registry.NacosServiceRegistry
@Override
public void register(Registration registration) {
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No service to register...");
return;
}
// 1. 获取 Nacos NamingService
NamingService namingService = namingService();
// 2. 构建实例信息(IP、端口、权重、元数据)
Instance instance = getNacosInstanceFromRegistration(registration);
try {
// 3. 注册到 Nacos Server(HTTP POST 请求)
// Nacos Server 接收后:
// - 添加到 Service
// - 维护心跳检测
// - 通知订阅者
namingService.registerInstance(registration.getServiceId(), instance);
} catch (Exception e) {
throw new NacosRegistrationException("...");
}
}3.2 服务发现 (LoadBalancer)
java
// NacosServiceDiscovery.getInstances()
public List<Instance> getInstances(String serviceId) throws NacosException {
// 从 Nacos Server 获取健康的实例列表
// 客户端缓存实例列表,长轮询监听变更
return namingService().selectInstances(serviceId, true);
}
// Spring Cloud LoadBalancer 集成
public class NacosLoadBalancerClient implements ServiceInstanceListSupplier {
@Override
public Flux<ServiceInstance> get() {
return Flux.defer(() -> {
// 从 Nacos 获取实例列表
List<Instance> nacosInstances = getNacosInstances(serviceId);
// 转换为 Spring Cloud ServiceInstance
List<ServiceInstance> instances = nacosInstances.stream()
.map(instance -> new NacosServiceInstance(instance))
.collect(Collectors.toList());
return Flux.just(instances);
});
}
}四、Sentinel 限流
4.1 入口
java
// Sentinel 通过 @SentinelResource 或 Spring Cloud Gateway 过滤器触发
// GatewaySentinelFilter — Sentinel 网关适配
public class SentinelGatewayFilter implements GatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 构建资源名
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
String resourceName = route.getId();
// 2. 执行 Sentinel 限流检查
Entry entry = null;
try {
entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_API_GATEWAY, EntryType.IN);
return chain.filter(exchange);
} catch (BlockException ex) {
// 3. 被限流 → 返回 429
return handleBlocked(exchange, ex);
} finally {
if (entry != null) {
entry.exit();
}
}
}
}4.2 CtSph.entry()
java
// com.alibaba.csp.sentinel.CtSph
@Override
public Entry entry(String name, EntryType type) throws BlockException {
return entryWithPriority(name, type, false);
}
private Entry entryWithPriority(String name, EntryType type, boolean prioritize) throws BlockException {
// 1. 从缓存获取 ProcessorSlotChain
ProcessorSlot<Object> chain = lookProcessChain(name);
// 2. 创建 Entry
CtEntry entry = new CtEntry(name, type);
try {
// 3. 执行 Slot 链(责任链模式)
// NodeSelectorSlot → ClusterBuilderSlot → StatisticSlot
// → FlowSlot → DegradeSlot → AuthoritySlot → SystemSlot
chain.entry(entry.getContext(), entry, name, type);
} catch (BlockException e) {
entry.exit();
throw e;
}
return entry;
}五、Feign 动态代理
5.1 代理创建
java
// Feign.Builder → ReflectiveFeign → FeignInvocationHandler
// 入口:@EnableFeignClients → FeignClientsRegistrar
// 1. 扫描 @FeignClient 接口
// 2. 注册 FeignClientFactoryBean
// 3. FactoryBean.getObject() → 创建代理
// FeignClientFactoryBean.getObject()
public Object getObject() {
return getTarget();
}
<T> T getTarget() {
// 构建 Feign Builder
Feign.Builder builder = feign(context);
// 创建 Target
Target<T> target = new HardCodedTarget<>(this.type, this.name, this.url);
// 创建代理
return builder.target(target);
}5.2 FeignInvocationHandler
java
// feign.ReflectiveFeign.FeignInvocationHandler
public class FeignInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 1. 处理 Object 方法
if ("equals".equals(method.getName())) {
// ...
} else if ("hashCode".equals(method.getName())) {
return hashCode();
} else if ("toString".equals(method.getName())) {
return toString();
}
// 2. 查找对应的方法处理器
MethodHandler handler = this.dispatch.get(method);
// 3. 执行 RPC 调用(核心!)
// 内部构建 HTTP 请求 → 序列化参数 → 发送 HTTP 请求 → 反序列化响应
return handler.invoke(args);
}
}5.3 负载均衡集成
java
// LoadBalancerFeignClient — 集成 Spring Cloud LoadBalancer
public class LoadBalancerFeignClient implements Client {
@Override
public Response execute(Request request, Request.Options options) throws IOException {
// 1. 解析 URL 中的服务名
URI originalUri = URI.create(request.url());
String serviceName = originalUri.getHost();
// 2. 通过 LoadBalancer 选择实例
ServiceInstance instance = loadBalancerClient.choose(serviceName);
// 3. 替换 URL 为实例地址
String url = buildUrl(instance, originalUri);
Request newRequest = buildRequest(request, url);
// 4. 执行 HTTP 调用
return this.delegate.execute(newRequest, options);
}
}六、完整链路示例
text
请求:GET http://gateway/api/orders/1001
Header: Authorization=Bearer xxx
源码执行路径:
1. Netty 接收请求 → ReactorHttpHandlerAdapter
↓
2. DispatcherHandler.handle() → WebFlux 分发
↓
3. RoutePredicateHandlerMapping.getHandlerInternal()
→ 路由:/api/orders/** → order-service
↓
4. Gateway 过滤器链
├── GatewaySentinelFilter → SphU.entry("order-service")
├── LoadBalancerClientFilter → Nacos 获取 order-service 实例
│ → NacosServiceDiscovery.getInstances()
│ → 选择实例:192.168.1.10:8080
└── NettyRoutingFilter → 转发到 192.168.1.10:8080
↓
5. 服务端(order-service)接收请求
├── SecurityFilterChain → 验证 JWT Token
├── DispatcherServlet.doDispatch() → RequestMappingHandlerMapping
├── OrderController.getOrder()
│ └── OrderService.getOrder(1001)
│ └── OrderFeignClient.getUser(123) → FeignInvocationHandler
│ → 负载均衡到 user-service
│ → 调用 UserService.getUser()
└── 返回 JSON 响应七、总结
| 组件 | 关键类 | 核心方法 |
|---|---|---|
| Gateway 路由 | RoutePredicateHandlerMapping | getHandlerInternal() |
| Gateway 过滤 | FilteringWebHandler | handle() |
| 负载均衡 | LoadBalancerClientFilter | filter() |
| Nacos 注册 | NacosServiceRegistry | register() |
| Nacos 发现 | NacosServiceDiscovery | getInstances() |
| Sentinel 限流 | CtSph | entry() |
| Sentinel 流控 | FlowSlot | checkFlow() |
| Feign 代理 | FeignInvocationHandler | invoke() |
| Feign 负载 | LoadBalancerFeignClient | execute() |
参考链接: