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();
}