1、大咖寄语作为 Spring Cloud 的早期玩家,见证了 Spring Cloud 家族的成长与壮大。在Netflix 体系不再继续提供新特性更新的大背景之下,Spring Cloud Alibaba 的出现,不仅提供了更符合中国开发者使用习惯的组件,也为 Spring Cloud 生态的其他使用者提供了更丰富的组件选择,承接了因 Netflix 体系不再更新导致的发展活力问题。相信在未来Spring Cloud Alibaba 获得更多开发者的亲睐与应用,这也将成为 Java 开发者必不可少的技能之一。程序猿 DDSpring Cloud 微服务实战作者Spring Cloud Aliba
2、ba 脱胎于内部中间件,经受了阿里多年海量业务场景的考验,是目前最成熟、功能最丰富也最有前景的 Spring Cloud 实现。希望Spring CloudAlibaba 从入门到实战电子书的发布有助于大家更加快速地上手,指导大家在项目中快速落地。周立(大目)Spring Cloud 与 Docker 微服务架构实战作者目录大咖寄语3基础知识篇5分布式配置26服务注册与发现54分布式服务调用74服务熔断和限流89分布式消息(事件)驱动107分布式事务1135基础知识篇基础知识篇前言前言近些年随着云技术的发展,越来越多的用户选择使用云技术来代替将传统的 IT 基础设施。在云技术发展的早期,业界的
3、关注点集中在虚拟化、分布式、存储等 Iaas 方面的技术。但是随着“云原生”概念的提出,大家的注意力开始转移到如何构建更加适合云环境运行的应用上来。“什么样的架构才是适合在云环境中运行”是一个非常大的问题,在此先不展开讨论,而是到 CNCF 对云原生的定义中寻找答案:云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。从上文的定义中可以发现
4、微服务”在云原生技术中占有这非常重要的位置。在jakarta.ee 2019 年的调研报告中也印证了这一点,超过 40%公司选择采用微服务架构来构建云上系统:基础知识篇 SOA 面向服务架构-微服务架构。单体架构单体架构在我们还是学生的年代,我们创建的绝大部分应用都属于单体应用。那个时候,我们几乎都是一个人在开发导师布置下来的各种实验。我们会把数据库连接、业务逻辑处理、展示逻辑等放在一起,甚至会在处理用户请求的地方直接连接数据库(多么美好的回忆啊 _)。7基础知识篇后来,我们会学习到 MVC 架构以及由此衍生出来各种多层架构,由此便开启了应用的拆分之旅。多层架构的本质,是按照技术职责将应用做
5、水平拆分,每一层解决的技术问题相对集中,层与层之间做单向依赖。这样做可以帮助我们更好的管理我们的代码,大大提升了后期的维护效率。但是,此时应用还是一个应用,部署时也是按照一个整体运行。我们看到的应用架构应该类似下面的样子:在程序规模不大,开发人员很少的时候,下面的有点是非常显著的:开发简单。单体应用的结构,天然决定了所有代码都集中在一起,开发者不需要在多个应用之间来回跳转来寻找其中的调用逻辑。测试简单。所有代码都在一个应用里,测试人员可以很方便的做到端到端的测试(当然,很多时候测试人员就是开发者自己)。部署简单。因为一个应用就是产品功能的全集,所以在部署的时候,只需要不是一款应用即可。即使是集
6、群部署,也不会增加多少复杂度:只需要将应用部署多份即可。开发迅速。上面的各种简单,带来的就是软件功能可以快速实现。很多时候,实现需求的速度是项目成功与否的决定性因素。所以,在开发简单&独立的产品时,单体架构依然是第一优先选择。如果故事可以一直这么简单就好了。随着功能的持续增加、团队规模的不断扩大,我们很快就会发现单体应用的弊端:基础知识篇基础知识篇XML-一种标记语言,用于以文档格式描述消息中的数据。SOAP(Simple Object Access Protocol)-在计算机网络上交换基于 XML 的消息的协议,通常是用 HTTP。WSDL(Web Services Description
7、 Language,Web 服务描述语言)-基于XML 的描述语言,用于描述与服务交互所需的服务的公共接口,协议绑定,消息格式。UDDI(Universal Description,Discovery,and Integration,是统一描述、发现和集成)-基于 XML 的注册协议,用于发布 WSDL 并允许第三方发现这些服务。ESB(Enterprise Service Bus,企业服务总线)-支持异构环境中的服务、消息,以及基于事件的交互,并且具有适当的服务级别和可管理性。一个典型的 SOA 架构模式如下图:SOA 看似解决了单体架构的所有问题,世界似乎都变得更加美好了 _但是SOA 并
8、不完美,他也有很多问题的或者说是场景下的不适应。首先就是对 SOA 的解释缺乏统一标准,上文的引用的定义也只是众多解释中使用的较为通用的一种。甚至可以这么说:一千个人眼中,有一千种 SOA。基于此,很多厂商便借用 SOA 的大旗来推广自己的产品和标准,这又进一步加剧了问题的严重性。除此之外,SOA 还有很多其他的问题或不足:基础知识篇基础知识篇The microservice architectural style is an approach to developing asingle application as a suite of small services,each running
9、 in its ownprocess and communicating with lightweight mechanisms,often an HTTPresource API.These services are built around business capabilities andindependently deployable by fully automated deployment machinery.Thereis a bare minimum of centralized management of these services,whichmay be written
10、in different programming languages and use different datastorage technologies.?这里提到几个重要的概念:一套小服务独立进程轻量级通信协议可独立部署多语言&不同储技术这个定义对微服务做了一个比较具象化较为易于理解的描述,通常来说我们看到的为服务架构如下图所示:基础知识篇基础知识篇“微服务微服务”不是银弹不是银弹微服务并不是一劳永逸的解决了所有的问题,相反的,如果不能正确的使用微服务,则有可能被微服务自身的限制拖入另一个泥潭:分布式的代价。原本在单体应用中,很多简单的问题都会在分布式环境下被几何级的放大。例如分布式事务、
11、分布式锁、远程调用等,不光要考虑如何实现他们,相关场景的异常处理也是必须要考虑到的问题。协同代价。如果你经历过一个项目上线需要发布十几个应用,而这些应用又分别由多个团队在维护。你就能深刻的体会到协同是一件多么痛苦的事情了。服务拆分需要很强的设计功力。微服务的各种优势,其中一个重要的基础是对服务领域的正确切分。如果使用了不合适的切分粒度,或者是错误的切分方法,都会让服务不能很好的实现高内聚低耦合的要求。框架篇框架篇从从 SpringSpring 到到 SpringSpring CloudCloudSpringSpring熟悉 java 语言的同学,对 Spring 框架应该都不陌生。从 2004
12、 年 1.0 版本发布开始,便由于其灵活易用的特性受到了整个 Java 行业的广泛关注。经过十多年的发展,Spring 框架早已经成为 Java 语言下编程模型的事实标准。其所倡导的 IOC/AOP 概念也早已深入人心。在 Spring 框架的早期,大家都喜欢称其为“轻量化”框架(现在好像早就没人提这个词了_),“轻量”是相对于 EJB 等企业级开发框架而言的。其“轻”的特性体现在:框架本身的大小很小,早期版本的 jar 包不超过 1MB;同时不依赖于运行容器,也是说任何容器里都可以运行 Spring 框架;更加重要的是 Spring 是非侵入的,使用 Spring 开发的应用可以不完全依赖
13、Spring 的类。基础知识篇基础知识篇Spring Cloud provides tools for developers to quickly build some of thecommon patterns in distributed systems(e.g.configuration management,service discovery,circuit breakers,intelligent routing,micro-proxy,controlbus,one-time tokens,global locks,leadership election,distributed se
14、ssions,cluster state).Coordination of distributed systems leads to boiler platepatterns,and using Spring Cloud developers can quickly stand up servicesand applications that implement those patterns.They will work well in anydistributed environment,including the developers own laptop,bare metaldata c
15、entres,and managed platforms such as Cloud Foundry.这里面提到几个关键词:分布式系统中的常见模式任何分布式环境“分布式系统中的常见模式”给了 Spring Cloud 一个清晰的定位,即“模式”。也就是说 Spring Cloud 是针对分布式系统开发所做的通用抽象,是标准模式的实现。这个定义非常抽象,看完之后并不能知道 Spring Cloud 具体包含什么功能。再来看一下 Spring 官方给出的一个 High Light 的架构图,就可以对这套模式有更清晰的认识:可以看到这个图中间就是各个 Microservice,也就是我们的这个微服务
16、的实现,周边周围的话就是去围绕这个微服务来去做各种辅助的信息事情。例如分布式追踪、服务注册、配置服务等,都绕微服务运行时所依赖的必不可少的的支持性功能。我们可以得出这样一个结论:Spring Cloud 是以微服务为核心的分布式系统的一个构建标准。基础知识篇基础知识篇图中深色的部分,其实它就是 Spring Cloud 标准,一共有 3 层。中间颜色最深的部分就是及整个微服务最核心的内容,包括了“RPC 调用”以及“服务注册与发现”。第二层,也就是围绕着核心的这一圈,是一些辅助微服务更好的工作功能,包括了负载均衡、路由、网关、断路器,还有分就是追踪等等这些内容。再外层的话,主要是些分布式云环境
17、里通用能力。最外面这一圈,是 Spring Cloud Alibaba 对 Spring Cloud 的实现。右上部分是对于 Spring Cloud 标准的实现。例如,我们通过 Dubbo 实现了 RPC 调用功能,通过 Nacos 实现了“服务注册与发现”、“分布式配置”,通过 Sentinel 实现了断路器等等,这里就不一一列举了。左下部分是我们 Spring Cloud Alibaba 对阿里云各种服务的集成。可能很多同学会有这样的一个问题:为什么要加上这一部分呢?此时回头审视一下Spring Cloud,它仅仅是一个微服务的一个框架。但是在实际生产过程中,单独使用微服务框架其实并不足
18、以支撑我们去构建一个完整的系统。所以这部分是用阿里帮助开发者完成微服务以外的云产品集成的功能。为什么要分成两个部分呢,这也是为了打消大家对于使用了 Spring Cloud Alibaba以后就会被平台绑定的担忧。虽然在品牌商都叫做 SpringCloudAlibaba,但是在代码上,我们采用两个独立的项目维护,分别是 Spring Cloud Alibaba 和 Aliyun Spring Boot。目前,Spring Cloud Alibaba 包含如下组件:基础知识篇基础知识篇编译框架、坐标&名称、其他基础信息等,根据实际情况按需填写。当然,很多参数默认值就可以满足大部分需求。开发者重点
19、关注的是下面 3 个部分:组件依赖组件依赖很少有开发者会使用语言最原始的 sdk 来实现所有功能。通常来说,大家都会使用各种技术产品的高级封装来实现相关的技术特性。这里就需要做 2 件事情:引入对应组件的sdk、在应用中配置组件。而通过 Java 工程脚手架就可以很轻易的完成这些工作。Java 工程脚手架中提供了 2 种寻找组件的方式:根据分类浏览&关键字搜索这里根据组件分类寻找需要使用的组件:基础知识篇基础知识篇未选择任何组件时,是不会给出任何示例代码的。示例代码是在选择了组件依赖以后,才会出现于用户选择的组件相关的示例,如下图:由于很多案例自身也依赖其他组件,所以在选择了某个案例以后,会多
20、出一些案例,同时依赖的组件也会增多。本次课程使用到的案例,都可以在这里寻找到。生成代码生成代码仅仅完成项目配置是不够的,最终开发者需要的是项目的代码。so,show me thecode无论是出于查阅组件用法的目的,还是出于需要工程完整代码的目的,脚手架都可以很好的支持:如果仅仅需要查阅代码,而不是下载完整工程,可以直接通过点击“浏览代码”来实现。点击该按钮以后,会打开一个包含了完整代码树以及允许查看每个文件的内容窗口:基础知识篇基础知识篇SandboxSandbox 沙箱环境沙箱环境Sandbox 沙箱环境,为开发者带来一套快速上手、免除任何环境依赖、免费、便捷的开发&运行环境。允许开发者在
21、上面查看、修改、部署示例代码,并且由平台提供相关运行资源。下面来看一下产品的界面:左边是产品的手册&说明部分。这里会包含说当前项目的功能说明、应用架构,以及如何部署和访问这些应用的操作步骤等。一些项目中使用到的技术点以及这些相关知识,也都会在这里呈现给用户。这部分文档的目的,就是方便用户去学习和理解当前的案例。右边的部分是应用列表。一个完整的产品,可能需要多个应用协同才能工作,这里就是用来陈列相关的应用列表,同时也是针对这些应用的操作入口。图片中的案例是一个任务管理器产品,功能相对简单。但是麻雀虽小五脏俱全。这个产品包含两个应用:服务端,的包含了这个任务管理器的所有业务逻辑,以及下层的持久化能
22、力等。WEB 客户端,包含了所有前端页面逻辑、与前端通信的控制器层。基础知识篇基础知识篇部署完成以后,会向 WEB-IDE 返回一个访问地址,开发者只需要点击这和地址就可以访问这个应用。下图是实际的访问效果。可以看到,两个应用,一个是任务管理器的web 操作页面、一个是后台数据库管理页面:通过上面的步骤,开发者可以将案例快速部署起来。先部署试用,然后去学习和修改代码,最后再部署验证。通过这样的循环,可以让开发者很快学习和理解案例的功能和相关技术点。分布式配置分布式配置4.4.快速上手快速上手4.14.1 如何引入如何引入 NacosNacos ConfigConfig 支持分布式配置支持分布式
23、配置Nacos Config 引入的方式同样也有两种,即 Aliyun Java Initializr 引入和Maven pom.xml 依赖。官方推荐使用 Aliyun Java Initializr 方式引入 NacosDiscovery,以便简化组件之间的依赖关系。4.1.14.1.1 简单简单 通过通过 AliyunAliyun JavaJava InitializrInitializr 创建工程并引入创建工程并引入 NacosNacos ConfigConfig(推荐)(推荐)由于 Spring Cloud 组件的版本和依赖较为复杂,推荐读者使用 Aliyun JavaInitial
24、izr 构建应用工程。读者选择偏好的 Web 浏览器访问 Aliyun Java Initializr,其资源网址为:https:/ Google Chrome 浏览器为例,当网页加载后,首先,在 项目基本信息 部分输入 Group:“com.alibaba.cloud”以及 Artifact:“nacos-config-sample”。然后,“组件依赖”输入框搜索:“Nacos Config”,选择 Nacos Configuration,如下所示:同上组件操作,增加“Spring Web”和“Spring Boot Actuator”组件:分布式配置28组 件 选 择 后,点 击“生 成”
25、高 亮 按 钮。随 后,平 台 将 生 成 一 个 名 为“nacos-config-sample.zip”的压缩文件,将其保存到本地目录,并解压该文件,工程目录将随之生成。打开目录下的 pom.xml 文件,不难发现 Nacos starter 声明其中(以下 XML 内容均来自于项目根路径中的 pom.xml 文件):com.alibaba.cloudspring-cloud-starter-alibaba-nacos-config不过该 starter 并未指定版本,具体的版本声明在 com.alibaba.cloud:spring-cloud-alibaba-dependencies
26、部分:29分布式配置com.alibaba.cloudspring-cloud-alibaba-dependencies$spring-cloud-alibaba.versionpomimportorg.springframework.bootspring-boot-dependencies$spring-boot.versionpomimport其中,$spring-cloud-alibaba.version 和$spring-boot.version 分别为Spring Cloud Alibaba 和 Spring Boot 组件依赖的版本,它们的版本定义在元素中,即 2.2.1.RELE
27、ASE 和 2.3.0.RELEASE:1.8UTF-8UTF-82.3.0.RELEASE2.2.1.RELEASE如果读者非常熟悉 Maven 依赖管理的配置方式,可以考虑 Maven pom.xml 依赖Nacos Config。4.1.24.1.2 高级高级 通过通过 MavenMaven pom.xmlpom.xml 依赖依赖 NacosNacos ConfigConfig分布式配置30如果要在您的项目中使用 Nacos 来实现服务注册/发现,使用 group ID 为 com.alibaba.cloud 和 artifact ID 为 spring-cloud-starter-al
28、ibaba-nacos-config 的starter。com.alibaba.cloudspring-cloud-starter-alibaba-nacos-config该声明方式同样需要声明 com.alibaba.cloud:spring-cloud-alibaba-dependencies,内容与上小节相同,在此不再赘述。下一节将讨论如何使用NacosConfig 支持分布式配置。4.1.34.1.3 偷懒偷懒 直接在沙箱里查看应用代码直接在沙箱里查看应用代码点击 链接,直接访问沙箱环境,这里会有为你准备好的案例代码_。4.24.2 使用使用 NacosNacos ConfigConf
29、ig 实现分布式配置实现分布式配置使用 Nacos Config 实现分布式配置与 Spring Cloud Consul 和 SpringCloud Zookeeper 的方式非常类似,仅需添加相关外部化配置即可工作。换言之,Nacos Config 同样不会侵入应用代码,方便应用整合和迁移,如果读者熟悉 SpringCloud Consul 或 Spring Cloud Zookeeper 使用方式 的话,通常需要将 Consul或 Zookeeper 服务进程预先部署,Nacos Config 也如此。4.2.14.2.1 启动启动 NacosNacos 服务器服务器我们为开发者提供了一
30、套免费的 Nacos Server:进入 http:/139.196.203.133:8848/nacos/查看控制台(账号名/密码为 nacos-configuration/nacos-configuration),选择 配置管理/配置列表:31分布式配置由于服务是公共免费的,为了做好隔离,所以分布式配置的功能,请选择在 sandbox-configuration 的命名空间下操作。具体启动方式参考 Nacos 官网。关于更多的 Nacos Server 版本,可以从 release 页面 下载最新的版本。4.2.24.2.2 添加添加 NacosNacos 配置配置点击“配置列表”页面右侧
31、的+号(红色箭头所指):浏览器跳转新页面,并填充内容如下:分布式配置分布式配置注意,Nacos Server 地址必须配置在 application.properties 文件。注意当你使用域名的方式来访问 Nacos 时,spring.cloud.nacos.config.server-addr 配置的方式为域名:port。例如 Nacos 的域名为 .nacos,监听的端口为80,则 spring.cloud.nacos.config.server-addr=.nacos:80。注意 80 端口不能省略。4.2.44.2.4 添加读取添加读取 NacosNacos ConfigConfig
32、 实现实现修改 nacos-config-sample 引导类,如下所示:SpringBootApplicationpublic class NacosConfigSampleApplication Value($user.name)private String userName;Value($user.age)private int userAge;PostConstructpublic void init()System.out.printf(init user name:%s,age:%d%n,userName,userAge);public static void main(Strin
33、g args)SpringApplication.run(NacosConfigSampleApplication.class,args);4.2.54.2.5 启动启动 NacosNacos ConfigConfig 应用应用运行 nacos-config-sample 引导类 NacosConfigSampleApplication,观察控制台结果(截取关键日志信息):init user name:nacos-config-sample,age:90分布式配置分布式配置SpringBootApplicationRestControllerRefreshScopepublic class N
34、acosConfigSampleApplication Value($user.name)private String userName;Value($user.age)private int userAge;PostConstructpublic void init()System.out.printf(init user name:%s,age:%d%n,userName,userAge);RequestMapping(/user)public String user()return String.format(HTTP user name:%s,age:%d,userName,userA
35、ge);public static void main(String args)SpringApplication.run(NacosConfigSampleApplication.class,args);重启引导类 NacosConfigSampleApplication,控制台输出如故:init user name:nacos-config-sample,age:90再通过命令行访问 REST 资源/user:%curl http:/127.0.0.1:8080/userHTTP user name:nacos-config-sample,age:90如果使用沙箱环境,请直接点击应用列表的
36、访问按钮,并在打开的浏览器窗口的地址栏中追加/user,如下图:分布式配置分布式配置%curl http:/127.0.0.1:8080/userHTTP user name:nacos-config-sample,age:99终端日志显示了这次配置变更同步到了 Value($user.age)属性 userAge 的内容。除此之外,应用控制台也输出了以下内容:init user name:nacos-config-sample,age:99而该日志是由 init()方法输出,那么是否说明该方法被框架调用了呢?答案是肯定的。既然 PostConstruct 方法执行了,那么 PreDestro
37、y 方法会不会被调用呢?不妨增加 Spring Bean 销毁回调方法:SpringBootApplicationRestControllerRefreshScopepublic class NacosConfigSampleApplication Value($user.name)private String userName;Value($user.age)private int userAge;PostConstructpublic void init()System.out.printf(init user name:%s,age:%d%n,userName,userAge);PreD
38、estroypublic void destroy()System.out.printf(destroy user name:%s,age:%d%n,userName,userAge);.再次重启引导类 NacosConfigSampleApplication,初始化日志仍旧输出:分布式配置分布式配置5.25.2 使用使用 NacosNacos ConfigConfig 实现实现ConfigurationPropertiesConfigurationProperties BeanBean 属性属性动态刷新动态刷新在应用 nacos-config-sample 新增 User 类,并标注 Ref
39、reshScope 和ConfigurationProperties,代码如下:RefreshScopeConfigurationProperties(prefix=user)public class User private String name;private int age;public String getName()return name;public void setName(String name)this.name=name;public int getAge()return age;public void setAge(int age)this.age=age;Overri
40、depublic String toString()return User+name=+name+,age=+age+;根据 ConfigurationProperties 的定义,User 类的属性绑定到了配置属性前缀user。下一步,调整引导类,代码如下:分布式配置分布式配置激活 ConfigurationProperties Bean EnableConfigurationProperties(User.class)。通过 Autowired 依赖注入 User Bean。使用 user Bean(toString()方法替换 user()中的实现。下一步,重启应用后,再将 user.a
41、ge 配置从 18 调整为 99,控制台日志输出符合期望:init user name:nacos-config-sample,age:18.fixed-127.0.0.1_8848 data-received dataId=nacos-config-sample.properties,group=DEFAULT_GROUP,tenant=null,md5=b0f42fac52934faf69757c2b6770d39c,content=user.name=nacos-config-sampleuser.age=90,type=properties.destroy user name:naco
42、s-config-sample,age:18o.s.c.e.event.RefreshEventListener:Refresh keys changed:user.age接下来,访问 REST 资源/user,观察终端日志输出:%curl http:/127.0.0.1:8080/userHTTP Username=nacos-config-sample,age=90User Bean 属性成功地变更为 90,达到实战效果。上小节提到 Nacos Config 配置变更会影响 RefreshScope Bean 的生命周期方法回调。同理,如果为 User 增加初始化和销毁方法的话,也会出现行
43、文,不过本次将 User 实现 Spring 标准的生命周期接口 InitializingBean 和 DisposableBean:RefreshScopeConfigurationProperties(prefix=user)public class User implements InitializingBean,DisposableBean private String name;private int age;public String getName()return name;分布式配置 19),观察控制台日志输出:43分布式配置init user name:nacos-confi
44、g-sample,age:90.c.a.n.client.config.impl.ClientWorker:fixed-127.0.0.1_8848 data-receiveddataId=nacos-config-sample.properties,group=DEFAULT_GROUP,tenant=null,md5=30d26411b8c1ffc1d16b3f9186db498a,content=user.name=nacos-config-sampleuser.age=19,type=properties.destroy()Username=nacos-config-sample,ag
45、e=90afterPropertiesSet()Username=nacos-config-sample,age=19destroy user name:nacos-config-sample,age:90.o.s.c.e.event.RefreshEventListener:Refresh keys changed:user.age不难发现,User Bean 的生命周期方法不仅被调用,并且仍旧是先销毁,再初始化。那么,这个现象和之前看到的 SpringApplication 重启是否有关系呢?答案也是肯定的,不过还是后文再讨论。下一小节将继续讨论怎么利用底层 Nacos 配置监听实现 Be
46、an 属性动态刷新。5.35.3 使用使用 NacosNacos ConfigConfig 监听实现监听实现 BeanBean 属性动态刷新属性动态刷新前文曾提及 com.alibaba.nacos.api.config.listener.Listener 是 Nacos ClientAPI 标准的配置监听器接口,由于仅监听配置内容,并不能直接与 Spring 体系打通,因此,需要借助于 Spring Cloud Alibaba Nacos Config API NacosConfigManager(感谢小伙伴 liaochuntao 和 zkzlx 的代码贡献),代码调整如下:SpringB
47、ootApplicationRestControllerRefreshScopeEnableConfigurationProperties(User.class)public class NacosConfigSampleApplication Value($user.name)private String userName;Value($user.age)private int userAge;分布式配置 String dataId=nacos-config-sample.properties;String group=DEFAULT_GROUP;nacosConfigManager.get
48、ConfigService().addListener(dataId,group,newAbstractListener()Overridepublic void receiveConfigInfo(String configInfo)System.out.println(Listener +configInfo););PostConstructpublic void init()System.out.printf(init user name:%s,age:%d%n,userName,userAge);PreDestroypublic void destroy()System.out.pri
49、ntf(destroy user name:%s,age:%d%n,userName,userAge);RequestMapping(/user)public String user()return HTTP +user;public static void main(String args)SpringApplication.run(NacosConfigSampleApplication.class,args);45分布式配置代码主要变化:Autowired 依赖注入 NacosConfigManager。新增 runner()方法,通过 NacosConfigManagerBean 获取
50、 ConfigService,并增加了 AbstractListener(Listener 抽象类)实现,监听 dataId=nacos-config-sample.properties 和 group=DEFAULT_GROUP 的配置内容。重启应用,并将配置 user.age 从 19 调整到 90,观察日志变化:c.a.n.client.config.impl.ClientWorker:fixed-127.0.0.1_8848 data-receiveddataId=nacos-config-sample.properties,group=DEFAULT_GROUP,tenant=nul






