SpringCloud——微服务实战:OpenFeign与Nacos服务调用详解
这篇文章摘要主要讲述了在微服务架构中,如何通过服务调用解决blog-info-service迁移时遇到的数据依赖问题。作者首先分析了直接访问数据库的错误方案会导致服务耦合,随后提出了正确的解决方案:使用OpenFeign进行服务间通信,并引入api模块定义服务契约。文章详细阐述了完整的调用链流程,包括Nacos服务发现和Feign远程调用的配合使用,强调了微服务自治的重要性。最后总结了四个关键面试问题,并指出这一节将SpringCloud的各个组件(Gateway、Nacos、Feign等)串联起来,形成完整的知识链。
目录
4.3.3 blog-info-service 迁移 —— 第一次真正体现微服务调用
一、原来的博客模块
二、但是马上出现问题
三、错误方案:直接访问数据库
服务耦合。
四、正确方案:服务调用
五、这里引入 api 模块
user-info-api
六、user-info-service实现
七、blog-service如何调用?
八、完整调用链
九、这里重新理解 Nacos
服务地址变化问题。
十、这一节面试重点
1. 为什么微服务之间不能直接调用Service?
2. 为什么需要api模块?
3. Feign为什么需要服务名?
4. Nacos和Feign关系?
十一、你现在整个 Spring Cloud 知识链已经串起来了
4.3.4 Gateway 服务迁移
继续,我们进入:
4.3.3 blog-info-service 迁移 —— 第一次真正体现微服务调用
这一节比用户服务迁移更重要。
原因:
用户服务迁移只是拆模块。
但是博客服务迁移会遇到真正的微服务问题:
一个服务需要另一个服务的数据怎么办?
这就是:
服务间通信
OpenFeign
API模块
Nacos服务发现
真正落地。
一、原来的博客模块
单体项目:
blog-system controller BlogController service BlogService mapper BlogMapper entity Blog调用:
浏览器 ↓ BlogController ↓ BlogService ↓ BlogMapper ↓ MySQL例如:
查询博客列表:
@GetMapping("/list") public List<Blog> list(){ return blogService.list(); }但是现在拆成微服务:
spring-cloud-blog ├── user-info-service │ └── blog-info-service博客代码全部迁移:
blog-info-service ├── controller │ BlogController ├── service │ BlogService ├── mapper │ BlogMapper ├── entity │ Blog └── BlogInfoApplication二、但是马上出现问题
假设博客列表:
以前返回:
{ "id":1, "title":"Spring Cloud学习", "userId":1001 }现在前端希望:
{ "id":1, "title":"Spring Cloud学习", "user":{ "id":1001, "username":"xiaolu" } }怎么办?
以前:
同一个项目:
直接查:
userMapper.selectById(userId)即可。
现在:
两个服务:
blog-service ❌ userMapper不存在。
因为:
user-service:
另外一个 JVM。
三、错误方案:直接访问数据库
有人会想到:
博客服务:
直接连接:
user_db查询用户。
例如:
select * from user where id=1001;看似简单。
但是问题:
服务耦合。
结构:
blog-service | | ↓ user_db那么:
用户服务存在意义降低。
如果用户表改字段:
例如:
username 改成 nickname博客服务也要改。
这违反:
微服务自治。
四、正确方案:服务调用
架构:
blog-service | | ↓ user-service通过:
HTTP/RPC。
流程:
用户请求博客列表 ↓ gateway ↓ blog-service ↓ 调用 user-service ↓ 返回用户信息 ↓ 组装博客数据 ↓ 返回前端五、这里引入 api 模块
问题:
blog-service 怎么知道:
user-service 有什么接口?
比如:
查询用户:
User getUserById(Long id);如果直接写:
@RestController不行。
因为:
Controller是服务实现。
所以:
抽接口。
创建:
user-info-api结构:
user-info ├── user-info-api │ └── user-info-serviceuser-info-api
只放:
接口。
例如:
public interface UserApi { UserDTO getById(Long id); }注意:
没有:
@Service
没有:
数据库。
只是:
契约。
六、user-info-service实现
真正代码:
@RestController public class UserController implements UserApi { @Override public UserDTO getById(Long id){ return userService.getById(id); } }关系:
接口 UserApi ↑ | | UserController ↑ | UserService七、blog-service如何调用?
blog-service:
引入:
<dependency> <artifactId> user-info-api </artifactId> </dependency>然后:
创建Feign接口:
@FeignClient( name="user-service" ) public interface UserFeignClient extends UserApi { }这一步非常关键。
你之前学:
OpenFeign。
现在终于知道为什么需要它。
八、完整调用链
请求:
GET /blog/list进入:
Gateway:
localhost:9000↓
路由:
lb://blog-service↓
blog-service:
BlogController↓
查询博客:
BlogService↓
发现需要用户:
调用:
UserFeignClient↓
OpenFeign:
根据:
name=user-service去:
Nacos找。
↓
Nacos返回:
user-service 192.168.1.10:8081↓
HTTP调用:
↓
UserController
↓
返回。
整体:
Nacos ↑ | Gateway | | blog-service | Feign | user-service九、这里重新理解 Nacos
以前你学:
Nacos注册发现。
感觉:
只是:
服务列表。
现在结合业务:
它解决:
服务地址变化问题。
例如:
用户服务:
今天:
192.168.1.10:8081明天:
扩容:
192.168.1.11:8081 192.168.1.12:8081博客服务不用改代码。
因为:
调用:
@FeignClient("user-service")不是:
http://192.168.1.10:8081十、这一节面试重点
1. 为什么微服务之间不能直接调用Service?
答:
因为服务运行在不同JVM中,无法共享对象,需要通过RPC或者HTTP通信。
2. 为什么需要api模块?
答:
api模块定义服务契约,实现接口和调用方解耦,Feign可以基于接口生成远程调用代理。
3. Feign为什么需要服务名?
答:
服务名用于Nacos服务发现,通过服务名获取真实实例地址。
4. Nacos和Feign关系?
一句话:
Nacos负责找服务,Feign负责调用服务。
十一、你现在整个 Spring Cloud 知识链已经串起来了
之前:
你学的是零件:
Gateway JWT Nacos Feign LoadBalancer现在案例:
把零件组装:
客户端 ↓ Gateway (统一入口 + JWT) ↓ Nacos (服务发现) ↓ Feign (远程调用) ↓ user-service/blog-service ↓ 数据库下一节进入:
4.3.4 Gateway 服务迁移
这里会把你之前写的:
AuthGlobalFilter
真正放入案例。
重点:
网关如何统一鉴权
为什么服务内部还需要校验
JWT用户信息如何向下传递
Header透传设计
这一部分和你之前练的 Gateway Filter 完全对应。
