Spring Cloud Alibaba Nacos 保姆级入门教程 —— 注册中心  配置中心全搞定
菜鸟的修仙笔记一边学一边记有不对的地方欢迎大佬指正前言最近在学 Spring Cloud 微服务体系今天磕了一下午的 Nacos从注册中心到配置中心从服务发现到负载均衡再到配置自动刷新总算把核心链路捋顺了。趁热打铁写篇博客狠狠真实一下自己。先放一张整体架构图心里有个谱┌──────────────────────────────────────────────────────────┐ │ Nacos Server │ │ ┌─────────────────────┐ ┌───────────────────────────┐ │ │ │ 注册中心 │ │ 配置中心 │ │ │ │ (服务注册 发现) │ │ (配置管理 动态刷新) │ │ │ └──────┬──────────────┘ └────────────┬──────────────┘ │ └─────────┼──────────────────────────────┼─────────────────┘ │ │ ┌─────▼─────┐ ┌─────▼─────┐ │ order服务 │ │ order服务 │ │ 注册到Nacos│ │ 拉取配置 │ │ 发现user服务│ │ 监听变化 │ └─────┬─────┘ └───────────┘ │ ┌─────▼─────┐ │ LoadBal │ │ ancer │ │ 负载均衡 │ └───────────┘一、注册中心1.1 什么是注册中心微服务架构下服务实例的网络地址是动态变化的扩缩容、故障转移不可能把 IP 写死在代码里。注册中心就是所有服务的通讯录服务启动时向注册中心注册自己的地址服务调用时从注册中心发现目标服务的地址列表1.2 引入 Nacos 注册中心第一步加依赖dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency第二步配地址spring: cloud: nacos: discovery: server-addr: localhost:8848 # Nacos 服务地址 application: name: order-service # 服务名注册时以此作为标识第三步启动类加注解SpringBootApplication EnableDiscoveryClient // 开启服务发现 public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } }启动后去 Nacos 控制台localhost:8848/nacos→ 服务管理 → 服务列表就能看到order-service了。二、服务调用 负载均衡注册只是第一步真正关键的是怎么调用。2.1 RestTemplate LoadBalanced最经典的方式用RestTemplate发起 HTTP 调用加LoadBalanced注解开启负载均衡Configuration public class RestTemplateConfig { ​ Bean LoadBalanced // 核心让 RestTemplate 拥有负载均衡能力 public RestTemplate restTemplate() { return new RestTemplate(); } }调用时直接用服务名代替 IP:端口Service public class OrderService { ​ Autowired private RestTemplate restTemplate; ​ public User getUserById(Long id) { // 注意URL 里写的是服务名不是 IP String url http://user-service/user/ id; return restTemplate.getForObject(url, User.class); } }LoadBalanced做了什么事restTemplate.getForObject(http://user-service/user/1, User.class) │ ▼ ┌─────────────────┐ │ 拦截器拦截请求 │ ← LoadBalancerInterceptor │ 从 URL 中提取服务名│ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 从 Nacos 获取 │ ← NacosServerList │ user-service 的 │ │ 所有实例列表 │ │ [192.168.1.1:8081│ │ 192.168.1.2:8082│ │ 192.168.1.3:8083]│ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 负载均衡算法选择 │ │ 一个实例 │ │ → 192.168.1.2:8082│ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 替换 URL 为真实地址│ │ http://192.168.1.2│ │ :8082/user/1 │ └─────────────────┘2.2 LoadBalancerClient除了用LoadBalanced注解也可以直接注入LoadBalancerClient手动选择实例Service public class OrderService { ​ Autowired private LoadBalancerClient loadBalancerClient; ​ Autowired private RestTemplate restTemplate; ​ public User getUserById(Long id) { // 手动选择服务实例 ServiceInstance instance loadBalancerClient.choose(user-service); // 拿到真实的 host:port String url String.format(http://%s:%s/user/%s, instance.getHost(), instance.getPort(), id); return restTemplate.getForObject(url, User.class); } }两种方式对比方式优点缺点LoadBalanced代码简洁注解驱动不够灵活无法自定义选择逻辑LoadBalancerClient灵活可以拿到实例元数据代码量稍多需手动拼接 URL三、配置中心注册中心搞定了服务在哪的问题配置中心解决的是配置怎么管的问题。3.1 为什么需要配置中心痛点场景10 个微服务每个都有application.yml改个数据库地址要改 10 个文件改了配置文件要重启服务才能生效敏感信息密码散落在各个配置文件里不安全配置中心就是把所有配置统一管理、动态刷新的地方。3.2 接入 Nacos 配置中心第一步加依赖dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId /dependency第二步配 Nacos 地址spring: application: name: order-service cloud: nacos: config: server-addr: localhost:8848第三步在 Nacos 控制台创建配置进入 Nacos → 配置管理 → 配置列表 → 创建配置字段值说明Data IDorder-service.yaml默认规则${spring.application.name}.${file-extension}GroupDEFAULT_GROUP默认分组配置内容见下方# Nacos 控制台里的配置内容 user: name: 张三 age: 183.3 使用 spring.config.import 导入配置Spring Boot 2.4 推荐用spring.config.import导入 Nacos 配置# application.yml spring: config: import: - nacos:order-service.yaml # 导入 Nacos 配置 - nacos:common.yaml # 可以导入多个 cloud: nacos: config: server-addr: localhost:8848引入多个>order-service.yaml ← 订单服务独有配置 common.yaml ← 公共配置各服务共享 order-service-dev.yaml ← 开发环境配置四、配置取值 自动刷新4.1 Value RefreshScopeRestController RefreshScope // 关键标记这个 Bean 的 Value 字段需要动态刷新 public class TestController { Value(${user.name}) private String userName; Value(${user.age}) private Integer age; GetMapping(/user-info) public String getUserInfo() { return 姓名 userName 年龄 age; } }验证自动刷新访问/user-info→姓名张三年龄18去 Nacos 控制台把user.age改成20发布再次访问/user-info→姓名张三年龄20✅ 不用重启原理简述Nacos 配置变更 │ ▼ Nacos Client 收到通知 │ ▼ Spring Cloud 刷新 Context │ ▼ RefreshScope 标注的 Bean 被重建 │ ▼ Value 重新从 Environment 取值 → 新值生效4.2 ConfigurationProperties 批量绑定当配置项很多时一个个Value太累了用ConfigurationProperties批量绑定Nacos 配置user: name: 张三 age: 18 addr: province: 广东 city: 深圳配置类Component ConfigurationProperties(prefix user) // 绑定 user 开头的所有配置 RefreshScope // 同样支持自动刷新 Data public class UserProperties { private String name; private Integer age; } }使用RestController public class TestController { Autowired private UserProperties userProperties; GetMapping(/user-info) public String getUserInfo() { return userProperties.getName() - userProperties.getAddr().getProvince(); } }Value vs ConfigurationProperties 对比维度ValueConfigurationProperties单个属性✅ 方便也能用但杀鸡用牛刀批量绑定❌ 要写很多个✅ 一个 prefix 搞定嵌套对象❌ 不支持✅ 自动映射松散绑定❌ 不支持✅user-name→userName数据校验❌ 不支持✅ 可以用Validated自动刷新需要RefreshScope需要RefreshScope推荐单两个属性用Value多了就用ConfigurationProperties。4.3 NacosConfigManager 监听配置变化前面两种方式都是被动刷新如果你想主动感知配置变化并做一些处理比如重建连接池可以用NacosConfigManager注册监听器Component public class ConfigListenerDemo { Autowired private NacosConfigManager nacosConfigManager; PostConstruct public void init() { // 获取 ConfigService ConfigService configService nacosConfigManager.getConfigService(); try { // 添加监听器dataId, group, 回调 configService.addListener(order-service.yaml, DEFAULT_GROUP, new Listener() { Override public Executor getExecutor() { return Executors.newSingleThreadExecutor(); } Override public void receiveConfigInfo(String configInfo) { // configInfo 就是最新的配置内容yaml 原文 System.out.println(配置变了新配置\n configInfo); // 在这里做一些自定义逻辑 // 比如重建数据库连接池、清空缓存等 onConfigChanged(configInfo); } }); } catch (NacosException e) { e.printStackTrace(); } } private void onConfigChanged(String newConfig) { // 自定义处理逻辑 } }五、扩展配置隔离 环境切换5.1 配置的三级隔离Nacos 通过三个维度实现配置隔离Namespace命名空间 └── Group分组 └── Data ID配置集ID └── 具体配置内容5.2 Namespace —— 环境隔离典型用法用 namespace 区分开发/测试/生产环境。spring: cloud: nacos: config: server-addr: localhost:8848 namespace: dev-env-id-xxxx # 用 namespace 的 ID不同 namespace 的配置完全隔离dev 环境看不到 prod 的配置。5.3 Group —— 微服务分组同一个 namespace 下用 group 对不同微服务做逻辑分组Group: ORDER_GROUP ├── order-service.yaml └── order-db.yaml Group: USER_GROUP ├── user-service.yaml └── user-db.yaml spring: cloud: nacos: config: group: ORDER_GROUP # 指定分组5.4 Data ID —— 配置集拆分利用>order-service.yaml # 主配置 order-service-datasource.yaml # 数据源配置 order-service-cache.yaml # 缓存配置 order-service-mq.yaml # 消息队列配置这样改造数据源时只改*-datasource.yaml不会误触其他配置。5.5 优先配置优先级由低到高共享配置shared-configs扩展配置extension-configs应用专属配置${spring.application.name}.yaml应用环境配置${spring.application.name}-${profile}.yaml优先级高的会覆盖优先级低的同名配置这就是近者优先原则。六、完整 Demo 流程回顾把今天学的串起来实现一个完整调用链路User 请求 GET /order/1 │ ▼ ┌─────────────┐ 2. 从 Nacos 注册中心 │ order-service│ ◄─── 发现 user-service 的实例列表 └──────┬──────┘ │ 1. order-service 启动时 │ 从 Nacos 配置中心拉取配置 │ 注册自己到 Nacos │ │ 3. 使用 LoadBalanced RestTemplate │ 或 LoadBalancerClient │ 负载均衡选择一个 user-service 实例 │ ▼ ┌─────────────┐ │ user-service │ │ 实例 2 │ ◄─── 4. 实际发起 HTTP 调用 └─────────────┘ │ │ 5. user-service 处理请求 │ 读取的配置如果被修改 │ RefreshScope 自动刷新 │ ▼ 返回结果给 order-service → 返回给 User关键依赖!-- 注册中心 -- dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency !-- 配置中心 -- dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId /dependency总结今天学的内容其实就两条主线注册中心配置中心核心问题服务在哪配置怎么管关键注解EnableDiscoveryClient、LoadBalancedRefreshScope、ConfigurationProperties服务调用RestTemplate/LoadBalancerClient-负载均衡轮询 → 可自定义-配置刷新-Value刷新 /NacosConfigManager监听隔离体系namespace → group → serviceNamenamespace → group → dataIdNacos 注册中心 配置中心

相关新闻