注册中心 → 远程调用 → 负载均衡 → 服务降级 → 网关
一、5 大组件的依赖关系 (开发顺序的灵魂)
┌──────────────┐
│ 1. 注册中心 │ ← 第 1 步:Eureka/Nacos 搭起来
│ (Eureka) │
└──────┬───────┘
│ 服务注册
↓
┌──────────────┐
│ 2. 远程调用 │ ← 第 2 步:Feign 远程调用其他服务
│ (Feign) │
└──────┬───────┘
│ 调用时
↓
┌──────────────┐
│ 3. 负载均衡 │ ← 第 3 步:Ribbon 选哪个实例
│ (Ribbon) │
└──────┬───────┘
│ 调用失败
↓
┌──────────────┐
│ 4. 服务降级 │ ← 第 4 步:Hystrix/Sentinel 熔断
│ (Hystrix) │
└──────┬───────┘
│ 外部访问
↓
┌──────────────┐
│ 5. 网关 │ ← 第 5 步:Gateway 入口路由
│ (Gateway) │
└──────────────┘
核心:1 步都不能乱------没有注册中心,其他 4 个组件都没法用。
二、项目实战 (4 个 JVM 服务)
┌──────────────────────┐
│ Eureka Server │ ← 注册中心
│ (8761) │
└──────────┬───────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
┌───────▼────────┐ ┌────────▼────────┐ ┌───────▼────────┐
│ 报表服务 │ │ 数据采集服务 │ │ 告警服务 │
│ (8081) │ │ (8082) │ │ (8083) │
└────────────────┘ └─────────────────┘ └────────────────┘
▲ ▲ ▲
│ │ │
└────── Gateway (9000) 网关统一入口 ──────────┘
老哥开发 4 个服务的顺序 (MOVA 项目真实开发流程):
1.搭 Eureka Server
2.搭数据采集服务(注册 Eureka)
3.搭报表服务(注册 Eureka + Feign 远程调用采集)
4.搭告警服务(注册 Eureka + Feign 远程调用报表)
5.加 Ribbon 负载均衡
6.加 Hystrix 熔断
7.加 Gateway 网关
三、单个服务开发 5 步详解
3.1 第 1 步:注册中心 (Eureka / Nacos)
为什么先搞? 因为没有注册中心,服务之间互相找不到。
// 1. Eureka Server 启动类
@SpringBootApplication
@EnableEurekaServer // ⚠️ 启用 Eureka Server
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
// 2. Eureka Server 配置
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false # 自己是 Server
fetch-registry: false
// 3. 业务服务(报表服务)启动类
@SpringBootApplication
@EnableEurekaClient // ⚠️ 启用 Eureka Client(注册到 Eureka)
public class ReportApplication {
public static void main(String[] args) {
SpringApplication.run(ReportApplication.class, args);
}
}
// 4. 业务服务配置
spring:
application:
name: mova-report-service # ⚠️ 服务名(Feign 调用用)
eureka:
client:
service-url:
defaultZone: http://eureka-server:8761/eureka/
关键点:
- ⚠️ Eureka Server 自己不注册到 Eureka (
register-with-eureka: false) - ⚠️ 业务服务启动时自动注册 (
@EnableEurekaClient) - ⚠️ 服务名很重要(Feign 调用时用)
3.2 第 2 步:远程调用 (Feign)
为什么第二步? 因为服务注册到 Eureka 后,才能用服务名远程调用。
老哥 MOVA 实战代码(报表服务远程调用数据采集服务):
// 1. Feign 接口(声明式)
@FeignClient(name = "data-collect-service") // ⚠️ 服务名(Eureka 注册的)
public interface DataCollectFeignClient {
@GetMapping("/api/collect/status")
Result<CollectStatus> getStatus();
@PostMapping("/api/collect/exec")
Result<Void> execute(@RequestBody CollectRequest request);
}
// 2. 启动类启用 Feign
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients // ⚠️ 启用 Feign
public class ReportApplication {
public static void main(String[] args) {
SpringApplication.run(ReportApplication.class, args);
}
}
// 3. 业务调用(像本地方法)
@Service
public class ReportService {
@Autowired
private DataCollectFeignClient dataCollectClient;
public Report generateReport(Long reportId) {
// 1. 远程调用数据采集服务
CollectStatus status = dataCollectClient.getStatus().getData();
// 2. 业务处理
return processReport(reportId, status);
}
}
关键点:
- ⚠️
@FeignClient(name="...")的 name = Eureka 注册的服务名 - ⚠️ 接口的 URL = 数据采集服务的 URL(不是 Eureka 地址)
- ⚠️ Feign 自动把方法调用转成 HTTP 请求
Feign 自动做的事:
- 找 Eureka 拿服务列表
- 用 Ribbon 选一个实例(默认轮询)
- 发 HTTP 请求
- 把响应反序列化成方法返回值
3.3 第 3 步:负载均衡 (Ribbon)
为什么第三步? 因为Feign 已经集成了 Ribbon ,默认轮询策略 。只需要"配策略",不写代码。
实战配置:
# application.yml(报表服务)
data-collect-service: # ⚠️ Feign Client 的服务名
ribbon:
# 1. 负载均衡策略
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule # 权重响应时间
# 2. 连接超时
ConnectTimeout: 3000
# 3. 读取超时
ReadTimeout: 5000
# 4. 重试次数
MaxAutoRetries: 1
# 5. 重试下一个实例
MaxAutoRetriesNextServer: 2
或者用全局配置(影响所有 Feign Client):
@Configuration
public class RibbonConfig {
@Bean
public IRule ribbonRule() {
return new WeightedResponseTimeRule(); // 权重响应时间
}
}
关键点:
- ⚠️ Ribbon 不需要单独启用(Feign 已经集成)
- ⚠️ Feign 调用 = Ribbon 负载均衡 + HTTP 请求
- ⚠️ Ribbon 客户端均衡(消费者自己选实例,不同于 Nginx 服务端均衡)
7 大策略:
| 策略 | 适用场景 |
|---|---|
| RoundRobinRule(默认) | 通用场景 |
| RandomRule | 通用场景 |
| WeightedResponseTimeRule | 推荐(性能好的实例权重高) |
| BestAvailableRule | 高峰期 |
| RetryRule | 关键业务 |
| ZoneAvoidanceRule | 多区域部署 |
| AvailabilityFilteringRule | 故障剔除 |
项目实战:
- 报表 用 WeightedResponseTimeRule
- 关键功能 用 RetryRule(重试 3 次)
3.4 第 4 步:服务降级 (Hystrix / Sentinel)
为什么第四步? 因为远程调用可能失败 (服务宕机 / 网络超时),降级是兜底。
实战代码:
// 1. Feign 接口 + Fallback 降级
@FeignClient(name = "data-collect-service",
fallback = DataCollectFallback.class) // ⚠️ 降级类
public interface DataCollectFeignClient {
@GetMapping("/api/collect/status")
Result<CollectStatus> getStatus();
}
// 2. Fallback 降级类(实现 Feign 接口)
@Component
public class DataCollectFallback implements DataCollectFeignClient {
@Override
public Result<CollectStatus> getStatus() {
log.warn("数据采集服务熔断,返回兜底数据");
// ⚠️ 关键:返回兜底数据(不是抛异常)
return Result.ok(new CollectStatus("UNKNOWN", "服务降级"));
}
}
// 3. 启用 Hystrix(application.yml)
feign:
hystrix:
enabled: true # ⚠️ 老版本用这个
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 5000 # 5 秒超时
circuitBreaker:
requestVolumeThreshold: 10 # 10 次请求统计
errorThresholdPercentage: 50 # 50% 失败率打开熔断
sleepWindowInMilliseconds: 10000 # 10 秒后进入半开
// 4. 启用 Hystrix 启动类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix // ⚠️ 启用 Hystrix
public class ReportApplication {
public static void main(String[] args) {
SpringApplication.run(ReportApplication.class, args);
}
}
关键点:
- ⚠️ Hystrix = 4 大机制(熔断 + 降级 + 隔离 + 限流)
- ⚠️ Fallback 必须实现 Feign 接口(不是 @HystrixCommand 那种)
- ⚠️ 降级返回兜底数据(不是抛异常)
Hystrix 3 种状态:
关闭(Closed):正常调用,失败率 < 50%
↓ 失败率 > 50%(10 秒内 10 个请求中 5 个失败)
打开(Open):快速失败,直接返回 Fallback
↓ 10 秒后
半开(Half-Open):试探调用 1 个
↓ 成功
关闭(Closed):恢复正常
项目实战:
- 报表 Hystrix 熔断,避免报表雪崩
- 故障发现时间从 30 分钟降至 30 秒
⚠️ 注意 :Spring Cloud 2020+ 改用 Resilience4j 替代 Hystrix ,新项目推荐用 Sentinel。
3.5 第 5 步:网关 (Gateway / Zuul)
为什么第五步? 因为所有服务都搭好后,才需要统一入口。
实战配置:
XML
# application.yml(独立 Gateway 服务)
server:
port: 9000
spring:
application:
name: mova-gateway
cloud:
gateway:
# 1. 路由配置
routes:
- id: mova-report
uri: lb://mova-report-service # ⚠️ lb = 负载均衡
predicates:
- Path=/api/mova/**
filters:
- StripPrefix=2 # 去掉 /api/mova 前缀
- id: mpvs-mask
uri: lb://mpvs-mask-service
predicates:
- Path=/api/mpvs/**
- id: spdb-collect
uri: lb://spdb-collect-service
predicates:
- Path=/api/spdb/**
# 2. 全局跨域
globalcors:
cors-configurations:
'[/**]':
allowedOriginPatterns: "*"
allowedMethods: "*"
# 3. 限流
redis:
rate-limiter:
replenish-rate: 100 # 每秒 100 个请求
burst-capacity: 200 # 突发 200 个

// 启动类
@SpringBootApplication
@EnableDiscoveryClient // ⚠️ Gateway 也注册到 Eureka
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
关键点:
- ⚠️ uri: lb://xxx 中的
lb= LoadBalancer(自动负载均衡) - ⚠️ predicates = 路由规则(Path / Header / Cookie 等)
- ⚠️ filters = 过滤(鉴权 / 限流 / 重写路径)
Gateway 4 大功能:
1.路由:根据 Path 转发
2.鉴权:JWT / OAuth2
3.限流:Redis 限流
4.熔断:Hystrix / Sentinel
四、5 大组件协同工作流 (完整链路)
外部用户请求
↓
1. Gateway 网关(9000 端口)
├─ 鉴权(JWT 验证)
├─ 限流(Redis 限流 100 QPS)
└─ 路由(Path=/api/mova/**)
↓
2. Ribbon 负载均衡(从 Eureka 拉服务列表,选 1 个实例)
↓
3. Feign 远程调用(mova-report-service)
↓
4. Hystrix 熔断保护(调用失败熔断,返回 Fallback)
↓
5. Eureka 服务发现(找 mova-report-service 的 IP:Port)
↓
目标服务执行(mova-report-service)
↓
返回结果
五、5 大组件的依赖关系
"5 大组件的依赖顺序就是开发顺序:
1.注册中心 (Eureka)------ 基础,没有它其他 4 个都没法用
2.远程调用 (Feign)------ 核心,用服务名调用其他服务
3.负载均衡 (Ribbon)------ Feign 自带 ,只配策略不写代码
4.服务降级 (Hystrix)------ 兜底,调用失败时返回 Fallback
5.网关 (Gateway)------ 入口,所有请求统一入口
开发顺序:Eureka Server → 数据采集服务 → 报表服务 → 告警服务 → 加 Ribbon → 加 Hystrix → 加 Gateway。"
六、完整代码模板
6.1 父 pom.xml 依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<properties>
<spring-cloud.version>2021.0.8</spring-cloud.version>
</properties>
<dependencies>
<!-- 1. Eureka 客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 2. Feign 远程调用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 3. Hystrix 熔断(Spring Cloud 2021 改 Resilience4j)-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- 4. Gateway 网关(独立服务)-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
7.2 Eureka Server 完整配置
# application.yml(Eureka Server)
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://eureka-server:8761/eureka/
server:
enable-self-preservation: true
eviction-interval-timer-in-ms: 5000
7.3 业务服务完整配置
# application.yml(报表服务)
server:
port: 8081
spring:
application:
name: mova-report-service
# 1. Eureka
eureka:
client:
service-url:
defaultZone: http://eureka-server:8761/eureka/
instance:
prefer-ip-address: true
lease-renewal-interval-in-seconds: 30
lease-expiration-duration-in-seconds: 90
# 2. Ribbon(Feign 自带)
data-collect-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
ConnectTimeout: 3000
ReadTimeout: 5000
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 2
# 3. Feign + Hystrix
feign:
hystrix:
enabled: true
client:
config:
default:
connectTimeout: 3000
readTimeout: 5000
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 5000
circuitBreaker:
requestVolumeThreshold: 10
errorThresholdPercentage: 50
sleepWindowInMilliseconds: 10000
7.4 Gateway 完整配置
# application.yml(独立 Gateway 服务)
server:
port: 9000
spring:
application:
name: mova-gateway
cloud:
gateway:
routes:
- id: mova-report
uri: lb://mova-report-service
predicates:
- Path=/api/mova/**
filters:
- StripPrefix=2
redis:
rate-limiter:
replenish-rate: 100
burst-capacity: 200
七、记忆口诀
"5 大组件开发顺序:注册 → 调用 → 均衡 → 降级 → 网关"
"1 不能乱:没有注册中心,其他 4 个都用不了"
"Feign 自带 Ribbon,Ribbon 不写代码"