SpringCloud——微服务实战:OpenFeign与Nacos服务调用详解

这篇文章摘要主要讲述了在微服务架构中,如何通过服务调用解决blog-info-service迁移时遇到的数据依赖问题。作者首先分析了直接访问数据库的错误方案会导致服务耦合,随后提出了正确的解决方案:使用OpenFeign进行服务间通信,并引入api模块定义服务契约。文章详细阐述了完整的调用链流程,包括Nacos服务发现和Feign远程调用的配合使用,强调了微服务自治的重要性。最后总结了四个关键面试问题,并指出这一节将SpringCloud的各个组件(Gateway、Nacos、Feign等)串联起来,形成完整的知识链。

目录

[4.3.3 blog-info-service 迁移 ------ 第一次真正体现微服务调用](#4.3.3 blog-info-service 迁移 —— 第一次真正体现微服务调用)

一、原来的博客模块

二、但是马上出现问题

三、错误方案:直接访问数据库

服务耦合。

四、正确方案:服务调用

[五、这里引入 api 模块](#五、这里引入 api 模块)

user-info-api

六、user-info-service实现

七、blog-service如何调用?

八、完整调用链

[九、这里重新理解 Nacos](#九、这里重新理解 Nacos)

服务地址变化问题。

十、这一节面试重点

[1. 为什么微服务之间不能直接调用Service?](#1. 为什么微服务之间不能直接调用Service?)

[2. 为什么需要api模块?](#2. 为什么需要api模块?)

[3. Feign为什么需要服务名?](#3. Feign为什么需要服务名?)

[4. Nacos和Feign关系?](#4. Nacos和Feign关系?)

[十一、你现在整个 Spring Cloud 知识链已经串起来了](#十一、你现在整个 Spring Cloud 知识链已经串起来了)

[4.3.4 Gateway 服务迁移](#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-service

user-info-api

只放:

接口。

例如:

复制代码
public interface UserApi {


    UserDTO getById(Long id);


}

注意:

没有:

@Service

没有:

数据库。

只是:

契约。


六、user-info-service实现

真正代码:

java 复制代码
@RestController
public class UserController 
        implements UserApi {


    @Override
    public UserDTO getById(Long id){

        return userService.getById(id);

    }

}

关系:

复制代码
             接口


        UserApi


          ↑


          |

          |


UserController


          ↑


          |


UserService

七、blog-service如何调用?

blog-service:

引入:

java 复制代码
<dependency>

    <artifactId>
       user-info-api
    </artifactId>

</dependency>

然后:

创建Feign接口:

java 复制代码
@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 完全对应。

相关推荐
萧瑟余晖9 小时前
Java深入解析篇十七之Spring Security
java·开发语言·spring
Flittly14 小时前
【雕虫大技】Agent 动态 Skill 供应链安全加固(二):执行隔离沙箱实战
java·spring boot·spring
星期一研究室20 小时前
代码块:长文中的‘荧光浮标’!让「关键内容」无损高亮呈现
微服务·产品·设计
BUG指挥官1 天前
Sa-Token和Spring Security对比
java·后端·spring
geminigoth1 天前
Spring AI Alibaba 入门开发一(备份)
java·人工智能·spring
xbgRS2 天前
spring整合mybaits
java·spring·mybatis
ruleslol2 天前
静态依赖注入 VS 动态依赖查询
spring
墨雨晨曦882 天前
Spring AI总结
java·人工智能·spring
用户3126874877202 天前
Spring Boot 异常处理到底怎么玩的?从 DispatcherServlet 到全局兜底的全链路拆解
spring
星期一研究室2 天前
从“能看”到“爱看”:用色彩心理学打造人人爱看的的专业文档🧩
微服务·产品·设计