Spring Cloud 微服务实战(二):改个配置还要重启服务?Nacos 配置中心 + OpenFeign 实战
Spring Cloud 微服务实战(二):改个配置还要重启服务?Nacos 配置中心 + OpenFeign 实战
个人主页:夏天拐跑了西瓜
专栏传送门:《大模型应用开发》、《Spring 生态全家桶体系化实战》
学习方向:Java 后端|AI‑Agent 大模型应用开发爱好者
⭐人生格言:路虽远,行则将至

本文是「Spring Cloud 微服务实战」系列的第二篇。在上一篇搭建好订单、库存服务的基础上,本文继续深入两个核心能力:一是 Nacos 配置中心,实现配置文件的集中管理与动态刷新;二是 OpenFeign,用声明式接口优雅地简化跨服务 HTTP 调用,并覆盖超时配置与底层客户端选型。
本文覆盖:Nacos 配置中心接入全流程(依赖引入 → 控制台创建配置 → bootstrap.yml 配置 → 动态刷新)、OpenFeign 声明式调用(依赖 → 接口定义 → 超时配置 → 底层客户端选型)、常见踩坑与版本差异说明。
适合读者:已搭建基础 Spring Cloud 项目、希望实现配置集中管理与服务间调用的开发者。
环境版本:Spring Boot 2.6.11、Spring Cloud 2021.0.4、Spring Cloud Alibaba 2021.0.4.0、Nacos 2.5.1、OpenFeign 3.x
系列文章导航
- 《Spring Cloud 微服务实战(一):还在硬编码服务地址?Nacos 注册中心从零搭建》
- 《Spring Cloud 微服务实战(二):改个配置还要重启服务?Nacos 配置中心 + OpenFeign 实战》(本篇)
- 《Spring Cloud 微服务实战(三):一个服务挂了,凭什么拖垮整个系统?Sentinel 限流熔断实战》
- 《Spring Cloud 微服务实战(四):每个请求都直连服务?你的集群缺一个 Gateway 门卫》

一、Nacos配置中心
1.0 前置条件
阅读本文前,请确保已完成系列第一篇的内容,即:
- 已搭建好 Spring Cloud 父工程(Spring Boot 2.6.11 + Spring Cloud 2021.0.4 + Spring Cloud Alibaba 2021.0.4.0)
- 已创建 order(订单)和 stock(库存)两个子服务
- 两个服务已注册到 Nacos 注册中心
- 已实现基于 Nacos 服务名的远程调用
如果你还没有完成上述步骤,建议先阅读《Spring Cloud 微服务实战(一):还在硬编码服务地址?Nacos 注册中心从零搭建》。
1.1 配置中心
在上一篇中,所有配置信息都存放在各服务自己的 application.yml 里。随着服务数量增多,这种方式会暴露出几个明显的问题,而配置中心正是针对这些问题设计的:
- 集中管理:服务集群化部署后,配置文件分散在不同服务器上,缺乏统一的管理入口;
- 环境隔离:从开发、测试、预发布到生产,需要维护多套环境的配置文件;
- 动态刷新:本地配置文件修改后必须重启服务才能生效,配置中心可以做到修改后立即生效;
- 权限控制:本地文本文件任何人都可以查看和修改,权限难以控制,配置中心提供了完善的权限体系;
- 版本记录:配置中心会记录每次变更的历史版本,便于追溯与回滚。
1.2 Nacos初体验(配置中心)
本节的目标:将 order 服务中 server.port=80 的配置迁移到 Nacos 中统一管理,使 order 服务启动时从 Nacos 读取该配置,最终以 80 端口正常启动。
实现步骤如下:
1、导入 Nacos 配置中心依赖
<!-- Nacos 配置中心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2、在 Nacos 控制台创建配置文件

3、在 order 的配置文件中指定 Nacos 地址及要加载的配置文件
spring:
application:
# 服务名,用于拼接 DataId
name: order
profiles:
# 环境名,用于拼接 DataId
active: study
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
# nacos 地址
server-addr: 127.0.0.1:8848
# 配置文件后缀,决定 DataId 格式
file-extension: yml
# DataId 拼接规则:${spring.application.name}-${spring.profiles.active}.${file-extension}
# 本例对应:order-study.yml
Nacos 配置中心默认按 ${spring.application.name}-${spring.profiles.active}.${file-extension} 的规则拼接 DataId,因此上面对应的配置文件名是 order-study.yml。
4、将 application.yml 重命名为 bootstrap.yml
配置中心的加载发生在应用上下文初始化之前,必须使用 bootstrap.yml 才能生效。

5、因版本变化,需补充 bootstrap 支持依赖
Spring Cloud 2020.x 之后,bootstrap 上下文默认关闭,需要显式引入:
<!-- bootstrap 上下文支持依赖(Spring Cloud 2020.x 后必须引入) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
6、启动测试,观察日志确认配置加载成功

1.3 命名空间和分组(了解)
配置中心对命名空间与分组的使用方式与注册中心完全一致,此处不再展开原理,直接演示效果。
先在 dev 命名空间下创建 DEV_GROUP 分组的配置文件:

然后在 bootstrap.yml 中指定命名空间 ID 与分组:
spring:
application:
# 服务名
name: order
profiles:
# 环境名
active: dev
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
# nacos 地址
server-addr: 127.0.0.1:8848
# 配置文件后缀
file-extension: yml
# 命名空间 ID(注意是 UUID,不是名称)
namespace: 06173ada-fb39-47b3-8551-7265a5177770
# 分组名称
group: DEV_GROUP
注意:命名空间配置填写的是命名空间 ID(一串 UUID),而不是命名空间名称。
1.4 配置动态刷新
动态刷新的目标:当 Nacos 中的配置发生变更时,服务无需重启即可读取到最新值。
先准备一个测试接口,读取 Nacos 配置中的 info 属性并返回:
@RestController
public class OrderController {
// 从 Nacos 配置中心读取 info 属性,默认值为 empty
@Value("${info:empty}")
private String info;
@GetMapping("/order/info")
public String info() {
return info;
}
}
此时修改 Nacos 中的配置后再次访问接口,返回值不会变化:


要开启动态刷新,只需在使用该配置的类上追加一个注解:
// 添加 @RefreshScope 注解,开启配置动态刷新
@RestController
@RefreshScope
public class OrderController {
@Value("${info:empty}")
private String info;
@GetMapping("/order/info")
public String info() {
return info;
}
}
添加 @RefreshScope 注解后,再次测试,Nacos 中修改配置即可实时生效:

二、OpenFeign
2.1 OpenFeign介绍
OpenFeign 是 Spring Cloud 提供的声明式 RPC 调用框架(注意它属于 Spring Cloud,而非 Alibaba 组件)。Alibaba 生态中与之对应的是 Dubbo,两者定位相同,区别在于通信协议:
- Dubbo 使用自研的 Dubbo 协议;
- OpenFeign 基于 HTTP 协议。
OpenFeign 的核心价值是简化 Java 中 HTTP 请求的编写过程,让远程调用代码具备更好的可维护性。它与 Sentinel、Nacos、Hystrix、LoadBalancer 等组件都可以低成本整合。
实现原理上,OpenFeign 基于接口(interface)封装,运行时生成代理对象完成实际调用——编写方式与单体项目中调用本地接口完全一致,这也是它最大的优势。
2.2 OpenFeign的初体验
按官方文档的步骤接入,共四步:
1、导入依赖
<!-- OpenFeign 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、启动类追加注解
// 启动类添加 @EnableFeignClients 注解,开启 Feign 客户端扫描
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
3、编写 OpenFeign Client 接口,与目标服务的接口定义保持映射
package com.study.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
// @FeignClient 指定目标服务名(Nacos 中注册的服务名)
@FeignClient("stock")
public interface StockClient {
// 路径和方法签名应与目标服务的 Controller 保持一致
// 建议直接从 stock 服务的 Controller 中复制
@GetMapping("/stock/test")
String test();
}
建议:接口上的路径与方法签名直接从目标服务的 Controller 中复制,避免手写产生偏差。
4、在 order 服务中编写测试接口验证
@RestController
public class OrderController {
// 注入 Feign 客户端,像调用本地方法一样发起远程调用
@Autowired
private StockClient stockClient;
// 基于 OpenFeign 调用 stock 服务
@GetMapping("/order/feign")
public String feign() {
String result = stockClient.test();
return result;
}
}
注入 StockClient 后像调用本地方法一样发起远程调用,访问 /order/feign 验证效果:


2.3 OpenFeign配置
2.3.1 OpenFeign的超时配置
官方文档中,OpenFeign 的超时配置只有两项:
connectTimeoutprevents blocking the caller due to the long server processing time.readTimeoutis applied from the time of connection establishment and is triggered when returning the response takes too long.
两者的定位不同:
- connectTimeout:客户端与服务端建立 TCP 连接的超时时间,一般保持默认即可;
- readTimeout:从请求发出到收到响应的超时时间,是实际调优中最常配置的项。
验证方式:让 stock 服务的接口休眠一段时间,观察达到超时阈值后的表现。order 服务配置如下:
feign:
client:
config:
stock: # 针对 stock 服务的配置
readTimeout: 1000 # 响应超时时间 1s,超过则直接报错
超时后抛出的异常:

注意版本差异:早期版本中 OpenFeign 的默认超时时间是 1 秒,而当前版本的默认值已放宽到 5 秒以上。另外首次请求可能因客户端初始化而偏慢,属于正常现象。
除按服务配置外,OpenFeign 还支持全局默认配置,两者同时存在时按服务配置的优先级更高:
feign:
client:
config:
default: # 全局默认配置,优先级低
read-timeout: 2000
stock: # 针对 stock 服务的细粒度配置,优先级高
readTimeout: 6000
2.3.2 OpenFeign的底层技术
当前版本的 OpenFeign 默认使用 HttpClient4 作为底层 HTTP 客户端,也可以通过配置切换为 OkHttp 或 HC5(HttpClient5),三选一。
三种客户端的对比如下:
| 对比维度 | HttpClient4 | OkHttp | HC5 |
|---|---|---|---|
| 协议支持 | 基础 HTTP/1.1 | HTTP/2 支持更完善 | HTTP/2 支持完善 |
| 性能 | 良好 | 略优 | 略优 |
| 维护方 | Apache | Square | Apache |
| 异步支持 | ✓ | ✓ | ✓ |
| 推荐度 | 默认,够用即可 | 推荐,社区活跃 | 推荐,Apache 新一代 |
配置方式:
默认使用 HttpClient4:
feign:
httpclient:
enabled: true # 默认使用 HttpClient4
切换为 HC5:
feign:
httpclient:
hc5:
enabled: true # 启用 HC5 作为底层客户端
切换为 OkHttp:
feign:
okhttp:
enabled: true # 启用 OkHttp 作为底层客户端
三、常见问题与踩坑总结
在实际开发中,以下是容易踩的坑,建议提前了解:
1. 配置修改后未生效
- 原因:忘记在使用配置的类上添加
@RefreshScope注解 - 解决:给需要动态刷新配置的 Controller 或 Bean 加上注解
2. bootstrap.yml 不加载
- 原因:Spring Cloud 2020.x 之后默认关闭 bootstrap 上下文
- 解决:显式引入
spring-cloud-starter-bootstrap依赖
3. 命名空间配置不生效
- 原因:在
namespace字段填了命名空间名称,而非 ID(UUID) - 解决:去 Nacos 控制台复制命名空间的 ID(一串 UUID)
4. OpenFeign 首次调用慢
- 原因:客户端首次调用时需要初始化连接池、加载配置,属于正常现象
- 解决:无需处理,后续调用会恢复正常
5. DataId 拼接规则混淆
- 规则:
${spring.application.name}-${spring.profiles.active}.${file-extension} - 示例:
order-study.yml - 注意:如果
spring.profiles.active未配置,则拼接为order.yml
6. 超时配置不生效
- 原因:同时配置了
default和按服务名配置,按服务名优先级更高 - 解决:确认配置层级,按服务名配置会覆盖全局默认
四、总结
本文围绕微服务的配置管理与远程调用两大主题,核心收获如下:
- Nacos 配置中心实现配置文件集中管理,支持命名空间与分组做多环境隔离。
- 配合
@RefreshScope注解实现配置动态刷新,修改配置无需重启服务。 - OpenFeign 通过
@FeignClient声明式接口简化跨服务 HTTP 调用,代码结构更清晰。 - 掌握 Feign 超时的全局与按服务配置,以及 HttpClient4、HC5、OkHttp 三种底层客户端的切换。
下一篇预告:Sentinel 限流、熔断与降级,解决微服务架构中的服务雪崩问题。
感兴趣的同学记得 点赞 + 关注,第一时间获取更新通知!
更多推荐

所有评论(0)