一、服务的拆分

1-1、springcloud项目的标准结构
SpringCloud 项目 ≠ 一个项目,而是一组项目(多个 SpringBoot 服务)。
这组项目通常包含:
-
网关
-
注册中心
-
配置中心
-
业务服务(如用户/订单/支付)
-
公共依赖模块
标准项目结构:
cloud-project/ ← 父工程(管理所有模块)
│── pom.xml ← 统一版本管理(dependencyManagement)
│
├── cloud-common/ ← 公共模块(工具类/统一响应/异常处理)
│ └── pom.xml
│
├── cloud-api/ ← 公共 Feign 接口模块(服务间调用用)
│ └── pom.xml
│
├── cloud-gateway/ ← 服务网关模块(统一入口)
│ └── pom.xml
│
├── cloud-register/ ← 注册中心(Nacos / Eureka)
│ └── pom.xml
│
├── cloud-config/ ← 配置中心(Nacos Config / SpringCloud Config)
│ └── pom.xml
│
├── cloud-user-service/ ← 用户服务(业务服务 A)
│ └── pom.xml
│
├── cloud-order-service/ ← 订单服务(业务服务 B)
│ └── pom.xml
│
└── cloud-pay-service/ ← 支付服务(业务服务 C)
└── pom.xml
各模块用来干嘛?
| 模块 | 作用 | 你可以理解为 |
|---|---|---|
| cloud-project(父工程) | 管理所有子模块的版本和依赖 | 整个系统的大外框 |
| cloud-common | 公共工具类、返回结果封装、异常处理 | 公共工具箱 |
| cloud-api | Feign 接口、服务之间的调用客户端 | 服务之间的通讯协议 |
| cloud-gateway | 统一入口、权限验证、路由、限流 | 大门/前台 |
| cloud-register | 服务注册与发现(Nacos/Eureka) | 服务通讯录 |
| cloud-config | 集中配置管理 | 公司制度手册 |
| cloud-user-service | 用户业务逻辑 | 工人 A |
| cloud-order-service | 订单业务逻辑 | 工人 B |
| cloud-pay-service | 支付业务逻辑 | 工人 C |
1-2、项目从零启动的顺序
-
先启动注册中心(Nacos/Eureka)
-
再启动配置中心(如果有)
-
再启动网关
-
最后启动每个业务服务
为什么?
因为业务服务启动时需要去「注册中心」登记自己。
二、微服务的远程调用
2-1、DEMO项目结构



2-2、RestTemplate 发起http请求


2-3、Feign
1、微服务之间的远程调用有两种方式
| 调用方式 | 技术 | 特点 |
|---|---|---|
| 基于 HTTP | OpenFeign(最常用) | 写接口就能调用,简单优雅 |
| 基于 RPC | Dubbo / gRPC / Thrift | 二进制协议,性能更高,但更复杂 |
SpringCloud 主推的是 OpenFeign。
2、场景举例
订单服务 → 想要查询用户信息 → 调用用户服务的接口
OrderService ----(网络调用)----> UserService
3、开始用 Feign 调用
第一步:在服务中开启 Feign
在订单服务的启动类上加:
java
@EnableFeignClients
@SpringBootApplication
public class OrderApplication {}
第二步:在 pom.xml 中引入依赖
XML
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
第三步:定义一个 Feign 接口
java
@FeignClient(name = "user-service") // 指向注册中心里的服务名
public interface UserClient {
@GetMapping("/user/{id}")
UserDTO getUserById(@PathVariable("id") Long id);
}
注意:
| 部分 | 意义 |
|---|---|
@FeignClient(name="user-service") |
告诉 Feign 去调用 注册中心中名字叫 user-service 的服务 |
@GetMapping("/user/{id}") |
告诉它调用对方的这个 HTTP 接口 |
【注意】:
这是被调用的接口!!!
第四步:在订单服务里调用它(像本地方法一样简单)
java
@Service
public class OrderService {
@Autowired
private UserClient userClient;
public void createOrder(Long userId) {
// 像本地方法一样,直接调用
UserDTO user = userClient.getUserById(userId);
System.out.println("下单用户:" + user.getName());
}
}
虽然看起来像本地方法调用,但本质是 HTTP 远程调用。
2-4、Feign + 负载均衡
如果 user-service 启动多份实例:
user-service:8081
user-service:8082
user-service:8083
Feign 会 自动做负载均衡,因为它与 Ribbon / LoadBalancer 集成。
你不需要写代码,SpringCloud 会帮你自动轮询调用不同实例。
2-5、Feign + 熔断(服务挂掉怎么办?)
如果用户服务挂了,为避免订单服务崩溃,你可以加 fallback:
java
@FeignClient(name = "user-service", fallback = UserClientFallback.class)
public interface UserClient { ... }
@Component
public class UserClientFallback implements UserClient {
public UserDTO getUserById(Long id) {
return new UserDTO(-1L, "用户服务当前不可用");
}
}
这叫 服务降级保护。
小结
在 SpringCloud 中,微服务之间通过 OpenFeign 实现远程调用。
Feign 会根据
@FeignClient指定的服务名,从 注册中心(Nacos/Eureka) 获取服务实例地址,并通过 HTTP 完成调用。同时结合 Ribbon / LoadBalancer 实现负载均衡,结合 Sentinel/Hystrix 提供熔断与降级保护,避免服务雪崩。
一句话总结
OpenFeign = 写接口 → 自动发 HTTP 请求 + 自动负载均衡 + 可降级保护。
三、RestTemplate 和 Feign 是什么关系
| 技术 | 出现时间 | 作用 | 写代码体验 |
|---|---|---|---|
| RestTemplate | 老一辈 | 手写 URL,自行发 HTTP 请求 | 麻烦,自己组装参数 |
| OpenFeign | 新一代(推荐) | 写接口就能调用,帮你自动 HTTP 请求 | 简单优雅 |
Feign 内部本质就是用 RestTemplate(或 HttpClient)发请求,只是帮你封装好了
3-1、代码演变过程
1)初级(无注册中心)
订单服务直接写死用户服务的 IP:
java
RestTemplate rt = new RestTemplate();
rt.getForObject("http://localhost:8081/user/1", User.class);
缺点:写死了 IP + 端口,服务迁移/扩容就挂了。
2)中级(有注册中心 + 负载均衡 Ribbon)
java
@Autowired
RestTemplate rt;
// 加上 @LoadBalanced,名字会去注册中心找
User u = rt.getForObject("http://user-service/user/1", User.class);
✔ 不再写死 IP
✔ 可以自动轮询多实例
✖ 但是 URL 写法仍然比较"硬"
3)高级(Feign)
java
@FeignClient("user-service")
public interface UserClient {
@GetMapping("/user/{id}")
User getUser(@PathVariable Long id);
}
使用时:
userClient.getUser(id);
像本地方法一样用 → 最优雅