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 完全对应。

相关推荐
xexpertS6 小时前
分布式系统过载治理:如何通过较小服务控制请求节奏
微服务·自动化
yio_yin6 小时前
Spring事务管理(数据一致性)
数据库·sql·spring
dear_bi_MyOnly7 小时前
【SpringBoot配置文件】
java·spring boot·后端·学习·spring·java-ee·学习方法
our_times8 小时前
2026年Java开发者破局指南:Spring AI 2.0 与 Agent 开发实战
java·人工智能·spring
wear工程师9 小时前
@Transactional 标了却没开事务?先看这次调用有没有经过代理
java·spring
野蛮人6号10 小时前
黑马天机学堂系列问题之域名无法正常使用
java·spring cloud·天机学堂
吴声子夜歌11 小时前
MongoDB 4.x——微服务入门
java·mongodb·微服务
静水楼台x12 小时前
spring security
java·数据库·spring
阿标在干嘛13 小时前
从HTTP到WebSocket:招投标信息实时推送系统的协议选型与架构设计
大数据·微服务·架构