Dubbo 3 中的三层配置隔离
Models提供的隔离
Dubbo目前提供了三个级别上的隔离:JVM级别、应用级别、服务(模块)级别,从而实现各个级别上的生命周期及配置信息的单独管理。这三个层次上的隔离由 FrameworkModel、ApplicationModel 和 ModuleModel 及它们对应的 Config 来完成。
FrameworkModel :Dubbo 框架的顶级模型,表示 Dubbo 框架的全局运行环境,适配多应用混合部署的场景,降低资源成本。
如:假设我们有一个在线教育平台,平台下有多个租户,而我们希望使这些租户的服务部署在同一个 JVM 上以节省资源,但它们之间可能使用不同的注册中心、监控设施、协议等,因此我们可以为每个租户分配一个 FrameWorkModel 实例来实现这种隔离。
FrameworkModel负责管理整个Dubbo框架的各种全局配置、元数据以及默认配置。
ApplicationModel :应用程序级别模型,表示一个 Dubbo 应用(通常为一个 SpringApplication)。适配单JVM多应用场景,通常结合热发布使用,降低热发布对整个应用的影响范围。
如,以上的在线教育平台有多个子系统,如课程管理、学生管理,而每个子系统都是独立的 Spring 应用,在同个 JVM 中运行,共享一个 FrameworkModel,也会共享 Framework 级别的默认配置和资源:
//课程管理应用 @SpringBootApplication public class ClassApplication { private static ApplicationModel classAppModel; public static void main(String[] args) { classAppModel .getApplicationConfigManager() .addRegistry(new RegistryConfig(REGISTRY_URL_CLASS)); //...其它设置 SpringApplication.run(ClassApplication.class, args); } public static void setApplicationModel(ApplicationModel classAppModel){ this.classAppModel = classAppModel; } }
//学生管理应用 @SpringBootApplication public class StudentApplication { private static ApplicationModel studentAppModel; public static void main(String[] args) { studentAppModel .getApplicationConfigManager() .addRegistry(new RegistryConfig(REGISTRY_URL_STUDENT)); //...其它设置 SpringApplication.run(StudentApplication.class, args); } public static void setApplicationModel(ApplicationModel studentAppModel){ this.studentAppModel = studentAppModel; } }
//单机发布多应用 public class MultiContextLauncher { private static FrameworkModel frameworkModel = new FrameworkModel(); public static void main(String[] args) { //使用同一个FrameworkModel ClassApplication.setApplicationModel(frameworkModel.newApplication()); StudenAppication.setApplicationModel(frameworkModel.newApplication()); new SpringApplicationBuilder(ClassApplication.class) .run(args); new SpringApplicationBuilder(StudentApplication.class.class) .run(args); } }
由此,我们可以重新部署单个应用与其对应的ApplicationModel,实现热发布,而不会影响到另一个应用。
ModuleModel :模块级别模型,表示应用下的子模块。适配一个应用下的多个模块(容器)。
如,上述的课程管理子系统内,新增课程和发布课程两个业务模块可能使用不同的spring容器。我们可以为每个spirng容器提供一个ModuleModel实例来管理、隔离模块级别的配置和资源:
@Configuration
@ComponentScan("com.example.demo.class")
public class ClassManageConfig {
// 课程管理模块配置
}
@Configuration
@ComponentScan("com.example.demo.student")
public class ClassPublishConfig {
// 课程发布模块配置
}
public class EducationPlatformApplication {
public static void main(String[] args) {
FrameworkModel frameworkModel = new FrameworkModel();
ApplicationModel applicationModel = frameworkModel.newApplication();
// 创建课程管理模块,使用自己的ApplicationContext与ModuleModel
ModuleModel classManageModuleModel = applicationModel.newModule();
AnnotationConfigApplicationContext classManageContext = new AnnotationConfigApplicationContext(classManageModuleModel);
classManageContext.register(ClassManagementConfig.class);
classManageContext.refresh();
// 创建学生管理模块,使用自己的ApplicationContext与ModuleModel
ModuleModel classPublishModuleModel = applicationModel.newModule();
AnnotationConfigApplicationContext classPublishContext = new AnnotationConfigApplicationContext(classPublishModuleModel);
classPublishContext.register(ClassPublishConfig.class);
classPublishContext.refresh();
}
}
三层的模型设计让Dubbo在处理复杂业务场景时具有更强的适应性和可扩展性。
以下是一个以传统方式(而非 DubboBootstrap)启动 Dubbo 的 Demo,可以帮助我们了解 FrameworkModel、ApplicationModel 和 ModuleModel 之间的组织关系。
private static void startWithExportNew() throws InterruptedException {
//创建三个层级的Model
FrameworkModel frameworkModel = new FrameworkModel();
ApplicationModel applicationModel = frameworkModel.newApplication();
ModuleModel moduleModel = applicationModel.newModule();
//提供配置中心、元数据中心、协议的配置
RegistryConfig registryConfig = new RegistryConfig(REGISTRY_URL);
MetadataReportConfig metadataReportConfig = new MetadataReportConfig(METADATA_REPORT_URL);
ProtocolConfig protocolConfig = new ProtocolConfig(CommonConstants.DUBBO, -1);
//如果之后需要获取注册中心或元数据中心,需要设置id,之后通过它们的Id获取(适配多注册中心)
final String registryId = "registry-1";
registryConfig.setId(registryId);
//Model的配置管理通过对应的ConfigManager进行
ConfigManager appConfigManager = applicationModel.getApplicationConfigManager();
appConfigManager.setApplication(new ApplicationConfig("dubbo-demo-api-provider-app-1"));
//提供应用层级的配置中心、元数据中心、协议默认设置
appConfigManager.addRegistry(registryConfig);
appConfigManager.addMetadataReport(metadataReportConfig);
appConfigManager.addProtocol(protocolConfig);
ModuleConfigManager moduleConfigManager = moduleModel.getConfigManager();
moduleConfigManager.setModule(new ModuleConfig("dubbo-demo-api-provider-app-1-module-1"));
ServiceConfig<DemoService> serviceConfig = new ServiceConfig<>();
//设置该ServiceConfig对应的ModuleModel
serviceConfig.setScopeModel(moduleModel);
serviceConfig.setProtocol(protocolConfig);
serviceConfig.setInterface(DemoService.class);
serviceConfig.setRef(new DemoServiceImpl());
//为ModuleModel添加ServiceConfig
moduleConfigManager.addConfig(serviceConfig);
serviceConfig.export();
new CountDownLatch(1).await();
}
- ApplicationModel 由 FrameWorkModel 创建,ModuleModel 由 ApplicationModel 创建,由此完成它们之间层级关系的引用。
- ServiceConfig 和 ReferenceConfig 需要设置其所属的 ScopeModel(实际只能为 ModuleModel )。然后,还需将它们设置到对应的ModuleModel 中。