当前位置: 首页 > 科技观察

服务配置:实现动态刷新和配置共享

时间:2023-03-19 13:00:32 科技观察

基于阿里开源的Sentinel,实现服务限流和容错,详细介绍了Sentinel的核心技术和配置规则。简单介绍了服务网关,简单说明了SpringCloudGateway的核心架构。项目中还集成了SpringCloudGateway网关,实现通过网关访问后端微服务。同时,基于Sentinel与SpringCloudGateway的集成,实现了网关的限流功能,详细介绍了SpringCloudGateway的核心技术。在链接跟踪章节中,我们简单介绍了分布式链接跟踪技术和解决方案,然后在项目中集成Sleuth实现链接跟踪,并利用Sleuth集成ZipKin实现分布式链接跟踪的可视化。在消息服务章节,我们介绍了MQ的使用场景、引入MQ后的注意事项以及MQ选型对比,在项目中集成了RocketMQ,介绍了RocketMQ的核心技术。在服务配置章节,我们首先介绍了服务配置和Nacos作为配置中心的概念,并在项目中集成了Nacos配置中心。接下来基于Nacos实现动态刷新和配置共享。本章概述注意:本章测试每个案例时,都需要启动Nacos、Sentinel、ZipKin和RocketMQ。细心的朋友可能已经发现,之前我们将微服务的配置放到了Nacos中,但是此时如果在Nacos中修改了配置,程序是读取不到修改后的配置的。因此,我们需要实现动态刷新的功能。“注:为了描述简单,这里以用户微服务为例,其他微服务的实现方法相同。”修改Nacos配置修改Nacos中server-user-dev.yaml的配置,在server-user-dev.yaml配置中添加如下内容。作者:姓名:冰河如下图。点击发布后,会弹出如下提示。只需单击“确认”即可发布。通过IOC容器获取Nacos配置(1)在用户微服务shop-user的io.binghe.shop.user.controller包下新建NacosController类,在NacosController类中注入org.springframework.context.ConfigurableApplicationContext类,并通过ConfigurableApplicationContext获取到系统环境变量中,从环境变量中获取author.name属性的值,也就是我们在Nacos中配置的作者姓名,如下图。/***@authorbinghe*@version1.0.0*@description从Nacos获取配置项*/@Slf4j@RestControllerpublicclassNacosController{@AutowiredprivateConfigurableApplicationContextcontext;@GetMapping("/nacos/test")publicStringnacosTest(){StringauthorName=context.getEnvironment().getProperty("author.name");log.info("获取到的作者姓名为:{}",authorName);返回作者姓名;}}(2)启动用户微服务和网关服务,在浏览器中输入http://localhost:10001/server-user/user/nacos/test,如下图。可以看到可以正确读取Nacos中的配置信息。(3)修改Nacos中server-user-dev.yaml的配置,将author.name的值改为binghe001,如下图。单击发布。(4)发布后,不重启用户微服务和网关服务,在浏览器刷新http://localhost:10001/server-user/user/nacos/test链接,发现读取的信息变成了binghe001,如下。可以看到Nacos中修改的配置是可以通过IOC容器读取的。通过注解获取Nacos配置(1)在用户微服务shop-user的io.binghe.shop.user.controller.NacosController类中添加@RefreshScope注解,将Nacos中author.name的值注入到NacosController类中,并通过接口获取注入的Nacos中的author.name值,如下图。/***@authorbinghe*@version1.0.0*@description从Nacos获取配置项*/@Slf4j@RefreshScope@RestControllerpublicclassNacosController{@AutowiredprivateConfigurableApplicationContextcontext;@Value("${author.name}")privateStringnacosAuthorName;@GetMapping("/nacos/test")publicStringnacosTest(){StringauthorName=context.getEnvironment().getProperty("author.name");log.info("获取到的作者姓名为:{}",authorName);返回作者姓名;}@GetMapping("/nacos/name")publicStringnacosName(){log.info("从Nacos获取的作者姓名为:{}",nacosAuthorName);返回nacosAuthorName;}}(2)启动用户微服务和网关服务,在浏览器中输入http://localhost:10001/server-user/user/nacos/name,如下图。(3)修改Nacos中server-user-dev.yaml的配置,将author.name的值改为binghe002,如下图。(4)发布后,不重启用户微服务和网关服务,在浏览器刷新http://localhost:10001/server-user/user/nacos/name链接,发现读取的信息变成了binghe002,如下。说明一下,使用注解的方式也可以读取Nacos中更新的配置信息。注意:虽然可以通过IOC容器和注解来读取Nacos中更新的配置信息,但是在实际项目中,还是建议使用注解来获取Nacos中更新的配置信息。实现配置共享一般来说,开发一个项目的过程会包括:开发环境、测试环境、预发布环境、生产环境。每个环境中的大部分配置是相同的,少数配置不同。如果我们能够把大部分相同的配置抽取出来,在不同的环境中共享同一个微服务,就可以大大降低我们的维护成本。此外,如果使用相同的技术栈,每个微服务的大部分配置可能都是相同的。如果我们将这些相同的配置提取出来,共享给各个微服务,维护成本可以进一步降低。因此,配置共享的实现可以从“单服务多环境配置和多服务配置”两个角度考虑。单服务多环境共享实现单个微服务在多个不同环境的配置共享是比较简单的,只要在Nacos中配置一个DataID为spring.application.name的配置文件即可,这个微服务是在所有环境中使用public配置即可。(1)在Nacos中新建配置,以server-user.yaml为DataID,复制各环境用户微服务的通用配置,如下。其中,我们假设用户微服务在多环境下的通用配置如下。服务器:端口:8060servlet:上下文路径:/userspring:应用程序:名称:服务器用户数据源:驱动程序类名称:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://localhost:3306/shop?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai用户名:root密码:root平台:mysqltype:com.alibaba.druid.pool.DruidDataSource#下面是连接池的补充设置,应用toallabove在数据源中#初始化大小,最小,最大initialSize:10minIdle:5maxActive:20#配置等待连接超时的时间maxWait:60000#配置间隔多长时间进行检测检测需要关闭的空闲连接,单位毫秒timeBetweenEvictionRunsMillis:3600000#配置一个连接在池中的最小存活时间,单位毫秒minEvictableIdleTimeMillis:3600000validationQuery:select1fromdualtestWhileIdle:truetestOnBorrow:falsetestOnReturn:false#打开PSCache并指定每个连接的PSCachepoolPreparedStatements:truemaxPoolPreparedStatementPerConnectionSize:20maxOpenPreparedStatements:20#配置用于监视和统计拦截的过滤器。去掉后,监控界面sql就不能用来统计了。'wall'用于防火墙过滤器:statcloud:nacos:discovery:server-addr:127.0.0.1:8848http:encoding:enabled:truecharset:UTF-8force:truemybatis-plus:global-config:db-配置:id类型:自动字段策略:非空表下划线:真数据库类型:oracle逻辑删除值:1逻辑不删除值??:0映射器位置:类路径:/映射器/*.xml配置:jdbc-type-for-null:'null'rocketmq:name-server:127.0.0.1:9876点击Publish(2)上传Nacos中的用户微服务的配置server-user-dev.yaml开发环境修改如下图。作者:姓名:binghe_dev如下所示。单击发布。(3)在Nacos中添加测试环境用户微服务的配置server-user-test.yaml。配置的主要内容如下。作者:姓名:binghe_test如下。单击发布。(4)此时Nacos中的配置如下。(5)查看用户微服务中bootstrap.yml文件的配置,如下图。spring:application:name:server-usercloud:nacos:config:server-addr:127.0.0.1:8848file-extension:yamlgroup:user_groupprofiles:active:dev可以看到,此时配置在bootstrap.yml文件中environment为dev,表示开发环境。(6)启动用户微服务和网关服务,在浏览器中输入http://localhost:10001/server-user/user/nacos/name,如下图。可见Nacos中server-user-dev.yaml配置中author.name的值是正确获取的。(7)在用户微服务的bootstrap.yml文件中修改环境变量进行测试,如下图。spring:profiles:active:test(8)重启用户微服务,在浏览器中输入http://localhost:10001/server-user/user/nacos/name,如下图。可见Nacos中server-user-test.yaml配置中author.name的值是正确获取的。总结一下:我们正确实现了单个微服务的公共配置在多个不同环境下的共享运行。多服务配置共享实现不同微服务之间的通用配置共享也比较简单。在Nacos中定义一个公共配置,然后将其导入到当前配置中。具体实现步骤如下。(1)在Nacos中新建配置,DataID为server-all.yaml。配置的主要内容是用户微服务、商品微服务和订单微服务的通用配置,如下图。弹簧:数据源:驱动程序类名称:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://localhost:3306/shop?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai用户名:rootpassword:rootplatform:mysqltype:com.alibaba.druid.pool.DruidDataSource#以下是连接池的补充设置,适用于以上所有数据源#初始大小,最小和最大initialSize:10minIdle:5maxActive:20#配置等待获取连接超时的时间maxWait:60000#配置检测空闲连接需要关闭的时间间隔,单位毫秒timeBetweenEvictionRunsMillis:3600000#配置连接在pool中的最小存活时间,单位为毫秒minEvictableIdleTimeMillis:3600000validationQuery:select1fromdualtestWhileIdle:truetestOnBorrow:falsetestOnReturn:false#开启PSCache,并指定PSC的大小acheoneachconnectionpoolPreparedStatements:truemaxPoolPreparedStatementPerConnectionSize:20maxOpenPrepared20#拦截的配置监控:maxOpenPrepared20filters,去掉后监控接口sql不能统计,'wall'用于防火墙filters:statcloud:nacos:di发现:服务器地址:127.0.0.1:8848http:编码:启用:true字符集:UTF-8force:truemybatis-plus:global-config:db-config:id-type:autofield-strategy:not-empty表下划线:真数据库类型:oracle逻辑删除值:1逻辑不删除值??:0映射器位置:类路径:/映射器/*.xml配置:jdbc-type-for-null:'null'具体配置如下,点击发布,接下来修改Nacos中各个微服务的配置,删除各个微服务配置中的通用配置。(2)修改Nacos中server-user.yaml的配置,修改后的配置如下。server:port:8060servlet:context-path:/userspring:application:name:server-userrocketmq:name-server:127.0.0.1:9876具体如下。单击发布。(3)修改Nacos中server-product-dev.yaml的配置,修改后的配置如下。server:port:8070servlet:context-path:/productspring:application:name:server-product如下。单击发布。(4)修改Nacos中server-order-dev.yaml的配置,修改后的配置如下。服务器:端口:8080tomcat:最大线程数:20servlet:上下文路径:/orderspring:应用程序:名称:服务器订单云:哨兵:传输:端口:9999仪表板:127.0.0.1:8888web-context-unify:falsefeign:sentinel:enabled:truerocketmq:name-server:127.0.0.1:9876producer:group:order-group如下。单击发布。(5)修改用户微服务shop-user中的bootstrap.yml文件,修改后的配置如下。spring:application:name:server-usercloud:nacos:config:server-addr:127.0.0.1:8848file-extension:yamlgroup:user_groupshared-configs[0]:data_id:server-all.yaml组:all_group刷新:trueprofiles:active:dev(6)修改商品微服务shop-product中的bootstrap.yml文件,修改后的配置如下。spring:application:name:server-productcloud:nacos:config:server-addr:127.0.0.1:8848file-extension:yamlgroup:product_groupshared-configs[0]:data_id:server-all.yamlgroup:all_group刷新:trueprofiles:active:dev(7)修改订单microserviceshop-order中的bootstrap.yml文件,修改后的配置如下。spring:application:name:server-ordercloud:nacos:config:server-addr:127.0.0.1:8848file-extension:yamlgroup:order_groupshared-configs[0]:data_id:server-all.yamlgroup:all_grouprefresh:trueprofiles:active:dev(8)分别启动用户微服务、商品微服务、订单微服务和服务网关,在浏览器1中输入localhost:10001/server-order/order/submit_order?userId=1001&productId=1001&count=,如如下所示。可见结果信息在浏览器中正确输出。查看每一个微服务也会打印出相关的日志,如下图。用户微服务会打印出如下信息。获取到的用户信息为:{"address":"Beijing","id":1001,"password":"c26be8aaf53b15054896983b43eb6a65","phone":"13212345678","username":"binghe"}用户微服务收到了订单信息:{"address":"Beijing","id":15235872727371776,"phone":"13212345678","totalPrice":2399.00,"userId":1001,"username":"binghe"}产品微服务将打印出以下信息。获取到的商品信息为:{"id":1001,"proName":"Huawei","proPrice":2399.00,"proStock":9999}更新商品库存传递的参数为:商品id:1001,采购数量:1订单微服务会打印出如下信息提交订单时传入的参数:{"count":1,"empty":false,"productId":1001,"userId":1001}网关服务会打印出如果库存扣除成功,则显示以下信息。执行前置过滤逻辑执行后置过滤逻辑访问接口主机:localhost访问接口端口:10001访问接口URL:/server-order/order/submit_order访问接口URL参数:userId=1001&productId=1001&count=1访问时长interface:863ms这说明我们的项目已经成功集成了Nacos的配置中心,实现了配置的动态刷新和共享。