25小节:使用观察者模式重构配置动态刷新
作者:程序员马丁
note
Ragent AI —— 从 0 到 1 纯手工打造企业级 Agentic RAG,拒绝 Demo 玩具!AI 时代,助你拿个offer。
使用观察者模式重构配置动态刷新,元数据信息:
- 什么是线程池oneThread:https://t.zsxq.com/5GfrN
- 代码仓库:https://gitcode.net/nageoffer/onethread —— 申请项目权限参考上述线程池项目链接
- 章节难度:★★★☆☆ - 较难
- 视频地址:文档先行视频次之
©版权所有 - 拿个offer-开源&项目实战星球专属学习项目,依据《中华人民共和国著作权法实施条例》和《知识星球产权保护》,严禁未经本项目原作者明确书面授权擅自分享至 GitHub、Gitee 等任何开放平台。违者将面临法律追究。
内容摘要:本文深入剖析了 oneThread 动态线程池框架中跨模块通信的设计挑战,通过对配置中心 Starter 与 Web Starter 解耦需求的分析,引出观察者模式在框架架构中的核心价值。文章从实际业务场景出发,详细解析了观察者模式的设计理念、实现机制以及在动态线程池配置刷新中的具体应用。
课程目录如下所示:
- 前言
- 跨模块通信的设计挑战
- 为什么选择观察者模式?
- 什么是观察者模式?
- oneThread 中的观察者模式实现
- 扩展性分析
- Guava vs Spring 观察者模式
- 文末总 结
前言
在构建 oneThread 动态线程池框架的过程中,我们面临着一个经典的架构设计问题:如何在保持模块独立性的前提下,实现跨模块的高效通信?
特别是在配置中心 Starter 需要通知 Web Starter 进行线程池参数更新时,传统的直接依赖方式会带来模块耦合、包体积膨胀等问题。为了解决这一挑战,我们引入了观察者模式,构建了一套松耦合、高扩展的事件驱动架构。
本文将带你深入了解这一设计决策的来龙去脉,以及观察者模式在 oneThread 框架中的精妙应用。
跨模块通信的设计挑战
1. 模块架构概览
oneThread 框架采用分层模块化设计,主要包含以下核心模块:
.
└── starter # 动态线程池配置中心组件包,实现线程池结合Spring框 架和配置中心动态刷新
├── adapter # 动态线程池适配层,比如对接 Web 容器 Tomcat 线程池等
│ └── web-spring-boot-starter # Web 容器线程池组件库
├── apollo-spring-boot-starter # Apollo 配置中心动态监控线程池组件库
├── common-spring-boot-starter # 配置中心公共监听等逻辑抽象组件库
├── dashboard-dev-spring-boot-starter # 控制台 API 组件库
└── nacos-cloud-spring-boot-starter # Nacos 配置中心动态监控线程池组件库
和本文章相关的在 starter 模块下,子模块职责如下:
- common-spring-boot-starter:提供配置解析、事件定义等公共能力。
- nacos/apollo-spring-boot-starter:监听配置中心变更,触发刷新逻辑。
- web-spring-boot-starter:管理 Web 容器线程池,响应配置变更。
如果采用直接依赖的方式解决跨模块通信,会面临以下问题:
- 配置中心相关的 Starter 依赖 web-starter,如果用户仅需要动态线程池依赖,无法按需依赖。
- 扩展性差,每增加一种线程池适配器(如 Dubbo、Hystrix 等),都需要修改配置中心 Starter 代码,增加新的依赖关系等。
代码耦合如下所示:
// 配置中心 Starter 需要了解所有可能的线程池类型
public class AbstractDynamicThreadPoolRefresher {
@Autowired(required = false)
private WebThreadPoolService webService;
@Autowired(required = false)
private RocketMQThreadPoolService rocketMQService;
@Autowired(required = false)
private RabbitMQThreadPoolService rabbitMQService;
public void refreshConfig(String config) {
if (webService != null) {
webService.update(config);
}
if (rocketMQService != null) {
rocketMQService.update(config);
}
// ... 更多if判断
}
}