Dubbo框架学习笔记(三)
来源:互联网 发布:数据库方案 编辑:程序博客网 时间:2024/05/28 17:07
Dubbo源码地址:https://github.com/alibaba/dubbo
Dubbo开发指南:http://dubbo.io/Developer+Guide-zh.htm
Dubbo服务发布
发布活动图:
服务发布方在spring的配置文件中配置如下:
<bean id="demoService"class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" />
上面是在spring中配置的服务的具体实现,是spring中的一个普通的bean。
<dubbo:serviceinterface="com.alibaba.dubbo.demo.DemoService" ref=”demoService”/>
在上面的配置中,spring容器在启动的过程中会解析自定义的schema元素dubbo并转换成实际的配置实现ServiceBean ,并把服务暴露出去
ServiceBean除了继承dubbo自己的配置抽象类(ServiceConfig)以外,还实现了一系列的spring接口用来参与到spring容器的启动以及bean的创建过程中去。由于spring实例化的ServiceBean是单例模式的,在Spring的容器ApplicationContext的启动过程refresh过程中最后第二步会预先初始化单例的bean, 在bean的初始化过程会设置beanName, 设置容器applicationContext, 回调 InitializingBean的afterPropertiesSet。
最后一步finishRefresh会触发ContextRefreshedEvent事件, 而ServiceBean实现了ApplicationListener接口监听了此事件, 而在之前一步实例化的ServiceBean注册了这个事件,所以ServiceBean的onApplicationEvent(ApplicationEvent event)方法被触发, 在这个方法中触发了export方法来暴露服务。
public void afterPropertiesSet() throws Exception { //如果没有配置provider if (getProvider() == null) { //获取IOC容器里的所有provider Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false); if (providerConfigMap != null && providerConfigMap.size() > 0) { Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); if ((protocolConfigMap == null || protocolConfigMap.size() == 0) && providerConfigMap.size() > 1) { // 兼容旧版本 List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>(); for (ProviderConfig config : providerConfigMap.values()) { if (config.isDefault() != null && config.isDefault().booleanValue()) { providerConfigs.add(config); } } //关联所有providers if (providerConfigs.size() > 0) { setProviders(providerConfigs); } } else { ProviderConfig providerConfig = null; for (ProviderConfig config : providerConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (providerConfig != null) { throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config); } providerConfig = config; } } if (providerConfig != null) { setProvider(providerConfig); } } } } //如果没有配置application,且没有配置provider if (getApplication() == null && (getProvider() == null || getProvider().getApplication() == null)) { //获取所有applications Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false); if (applicationConfigMap != null && applicationConfigMap.size() > 0) { ApplicationConfig applicationConfig = null; for (ApplicationConfig config : applicationConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (applicationConfig != null) { throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config); } applicationConfig = config; } } //关联application if (applicationConfig != null) { setApplication(applicationConfig); } } } //如果没有配置module,且没有配置provider if (getModule() == null && (getProvider() == null || getProvider().getModule() == null)) { Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false); if (moduleConfigMap != null && moduleConfigMap.size() > 0) { ModuleConfig moduleConfig = null; for (ModuleConfig config : moduleConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (moduleConfig != null) { throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config); } moduleConfig = config; } } //关联module if (moduleConfig != null) { setModule(moduleConfig); } } } //如果没有配置registries,且没有配置provider if ((getRegistries() == null || getRegistries().size() == 0) && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0) && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) { Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false); if (registryConfigMap != null && registryConfigMap.size() > 0) { List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>(); for (RegistryConfig config : registryConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { registryConfigs.add(config); } } //关联registries if (registryConfigs != null && registryConfigs.size() > 0) { super.setRegistries(registryConfigs); } } } //如果没有配置monitor,且没有配置provider if (getMonitor() == null && (getProvider() == null || getProvider().getMonitor() == null) && (getApplication() == null || getApplication().getMonitor() == null)) { Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false); if (monitorConfigMap != null && monitorConfigMap.size() > 0) { MonitorConfig monitorConfig = null; for (MonitorConfig config : monitorConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (monitorConfig != null) { throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config); } monitorConfig = config; } } //关联monitor if (monitorConfig != null) { setMonitor(monitorConfig); } } } //如果没有配置protocol,且没有配置provider if ((getProtocols() == null || getProtocols().size() == 0) && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) { Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>(); for (ProtocolConfig config : protocolConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { protocolConfigs.add(config); } } //关联protocol if (protocolConfigs != null && protocolConfigs.size() > 0) { super.setProtocols(protocolConfigs); } } } //如果没有配置path if (getPath() == null || getPath().length() == 0) { if (beanName != null && beanName.length() > 0 && getInterface() != null && getInterface().length() > 0 && beanName.startsWith(getInterface())) { setPath(beanName); } } //暴露provider if (! isDelay()) { export(); } }
ServiceConfig.doExportUrls()执行具体的export过程
1. loadRegistries(true)
checkRegistry如果xml中没有配置注册中,从dubbo.properties中读取配置,构建RegistryConfig对象并赋值
构建注册中心URL统一数据模式集合List<registryUrl>
2. 因为dubbo支持多协议配置,遍历所有协议分别根据不同的协议把服务export到不同的注册中心上去
a) 判断是否是泛型暴露
b) 根据协议构建暴露服务的统一数据模型URL
c) 配置的了monitor加载monitor,并给URL设置MONITOR_KEY
d) 给注册中regitryUrl设置EXPORT_KEY值为前面构建的暴露服务url
e) 根据服务具体实现,实现接口以及regitryUrl从代理工厂ProxyFactory获取代理Invoker(继承于AbstractProxyInvoker),它是对具体实现的一种代理
f) Protocol.export(invoker) 暴露服务invoker
Invoker包含上一步传入的RegistryUrl, registryUrl的protocol值为registry
ProtocolListenerWrapper和ProtocolFilterWrapper对于协议为REGISTRY_PROTOCOL直接跳过,最终由RegistryProtocol处理export的过程
public synchronized void export() { //如果provider没有配置 if (provider != null) { //如果exporter没有配置使用provider所关联的exporter if (export == null) { export = provider.getExport(); } //如果delay(延迟暴露)没有配置,获取provider的delay if (delay == null) { delay = provider.getDelay(); } } //如果不需要暴露接口则直接返回 if (export != null && ! export.booleanValue()) { return; } //如果延迟暴露的时间(毫秒级)是存在的,开启线程并等待delay毫秒后开始暴露接口,否则直接执行暴露接口过程 if (delay != null && delay > 0) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(delay); } catch (Throwable e) { } doExport(); } }); thread.setDaemon(true); thread.setName("DelayExportServiceThread"); thread.start(); } else { doExport(); } }
protected synchronized void doExport() { //如果不需要暴露接口则抛出异常 if (unexported) { throw new IllegalStateException("Already unexported!"); } //如果已经暴露则不需要重复暴露 if (exported) { return; } exported = true; //如果interfaceName没配置(这样dubbo就无法找到需要暴露的service对象)则抛出异常 if (interfaceName == null || interfaceName.length() == 0) { throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!"); } checkDefault(); //provider已经配置的情况下,如果application、module、registries、monitor、protocol中有未配置的均可以从provider获取 if (provider != null) { if (application == null) { application = provider.getApplication(); } if (module == null) { module = provider.getModule(); } if (registries == null) { registries = provider.getRegistries(); } if (monitor == null) { monitor = provider.getMonitor(); } if (protocols == null) { protocols = provider.getProtocols(); } } if (module != null) { if (registries == null) { registries = module.getRegistries(); } if (monitor == null) { monitor = module.getMonitor(); } } if (application != null) { if (registries == null) { registries = application.getRegistries(); } if (monitor == null) { monitor = application.getMonitor(); } } if (ref instanceof GenericService) { interfaceClass = GenericService.class; if (StringUtils.isEmpty(generic)) { generic = Boolean.TRUE.toString(); } } else { try { interfaceClass = Class.forName(interfaceName, true, Thread.currentThread() .getContextClassLoader()); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } checkInterfaceAndMethods(interfaceClass, methods); checkRef(); generic = Boolean.FALSE.toString(); } //如果是本地服务 if(local !=null){ //如果是本地服务在interfaceName属性后面加上Local if(local=="true"){ local=interfaceName+"Local"; } Class<?> localClass; try { //加载service localClass = ClassHelper.forNameWithThreadContextClassLoader(local); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } if(!interfaceClass.isAssignableFrom(localClass)){ throw new IllegalStateException("The local implemention class " + localClass.getName() + " not implement interface " + interfaceName); } } //如果是远程服务 if(stub !=null){ if(stub=="true"){ stub=interfaceName+"Stub"; } Class<?> stubClass; try { //加载service stubClass = ClassHelper.forNameWithThreadContextClassLoader(stub); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } if(!interfaceClass.isAssignableFrom(stubClass)){ throw new IllegalStateException("The stub implemention class " + stubClass.getName() + " not implement interface " + interfaceName); } } //检查application checkApplication(); //检查registries checkRegistry(); //检查protocol checkProtocol(); //将所有这些对象的属性关联到provider appendProperties(this); checkStubAndMock(interfaceClass); if (path == null || path.length() == 0) { path = interfaceName; } //暴露地址 doExportUrls(); }
private void doExportUrls() { //将注册的所有url匹配上对应的协议在服务端暴露出来 List<URL> registryURLs = loadRegistries(true); for (ProtocolConfig protocolConfig : protocols) { doExportUrlsFor1Protocol(protocolConfig, registryURLs); } }
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) { //如果没配置protocol则默认使用dubbo协议 String name = protocolConfig.getName(); if (name == null || name.length() == 0) { name = "dubbo"; } //获取主机地址 String host = protocolConfig.getHost(); if (provider != null && (host == null || host.length() == 0)) { host = provider.getHost(); } boolean anyhost = false; if (NetUtils.isInvalidLocalHost(host)) { anyhost = true; try { host = InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { logger.warn(e.getMessage(), e); } if (NetUtils.isInvalidLocalHost(host)) { if (registryURLs != null && registryURLs.size() > 0) { for (URL registryURL : registryURLs) { try { //创建socket,连接到注册中心 Socket socket = new Socket(); try { SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort()); socket.connect(addr, 1000); //获取服务所在主机地址 host = socket.getLocalAddress().getHostAddress(); break; } finally { try { socket.close(); } catch (Throwable e) {} } } catch (Exception e) { logger.warn(e.getMessage(), e); } } } if (NetUtils.isInvalidLocalHost(host)) { host = NetUtils.getLocalHost(); } } } //获取协议接口号 Integer port = protocolConfig.getPort(); if (provider != null && (port == null || port == 0)) { port = provider.getPort(); } final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort(); if (port == null || port == 0) { port = defaultPort; } if (port == null || port <= 0) { port = getRandomPort(name); if (port == null || port < 0) { port = NetUtils.getAvailablePort(defaultPort); putRandomPort(name, port); } logger.warn("Use random available port(" + port + ") for protocol " + name); } //获取application、module、provider、protocol、exporter、registries、monitor所有属性 Map<String, String> map = new HashMap<String, String>(); if (anyhost) { map.put(Constants.ANYHOST_KEY, "true"); } map.put(Constants.SIDE_KEY, Constants.PROVIDER_SIDE); map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion()); map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); if (ConfigUtils.getPid() > 0) { map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); } appendParameters(map, application); appendParameters(map, module); appendParameters(map, provider, Constants.DEFAULT_KEY); appendParameters(map, protocolConfig); appendParameters(map, this); if (methods != null && methods.size() > 0) { for (MethodConfig method : methods) { 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 (arguments != null && arguments.size() > 0) { for (ArgumentConfig argument : arguments) { //类型自动转换. if(argument.getType() != null && argument.getType().length() >0){ Method[] methods = interfaceClass.getMethods(); //遍历所有方法 if(methods != null && methods.length > 0){ for (int i = 0; i < methods.length; i++) { String methodName = methods[i].getName(); //匹配方法名称,获取方法签名. if(methodName.equals(method.getName())){ Class<?>[] argtypes = methods[i].getParameterTypes(); //一个方法中单个callback if (argument.getIndex() != -1 ){ if (argtypes[argument.getIndex()].getName().equals(argument.getType())){ appendParameters(map, argument, method.getName() + "." + argument.getIndex()); }else { throw new IllegalArgumentException("argument config error : the index attribute and type attirbute not match :index :"+argument.getIndex() + ", type:" + argument.getType()); } } else { //一个方法中多个callback for (int j = 0 ;j<argtypes.length ;j++) { Class<?> argclazz = argtypes[j]; if (argclazz.getName().equals(argument.getType())){ appendParameters(map, argument, method.getName() + "." + j); if (argument.getIndex() != -1 && argument.getIndex() != j){ throw new IllegalArgumentException("argument config error : the index attribute and type attirbute not match :index :"+argument.getIndex() + ", type:" + argument.getType()); } } } } } } } }else if(argument.getIndex() != -1){ 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", generic); map.put("methods", Constants.ANY_VALUE); } else { String revision = Version.getVersion(interfaceClass, version); if (revision != null && revision.length() > 0) { map.put("revision", revision); } String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames(); if(methods.length == 0) { logger.warn("NO method found in service interface " + interfaceClass.getName()); map.put("methods", Constants.ANY_VALUE); } else { map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ",")); } } if (! ConfigUtils.isEmpty(token)) { if (ConfigUtils.isDefault(token)) { map.put("token", UUID.randomUUID().toString()); } else { map.put("token", token); } } if ("injvm".equals(protocolConfig.getName())) { protocolConfig.setRegister(false); map.put("notify", "false"); } // 导出服务 String contextPath = protocolConfig.getContextpath(); if ((contextPath == null || contextPath.length() == 0) && provider != null) { contextPath = provider.getContextpath(); } //创建服务所在url URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map); if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class) .hasExtension(url.getProtocol())) { url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class) .getExtension(url.getProtocol()).getConfigurator(url).configure(url); } String scope = url.getParameter(Constants.SCOPE_KEY); //配置为none不暴露 if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) { //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务) if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) { //暴露的地址是localhost所以远端无法访问 exportLocal(url); } //如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露远程服务) if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){ if (logger.isInfoEnabled()) { logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url); } if (registryURLs != null && registryURLs.size() > 0 && url.getParameter("register", true)) { for (URL registryURL : registryURLs) { url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic")); URL monitorUrl = loadMonitor(registryURL); if (monitorUrl != null) { url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString()); } if (logger.isInfoEnabled()) { logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL); } //获取invoker Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString())); //根据协议将invoker暴露成exporter,具体过程是创建一个ExchangeServer,它会绑定一个ServerSocket到配置端口 Exporter<?> exporter = protocol.export(invoker); //将创建的exporter放进链表便于管理 exporters.add(exporter); } } else { Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url); Exporter<?> exporter = protocol.export(invoker); exporters.add(exporter); } } } this.urls.add(url); }
RegistryProtocol暴露服务过程
这里传入的Invoker是由RegistryUrl从ProxyFactory得到的Invoker
1. 从Invoker获取providerUrl,在获取cacheKey, 根据cacheKey获取本地缓存的ExporterChangeableWrapper(exporter代理,建立返回的exporter与protocol export出的exporter的对应关系), 如果存在返回。
2. 如果不存在,根据传入的 Invoker获取providerUrl, 在构建InvokerDelegete(originInvoker, providerUrl)
3. Protocol.exprot(invokerDelegete) 根据providerUrl 的协议(一般是dubbo协议)通过Protocol的设配类暴露服务,得到exporter
4. 利用providerUr导出的exporter和invoker构建对象ExporterChangeableWrapper缓存到本地
5. 由Invoker得到registryUrl。
在根据registryUrl从RegistryFactory获取Registry, 获取RegistryUrl的注册中心协议,这里我们拿zooKeeper协议为例。由dubbo的扩展机制得到的是ZookeeperRegistryFactory,得到注册器为ZookeeperRegistry
6. 由Invoker获取ProviderUrl在去除不需要在注册中心看到的字段得到registryProviderUrl
7. 注册中心(ZookeeperRegistry)注册registryProviderUrl
Registry.register(registryProviderUrl)
8. 由registryProviderUrl获取overrideSubscribeUrl,在构建OverrideListener
9. registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener) 注册中心订阅这个url, 用来当数据变化通知重新暴露, 哪zookeeper为例,暴露服务会在zookeeper生成一个节点,当节点发生变化的时候会触发overrideSubscribeListener的notify方法重新暴露服务
10. 构建并返回一个新的exporter实例
DubboProtocol暴露服务的过程
1. 从invoker获取统一数据模型url
2. 由url构建serviceKey(一般由端口,接口名,版本,group分组)
如:com.alibaba.dubbo.demo.DemoService:20880 这个是由接口和端口组成的
3. 构建DubboExporter放入本地map做缓存
4. 根据url openserver。 查找本地缓存以key为url.getAddress如果没有ExchangeServer创建。设置heartbeat时间,设置编码解码协议
根据url和ExchangeHandler 绑定server并返回(具体如何绑定专题介绍)
5. 返回DubboExporter对象
所以服务发布过程大致分成3步:
- 获取注册中心信息,构建协议信息,然后将其组合
- 通过ProxyFactory将HelloServiceImpl封装成一个Invoker执行
- 使用Protocol将invoker导出成一个Exporter(包括去注册中心注册服务等)
默默吐槽一下,为什么CSDN的图片上传了老是加载不出来!!
- Dubbo框架学习笔记(三)
- Dubbo框架学习笔记
- Dubbo框架学习笔记(一)
- Dubbo框架学习笔记(二)
- Dubbo框架学习笔记(四)
- dubbo源码 学习笔记(三)
- Dubbo学习笔记(三)------Zookeeper注册中心
- 阿里巴巴分布式服务框架dubbo学习笔记
- 新人学习笔记-Dubbo框架集合
- dubbo 源码学习笔记 (三) —— dubbo引用服务的过程
- dubbo学习笔记 三 架构预览
- Dubbo学习笔记(三) Provider和Consumer
- Mina框架学习笔记(三)
- Mina框架学习笔记(三)
- Mina框架学习笔记(三)
- Volley网络框架学习笔记(三)
- 前端框架angular学习笔记(三)
- Dubbo学习笔记(一)
- Linux中的黏滞位
- 正确理解Java中为何关键词private声明的方法不存在覆盖
- 有关windows环境下eclipse+PyDev+Python时候在Preferences找不到PyDev的错误示范和解决方案
- eclipse常用快捷键
- 大数据IMF传奇行动绝密课程第96课:通过SparkStreaming的foreachRDD把处理后的数据写入外部存储系统中
- Dubbo框架学习笔记(三)
- F
- win10系统找不到以太网该怎么办
- 欢迎使用CSDN-markdown编辑器
- c语言mysql代码
- Java的运行时数据区
- PHP Document解析XML(对比基于事件xml解析)
- servlet: filter的<dispatcher>FORWARD</dispatcher>
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 hrbust 2331 Great Atm