微服务-设置管理

[复制链接]
发表于 2025-11-16 03:27:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1.什么是设置管理

到现在为止我们已包办理了微服务干系的几个题目:

不外,现在依然另有几个题目须要办理:


  • 网关路由在设置文件中写死了,如果变动必须重启微服务
  • 某些业务设置在设置文件中写死了,每次修改都要重启服务
  • 每个微服务都有很多重复的设置,维护资本高
这些题目都可以通过同一的设置管理器服务办理。而Nacos不但仅具备注册中央功能,也具备设置管理的功能:


微服务共享的设置可以同一交给Nacos生存和管理,在Nacos控制台修改设置后,Nacos会将设置变动推送给干系的微服务,而且无需重启即可见效,实现设置热更新。
网关的路由同样是设置,因此同样可以基于这个功能实现动态路由功能,无需重启网关即可修改路由设置。
2.设置共享

我们可以把微服务共享的设置抽取到Nacos中同一管理,如许就不须要每个微服务都重复设置了。分为两步:


  • 在Nacos中添加共享设置
  • 微服务拉取设置
添加共享设置

以cart-service为例,我们看看有哪些设置是重复的,可以抽取的:
起首是jdbc干系设置:



留意这里的jdbc的干系参数并没有写死,比方:


  • 数据库ip:通过${hm.db.host:192.168.101.129}设置了默认值为192.168.150.101,同时答应通过${hm.db.host}来覆盖默认值
  • 数据库端口:通过${hm.db.port:3306}设置了默认值为3306,同时答应通过${hm.db.port}来覆盖默认值
  • 数据库database:可以通过${hm.db.database}来设定,无默认值

拉取共享设置

基于NacosConfig拉取共享设置代替微服务的当地设置.
刚开始我们的项目还没有举行拉取,是一个平凡的SpringBoot项目,内部加载设置文件是如许的一个序次:项目一启动,直接去读取application.yml,它会基于这些设置去完成ApplicationContext的初始化,我们知道ApplicationContext 是Spring的bean工厂大概叫整个Spring上下文大概叫容器.
一旦引入了设置管理,那如许的项目就跟传统的SpringBoot项目不一样了,它就会参加一个SpringCloud上下文,这个SpringCloud上下文在已启动会先实验去拉取Nacos设置,基于这些设置会去完成SpringCloud上下文的ApplicatonContext的初始化.当这个初始化完成了才会去完成SpringBoot的设置文件加载和SpringBoot上下文初始化.但是题目来了: 我们的Nacos地点是设置在application.yml文件中的,现在你一上来你就要去拉取Nacos设置还没有去读取application.yml呢,如许就产生抵牾.

基于这个题目,SpringCloud引出一个新的文件bootstrap.yml [引导设置文件],项目启动先读取这个文件,我们可以把Nacos地点设置到这个文件中

文件好创建,但是文件将来被拉取,加载设置,初始化,这个过程谁来处置处罚呢?


因此,微服务整合Nacos设置管理的步调如下:
1)引入依靠:
在cart-service模块引入依靠:
  1.   <!--nacos配置管理-->
  2.   <dependency>
  3.       <groupId>com.alibaba.cloud</groupId>
  4.       <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  5.   </dependency>
  6.   <!--读取bootstrap文件-->
  7.   <dependency>
  8.       <groupId>org.springframework.cloud</groupId>
  9.       <artifactId>spring-cloud-starter-bootstrap</artifactId>
  10.   </dependency>
复制代码
2)新建bootstrap.yaml
在cart-service中的resources目次新建一个bootstrap.yaml文件:

内容如下:
  1. spring:
  2.   application:
  3.     name: cart-service # 服务名称
  4.   profiles:
  5.     active: dev
  6.   cloud:
  7.     nacos:
  8.       server-addr: 192.168.150.101 # nacos地址
  9.       config:
  10.         file-extension: yaml # 文件后缀名
  11.         shared-configs: # 共享配置
  12.           - dataId: shared-jdbc.yaml # 共享mybatis配置
  13.           - dataId: shared-log.yaml # 共享日志日志配置
  14.           - dataId: shared-swagger.yaml # 共享日志日志配置
复制代码
3)修改application.yaml
由于一些设置挪到了bootstrap.yaml,因此application.yaml须要修改为:
  1. server:
  2.   port: 8082
  3. feign:
  4.   okhttp:
  5.     enabled: true # 开启OKHttp连接池支持
  6. hm:
  7.   swagger:
  8.     title: 购物车服务接口文档
  9.     package: com.hmall.cart.controller
  10.   db:
  11.     database: hm-cart
复制代码
重启服务,发现全部设置都见效了。
3.设置热更新

设置热更新: 当修改设置文件中的设置时,微服务无需重启即可使设置见效.

有很多的业务干系参数,将来大概会根据现实情况临时调解。比方购物车业务,购物车数目有一个上限,默认是10,对应代码如下:

现在这里购物车是写死的固定值,我们应该将其设置在设置文件中,方便后期修改。
但现在的题目是,即便写在设置文件中,修改了设置还是须要重新打包、重启服务才气见效。能不能不消重启,直接见效呢?
这就要用到Nacos的设置热更新本事了,分为两步:


  • 在Nacos中添加设置
  • 在微服务读取设置
添加设置到Nacos

起首,我们在nacos中添加一个设置文件,将购物车的上限数目添加到设置中:

留意文件的dataId格式:
   [服务名]-[spring.active.profile].[后缀名]
  文件名称由三部门构成:


  • 服务名:我们是购物车服务,以是是cart-service
  • spring.active.profile:就是spring boot中的spring.active.profile,可以省略,则全部profile共享该设置
  • 后缀名:比方yaml
这里我们直接使用cart-service.yaml这个名称,则不管是dev还是local情况都可以共享该设置。
设置内容如下:
  1. hm:
  2.   cart:
  3.     maxAmount: 1 # 购物车商品数量上限
复制代码
提交设置,在控制台能看到新添加的设置:

设置热更新

接着,我们在微服务中读取设置,实现设置热更新。
在cart-service中新建一个属性读取类:

  1. package com.hmall.cart.config;
  2. import lombok.Data;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. import org.springframework.stereotype.Component;
  5. @Data
  6. @Component
  7. @ConfigurationProperties(prefix = "hm.cart")
  8. public class CartProperties {
  9.     private Integer maxItems;
  10. }
复制代码
接着,在业务中使用该属性加载类:

重启后举行测试即可.
4.动态路由

动态路由是Nacos设置管理的一个应用,现在我们的路由不是动态的,而是写死在网关的设置文件中的,当网关启动的时间就会去加载设置文件路由信息,生存在内存中的一个路由表内里,着实就是一个缓存,那么下次有哀求直接读取缓存就可以了,进步速率.那么这也带来了一个题目,假设我们项目运行过程中,我们的路由信息须要发生变动,那这个时间光去改设置文件就不可了,由于它已经被缓存起来了,以是你必须去重启网关服务才行,但是网关但是整个服务的入口,它怎么能恣意停机呢?它停机可想而知对整个微服务会带来非常大的影响,以是我们想实现的结果是,我们改路由立马见效不消重启网关,这就是动态路由.

监听Nacos设置变动

在Nacos官网中给出了手动监听Nacos设置变动的SDK:
https://nacos.io/zh-cn/docs/sdk.html



这里核心的步调有2步:


  • 创建ConfigService,目的是毗连到Nacos
  • 添加设置监听器,编写设置变动的关照处置处罚逻辑
由于我们接纳了spring-cloud-starter-alibaba-nacos-config自动装配,因此ConfigService已经在com.alibaba.cloud.nacos.NacosConfigManager中自动创建好了:


这内里还提供了getConfigService()方法

终极代码:


  1. package com.hmall.gateway.routers;
  2. import com.alibaba.cloud.nacos.NacosConfigManager;
  3. import com.alibaba.nacos.api.config.listener.Listener;
  4. import com.alibaba.nacos.api.exception.NacosException;
  5. import lombok.RequiredArgsConstructor;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.stereotype.Component;
  8. import javax.annotation.PostConstruct;
  9. import java.util.concurrent.Executor;
  10. @Component
  11. @Slf4j
  12. @RequiredArgsConstructor
  13. public class DynamicRouteLoader {
  14.     private final NacosConfigManager nacosConfigManager;
  15.     private final String dataId = "gateway-routes.json";
  16.     private final String group = "DEFAULT_GROUP";
  17.     @PostConstruct //在这个bean初始化之后执行
  18.     public void initRouteConfigListener() throws NacosException {
  19.         //1.项目启动时,先拉取一个配置,并且添加配置监听器
  20.         String configInfo = nacosConfigManager.getConfigService().getConfigAndSignListener(dataId, group, 5000, new Listener() {
  21.             @Override
  22.             public Executor getExecutor() {//这里逻辑比较简单就不使用线程池了
  23.                 return null;
  24.             }
  25.             @Override
  26.             public void receiveConfigInfo(String configInfo) {
  27.                 //2.监听到配置变更,需要去更新路由表
  28.                 updateConfigInfo(configInfo);
  29.             }
  30.         });
  31.         //3.第一次读取到配置,也需要更新到路由表
  32.         updateConfigInfo(configInfo);
  33.     }
  34.     public void updateConfigInfo(String configInfo){
  35.         //TODO
  36.     }
  37. }
复制代码


  1. package com.hmall.gateway.routers;
  2. import cn.hutool.json.JSONUtil;
  3. import com.alibaba.cloud.nacos.NacosConfigManager;
  4. import com.alibaba.nacos.api.config.listener.Listener;
  5. import com.alibaba.nacos.api.exception.NacosException;
  6. import lombok.RequiredArgsConstructor;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.cloud.gateway.route.RouteDefinition;
  9. import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
  10. import org.springframework.stereotype.Component;
  11. import reactor.core.publisher.Mono;
  12. import javax.annotation.PostConstruct;
  13. import java.util.HashSet;
  14. import java.util.List;
  15. import java.util.Set;
  16. import java.util.concurrent.Executor;
  17. @Component
  18. @Slf4j
  19. @RequiredArgsConstructor
  20. public class DynamicRouteLoader {
  21.     private final NacosConfigManager nacosConfigManager;
  22.     private final RouteDefinitionWriter writer;
  23.     private final String dataId = "gateway-routes.json";
  24.     private final String group = "DEFAULT_GROUP";
  25.     private final Set<String> routeIds = new HashSet<>();
  26.     @PostConstruct //在这个bean初始化之后执行
  27.     public void initRouteConfigListener() throws NacosException {
  28.         //1.项目启动时,先拉取一个配置,并且添加配置监听器
  29.         String configInfo = nacosConfigManager.getConfigService().getConfigAndSignListener(dataId, group, 5000, new Listener() {
  30.             @Override
  31.             public Executor getExecutor() {//这里逻辑比较简单就不使用线程池了
  32.                 return null;
  33.             }
  34.             @Override
  35.             public void receiveConfigInfo(String configInfo) {
  36.                 //2.监听到配置变更,需要去更新路由表
  37.                 updateConfigInfo(configInfo);
  38.             }
  39.         });
  40.         //3.第一次读取到配置,也需要更新到路由表
  41.         updateConfigInfo(configInfo);
  42.     }
  43.     public void updateConfigInfo(String configInfo){
  44.         log.debug("监听到路由配置信息:{}",configInfo);
  45.         // 1.解析配置信息,转为RouteDefinition
  46.         List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);
  47.         //2.删除旧的路由表
  48.         for (String routeId : routeIds) {
  49.             writer.delete(Mono.just(routeId)).subscribe();
  50.         }
  51.         routeIds.clear();
  52.         //3.更新路由表
  53.         for (RouteDefinition routeDefinition : routeDefinitions) {
  54.             //3.1 更新路由表
  55.             writer.save(Mono.just(routeDefinition)).subscribe();//响应式编程处理方案
  56.             //3.2 记录路由id,便于下一次更新时删除
  57.             routeIds.add(routeDefinition.getId());
  58.         }
  59.     }
  60. }
复制代码
重启网关,恣意访问一个接口,比如 http://localhost:8080/search/list?pageNo=1&pageSize=1:

发现是404,无法访问。
接下来,我们直接在Nacos控制台添加路由,路由文件名为gateway-routes.json,范例为json:

  1. [
  2.     {
  3.         "id": "item",
  4.         "predicates": [{
  5.             "name": "Path",
  6.             "args": {"_genkey_0":"/items/**", "_genkey_1":"/search/**"}
  7.         }],
  8.         "filters": [],
  9.         "uri": "lb://item-service"
  10.     },
  11.     {
  12.         "id": "cart",
  13.         "predicates": [{
  14.             "name": "Path",
  15.             "args": {"_genkey_0":"/carts/**"}
  16.         }],
  17.         "filters": [],
  18.         "uri": "lb://cart-service"
  19.     },
  20.     {
  21.         "id": "user",
  22.         "predicates": [{
  23.             "name": "Path",
  24.             "args": {"_genkey_0":"/users/**", "_genkey_1":"/addresses/**"}
  25.         }],
  26.         "filters": [],
  27.         "uri": "lb://user-service"
  28.     },
  29.     {
  30.         "id": "trade",
  31.         "predicates": [{
  32.             "name": "Path",
  33.             "args": {"_genkey_0":"/orders/**"}
  34.         }],
  35.         "filters": [],
  36.         "uri": "lb://trade-service"
  37.     },
  38.     {
  39.         "id": "pay",
  40.         "predicates": [{
  41.             "name": "Path",
  42.             "args": {"_genkey_0":"/pay-orders/**"}
  43.         }],
  44.         "filters": [],
  45.         "uri": "lb://pay-service"
  46.     }
  47. ]
复制代码

无需重启网关,稍等几秒钟后,再次访问刚才的地点:

乐成了!
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表