DubboBootStrap 监听实现
public DubboBootstrap start() {
//1. 判断是不是没有启动,如果是就将true设置给started表示,然后执行启动程序
if (started.compareAndSet(false, true)) {
ready.set(false);
//2. 初始化
initialize();
if (logger.isInfoEnabled()) {
logger.info(NAME + " is starting...");
}
// 3. export Dubbo Services 暴露Provider的 Services 服务暴露
exportServices();
// 判断是否是进行服务暴力
if (!isOnlyRegisterProvider() || hasExportedServices()) {
// 4.导出元数据 export MetadataService
exportMetadataService();
//5. Register the local ServiceInstance if required通过spi方式获取服务注册中心
registerServiceInstance();
}
//6 处理Consumer的ReferenceConfig 服务引用
referServices();
if (asyncExportingFutures.size() > 0) {//异步操作,在exportServices中添加
new Thread(() -> {
try {
this.awaitFinish();
} catch (Exception e) {
logger.warn(NAME + " exportAsync occurred an exception.");
}
ready.set(true);
if (logger.isInfoEnabled()) {
logger.info(NAME + " is ready.");
}
}).start();
} else {
ready.set(true);
if (logger.isInfoEnabled()) {
logger.info(NAME + " is ready.");
}
}
if (logger.isInfoEnabled()) {
logger.info(NAME + " has started.");
}
}
return this;
}
dubboBootStrap 初始化
public void initialize() {
//CAS操作确认是否初始化
if (!initialized.compareAndSet(false, true)) {
return;
}
//1. 初始化框架的扩展
//这个实现就是从系统中获取SPI接口FrameworkExt的所有的扩展实例,然后依次调用initialize方法
//iniFrameworkExts == Environment#initialize()
ApplicationModel.initFrameworkExts();
//2. 初始化配置中心
// startConfigCenter中第一条语句,当注册中心使用zookeeper时,如果配置中心地址没有指定就以注册中心zookeeper作为默认的配置中心
startConfigCenter();
//4. 加载远程的配置
loadRemoteConfigs();
//5. 检查全局配置
checkGlobalConfigs();
// @since 2.7.8
startMetadataCenter();
//6. 初始化元数据操作接口
initMetadataService();
//7. 将本身添加到事件监听器列表中,因为DubboBootstrap本身就是一个事件监听器
initEventListener();
if (logger.isInfoEnabled()) {
logger.info(NAME + " has been initialized!");
}
}
初始化过程图解
第一步初始化框架拓展
FrameworkExt 继承了 LifeCycle。这里通过SPI机制加载FrameworkExt 类扩展实例,并调用实例的初始化方法
public static void initFrameworkExts() {
Set<FrameworkExt> exts = ExtensionLoader.getExtensionLoader(FrameworkExt.class).getSupportedExtensionInstances();
for (FrameworkExt ext : exts) {
ext.initialize();
}
}
FrameworkExt 共有三个实现 ConfgiManager、Environment、ServiceRepository
其中 Environment 重写了 initialize方法。将配置中心信息存入ApplicationModel本地缓存中。
//就是将配置中心COnfigCenter的信息存入到本地缓存中
@Override
public void initialize() throws IllegalStateException {
ConfigManager configManager = ApplicationModel.getConfigManager();
Optional<Collection<ConfigCenterConfig>> defaultConfigs = configManager.getDefaultConfigCenter();
defaultConfigs.ifPresent(configs -> {
for (ConfigCenterConfig config : configs) {
this.setExternalConfigMap(config.getExternalConfiguration());
this.setAppExternalConfigMap(config.getAppExternalConfiguration());
}
});
this.externalConfiguration.setProperties(externalConfigurationMap);
this.appExternalConfiguration.setProperties(appExternalConfigurationMap);
}
第二步 初始化配置中心
private void startConfigCenter() {
// 当注册中心使用zookeeper时,如果配置中心地址没有指定就以注册中心zookeeper作为默认的配置中心
useRegistryAsConfigCenterIfNecessary();
//从ConfigManager实例中获取配置中心的配置
Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
// check Config Center
if (CollectionUtils.isEmpty(configCenters)) {
ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
configCenterConfig.refresh();
if (configCenterConfig.isValid()) {
configManager.addConfigCenter(configCenterConfig);
configCenters = configManager.getConfigCenters();
}
} else {
for (ConfigCenterConfig configCenterConfig : configCenters) {
configCenterConfig.refresh();
ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
}
}
if (CollectionUtils.isNotEmpty(configCenters)) {
CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
for (ConfigCenterConfig configCenter : configCenters) {
compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter));
}
//然后把获取的配置封装之后存入Environment对象实例中
environment.setDynamicConfiguration(compositeDynamicConfiguration);
}
//刷新配置
configManager.refreshAll();
}
使用zookeeper作为注册中心时,没有指定配置中心地址,默认使用zookeeper 作为配置中心
private void useRegistryAsConfigCenterIfNecessary() {
// we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
//配置了注册中心
if (environment.getDynamicConfiguration().isPresent()) {
return;
}
//配置中心没有配置,如果有就直接返回
if (CollectionUtils.isNotEmpty(configManager.getConfigCenters())) {
return;
}
//从configManager中获取注册中心的地址,然后利用注册中心的地址信息构建ConfigCenterConfig
configManager
.getDefaultRegistries()
.stream()
.filter(this::isUsedRegistryAsConfigCenter)
.map(this::registryAsConfigCenter)
.forEach(
configManager::addConfigCenter ////将新建的ConfigCenterConfig添加到ConfigManager对象中
);
}
第三步加载远程配置
处理RegistryConfig和ProtocolConfig的 ID不一致问题
private void loadRemoteConfigs() {
// registry ids to registry configs
List<RegistryConfig> tmpRegistries = new ArrayList<>();
Set<String> registryIds = configManager.getRegistryIds();
registryIds.forEach(id -> {
if (tmpRegistries.stream().noneMatch(reg -> reg.getId().equals(id))) {
tmpRegistries.add(configManager.getRegistry(id).orElseGet(() -> {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setId(id);
registryConfig.refresh();
return registryConfig;
}));
}
});
configManager.addRegistries(tmpRegistries);
// protocol ids to protocol configs
List<ProtocolConfig> tmpProtocols = new ArrayList<>();
Set<String> protocolIds = configManager.getProtocolIds();
protocolIds.forEach(id -> {
if (tmpProtocols.stream().noneMatch(prot -> prot.getId().equals(id))) {
tmpProtocols.add(configManager.getProtocol(id).orElseGet(() -> {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setId(id);
protocolConfig.refresh();
return protocolConfig;
}));
}
});
configManager.addProtocols(tmpProtocols);
}
第四步 检查全局配置
主要对各个组件进行非空和命名规范检查
private void checkGlobalConfigs() {
// 检查Application
ConfigValidationUtils.validateApplicationConfig(getApplication());
//校验元数据
Collection<MetadataReportConfig> metadatas = configManager.getMetadataConfigs();
if (CollectionUtils.isEmpty(metadatas)) {
MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
metadataReportConfig.refresh();
if (metadataReportConfig.isValid()) {
configManager.addMetadataReport(metadataReportConfig);
metadatas = configManager.getMetadataConfigs();
}
}
if (CollectionUtils.isNotEmpty(metadatas)) {
for (MetadataReportConfig metadataReportConfig : metadatas) {
metadataReportConfig.refresh();
ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
}
}
// 校验服务提供者配置
Collection<ProviderConfig> providers = configManager.getProviders();
if (CollectionUtils.isEmpty(providers)) {
configManager.getDefaultProvider().orElseGet(() -> {
ProviderConfig providerConfig = new ProviderConfig();
configManager.addProvider(providerConfig);
providerConfig.refresh();
return providerConfig;
});
}
for (ProviderConfig providerConfig : configManager.getProviders()) {
ConfigValidationUtils.validateProviderConfig(providerConfig);
}
// 校验服务消费者配置
Collection<ConsumerConfig> consumers = configManager.getConsumers();
if (CollectionUtils.isEmpty(consumers)) {
configManager.getDefaultConsumer().orElseGet(() -> {
ConsumerConfig consumerConfig = new ConsumerConfig();
configManager.addConsumer(consumerConfig);
consumerConfig.refresh();
return consumerConfig;
});
}
for (ConsumerConfig consumerConfig : configManager.getConsumers()) {
ConfigValidationUtils.validateConsumerConfig(consumerConfig);
}
//校验监控配置
ConfigValidationUtils.validateMonitorConfig(getMonitor());
// check Metrics
ConfigValidationUtils.validateMetricsConfig(getMetrics());
// check Module
ConfigValidationUtils.validateModuleConfig(getModule());
// check Ssl
ConfigValidationUtils.validateSslConfig(getSsl());
}
第五步 初始化元数据
private void initMetadataService() {
startMetadataCenter();
this.metadataService = getDefaultExtension();
this.metadataServiceExporter = new ConfigurableMetadataServiceExporter(metadataService);
}
第六步 将自身加入事件监听队列
private void initEventListener() {
// Add current instance into listeners
addEventListener(this);
}
public DubboBootstrap addEventListener(EventListener<?> listener) {
eventDispatcher.addEventListener(listener);
return this;
}
DubboBootStrap 服务暴露
将服务注册到注册中心,如果消费者订阅了注册中心存储的服务,提供对应服务接口的远程调用
private void exportServices() {
//从配置管理器中获取到所有的要暴露的服务配置,一个接口类对应一个ServiceConfigBase实例
//从ConfigManager中获取所有的ServiceConfig实例,然后遍历,一个一个的暴露
configManager.getServices().forEach(sc -> {
// TODO, compatible with ServiceConfig.export()
// 服务export的核心逻辑方法是ServiceConfig#export()
ServiceConfig serviceConfig = (ServiceConfig) sc;
//将DubboBootstrap实例赋值给ServiceConfig
serviceConfig.setBootstrap(this);
//判断是否异步暴露接口
if (exportAsync) {
//如果是异步暴露接口,就获取一个线程池来异步执行接口暴露逻辑
ExecutorService executor = executorRepository.getServiceExporterExecutor();
Future<?> future = executor.submit(() -> {
//暴露接口,将接口信息注册到注册中心
sc.export();
exportedServices.add(sc);
});
asyncExportingFutures.add(future);
} else {
//同步export
sc.export();
exportedServices.add(sc);
}
});
}
public synchronized void export() {
//如果bootstrap为空即没有初始化,就初始化
if (bootstrap == null) {
bootstrap = DubboBootstrap.getInstance();
bootstrap.initialize();
}
checkAndUpdateSubConfigs();
// 初始化服务的原数据信息
//init serviceMetadata
serviceMetadata.setVersion(getVersion());
serviceMetadata.setGroup(getGroup());
serviceMetadata.setDefaultGroup(getGroup());
serviceMetadata.setServiceType(getInterfaceClass());
//设置服务接口
serviceMetadata.setServiceInterfaceName(getInterface());
//设置服务实现类
serviceMetadata.setTarget(getRef());
//如果服务已经export那么就返回
if (!shouldExport()) {
return;
}
//是否为延迟export
if (shouldDelay()) {
//如果是延时export,就使用时间调度器延时服务export逻辑
DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS);
} else {
//不是延时export那就直接export
doExport();
}
//发布serviceConfigExportedEvent事件
exported();
}
doExprot 准备执行服务暴露
protected synchronized void doExport() {
//如果service已经被unexported,就抛出异常
if (unexported) {
throw new IllegalStateException("The service " + interfaceClass.getName() + " has already unexported!");
}
//如果服务已经被暴露,就返回
if (exported) {
return;
}
exported = true;
//设置path值,值为接口的全限定名
if (StringUtils.isEmpty(path)) {
path = interfaceName;
}
//执行服务暴露逻辑
doExportUrls();
}
核心暴露方法,一个服务配置实例 ServiceConfig 可能同时以多个协议暴露
@SuppressWarnings({"unchecked", "rawtypes"})
private void doExportUrls() {
//从ApplicationModel容器中获取服务仓库ServiceRepository(也是一个容器)
ServiceRepository repository = ApplicationModel.getServiceRepository();
//生产一个服务描述实例ServiceDescriptor
ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass());
//将服务提供者的信息存放到ServiceRepository中
repository.registerProvider(
getUniqueServiceName(),
ref,
serviceDescriptor,
this,
serviceMetadata
);
//获取服务注册中心的URL地址信息,一个服务可以同时在多个注册中心注册。所以此处是List
List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);
//遍历服务要暴露的协议集合。一个服务可能同时以dubbo协议,rest协议等export。一般默认是dubbo协议,也推荐是用dubbo协议
for (ProtocolConfig protocolConfig : protocols) {
//构建服务的path的key
String pathKey = URL.buildKey(getContextPath(protocolConfig)
.map(p -> p + "/" + path)
.orElse(path), group, version);
repository.registerService(pathKey, interfaceClass);
serviceMetadata.setServiceKey(pathKey);
//针对一个协议,在一个或多个注册中心来export这个服务
doExportUrlsFor1Protocol(protocolConfig, registryURLs);
}
}
针对不同协议,在一个或多个注册中心暴露此服务。此方法主要:根据协议组装参数,根据scope来决定以本地(local)方式还是以远程(remote)方式暴露服务. 关键逻辑在于使用ProxyFactory来生成代理接口invoker,并且生成invoker包装类即扩展了ServiceConfig的Invoker对象,根据Protocol把invoker包装类 进行暴露 之后放入exporters 已暴露的服务集合中
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
//获取协议名称,没有则默认使用dubbo
String name = protocolConfig.getName();
if (StringUtils.isEmpty(name)) {
name = DUBBO;
}
// 组装参数 一直到461行
Map<String, String> map = new HashMap<String, String>();
map.put(SIDE_KEY, PROVIDER_SIDE);
ServiceConfig.appendRuntimeParameters(map);
AbstractConfig.appendParameters(map, getMetrics());
AbstractConfig.appendParameters(map, getApplication());
AbstractConfig.appendParameters(map, getModule());
// remove 'default.' prefix for configs from ProviderConfig
// appendParameters(map, provider, Constants.DEFAULT_KEY);
AbstractConfig.appendParameters(map, provider);
AbstractConfig.appendParameters(map, protocolConfig);
AbstractConfig.appendParameters(map, this);
MetadataReportConfig metadataReportConfig = getMetadataReportConfig();
if (metadataReportConfig != null && metadataReportConfig.isValid()) {
map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE);
}
if (CollectionUtils.isNotEmpty(getMethods())) {
for (MethodConfig method : getMethods()) {
AbstractConfig.appendParameters(map, method, method.getName());
String retryKey = method.getName() + ".retry";
if (map.containsKey(retryKey)) {
String retryValue = map.remove(retryKey);
if ("false".equals(retryValue)) {
map.put(method.getName() + ".retries", "0");
}
}
List<ArgumentConfig> arguments = method.getArguments();
if (CollectionUtils.isNotEmpty(arguments)) {
for (ArgumentConfig argument : arguments) {
// convert argument type
if (argument.getType() != null && argument.getType().length() > 0) {
Method[] methods = interfaceClass.getMethods();
// visit all methods
if (methods.length > 0) {
for (int i = 0; i < methods.length; i++) {
String methodName = methods[i].getName();
// target the method, and get its signature
if (methodName.equals(method.getName())) {
Class<?>[] argtypes = methods[i].getParameterTypes();
// one callback in the method
if (argument.getIndex() != -1) {
if (argtypes[argument.getIndex()].getName().equals(argument.getType())) {
AbstractConfig.appendParameters(map, argument, method.getName() + "." + argument.getIndex());
} else {
throw new IllegalArgumentException("Argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
}
} else {
// multiple callbacks in the method
for (int j = 0; j < argtypes.length; j++) {
Class<?> argclazz = argtypes[j];
if (argclazz.getName().equals(argument.getType())) {
AbstractConfig.appendParameters(map, argument, method.getName() + "." + j);
if (argument.getIndex() != -1 && argument.getIndex() != j) {
throw new IllegalArgumentException("Argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
}
}
}
}
}
}
}
} else if (argument.getIndex() != -1) {
AbstractConfig.appendParameters(map, argument, method.getName() + "." + argument.getIndex());
} else {
throw new IllegalArgumentException("Argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
}
}
}
} // end of methods for
}
if (ProtocolUtils.isGeneric(generic)) {
map.put(GENERIC_KEY, generic);
map.put(METHODS_KEY, ANY_VALUE);
} else {
String revision = Version.getVersion(interfaceClass, version);
if (revision != null && revision.length() > 0) {
map.put(REVISION_KEY, revision);
}
String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
if (methods.length == 0) {
logger.warn("No method found in service interface " + interfaceClass.getName());
map.put(METHODS_KEY, ANY_VALUE);
} else {
map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
}
}
/**
* Here the token value configured by the provider is used to assign the value to ServiceConfig#token
*/
if (ConfigUtils.isEmpty(token) && provider != null) {
token = provider.getToken();
}
if (!ConfigUtils.isEmpty(token)) {
if (ConfigUtils.isDefault(token)) {
map.put(TOKEN_KEY, UUID.randomUUID().toString());
} else {
map.put(TOKEN_KEY, token);
}
}
//init serviceMetadata attachments, ServiceMetadata中的attachments will be transferred to remote side
serviceMetadata.getAttachments().putAll(map);
// export service , 构建URL实例
String host = findConfigedHosts(protocolConfig, registryURLs, map);
Integer port = findConfigedPorts(protocolConfig, name, map);
URL url = new URL(name, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), map);
// You can customize Configurator to append extra parameters
if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
.hasExtension(url.getProtocol())) {
url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
.getExtension(url.getProtocol()).getConfigurator(url).configure(url);
}
//获取scope ,如果没有配置服务的scope时就不暴露服务
String scope = url.getParameter(SCOPE_KEY);
// don't export when none is configured
if (!SCOPE_NONE.equalsIgnoreCase(scope)) {
// export to local if the config is not remote (export to remote only when config is remote)
//如果scope != remote , 就以本地方式export
if (!SCOPE_REMOTE.equalsIgnoreCase(scope)) {
exportLocal(url);
}
// export to remote if the config is not local (export to local only when config is local)
//如果scope不是local,就默认以remote方式export
if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) {
if (CollectionUtils.isNotEmpty(registryURLs)) {
//遍历注册中心的地址。来一个一个的export
for (URL registryURL : registryURLs) {
//if protocol is only injvm ,not register 如果协议为injvm, 就不需要暴露,在同一个jvm内的服务
if (LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
continue;
}
//添加dynamic参数配置
url = url.addParameterIfAbsent(DYNAMIC_KEY, registryURL.getParameter(DYNAMIC_KEY));
//添加监控中心url配置, 可选
URL monitorUrl = ConfigValidationUtils.loadMonitor(this, registryURL);
if (monitorUrl != null) {
url = url.addParameterAndEncoded(MONITOR_KEY, monitorUrl.toFullString());
}
if (logger.isInfoEnabled()) {
if (url.getParameter(REGISTER_KEY, true)) {
logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
} else {
logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
}
}
// For providers, this is used to enable custom proxy to generate invoker
String proxy = url.getParameter(PROXY_KEY);
if (StringUtils.isNotEmpty(proxy)) {
registryURL = registryURL.addParameter(PROXY_KEY, proxy);
}
// 使用ProxyFactory来生成接口的代理。invoker是一个执行者
Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
//生成Invoker的包装类,实现了Invoker接口,其本身也是一个Invoker,只是在invoker的基础上扩展了ServiceConfig
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
//使用Protocol来暴露服务接口到对应的注册中心
// private static final Protocol PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
//取的是Protocol 接口的代理类的实例。SPI的时候讲过了执行代理类中的方法的时候,是从url中取参数的。
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
//将这个Exporter实例存入ServiceConfig中的exporters属性中
exporters.add(exporter);
}
} else {
if (logger.isInfoEnabled()) {
logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
}
Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url);
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
exporters.add(exporter);
}
MetadataUtils.publishServiceDefinition(url);
}
}
this.urls.add(url);
}
PROTOCOL.export(wrapperInvoker),默认协议是dubbo。因此调用的是 DubboProtocol.export函数。 做了两件事情: ①开启服务 ②注册到注册中心
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
URL url = invoker.getUrl();
String key = serviceKey(url);
DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
exporterMap.put(key, exporter);
Boolean isStubSupportEvent = url.getParameter(STUB_EVENT_KEY, DEFAULT_STUB_EVENT);
Boolean isCallbackservice = url.getParameter(IS_CALLBACK_SERVICE, false);
if (isStubSupportEvent && !isCallbackservice) {
String stubServiceMethods = url.getParameter(STUB_EVENT_METHODS_KEY);
if (stubServiceMethods == null || stubServiceMethods.length() == 0) {
if (logger.isWarnEnabled()) {
logger.warn(new IllegalStateException("consumer [" + url.getParameter(INTERFACE_KEY) +
"], has set stubproxy support event ,but no stub methods founded."));
}
}
}
openServer(url);//开启服务
optimizeSerialization(url);//注册
return exporter;
}