• 深入学习Motan系列(三)——服务发布


    袋鼠回头看了看文章,有些啰嗦,争取语音简练,不断提高表达力!袋鼠奋起直追!

    注:此篇文章,暂时为了以后时间线排序的需要,暂时发表出来,可是仍然有许多地方需要改写。自己打算把服务端发布,客户端订阅都搞定后,再修改这部分。

    接着上篇继续分析doExport()

    。。。前面的部分就做了一件事,将相关配置信息转换成URL类。。。
    下面的两行也就做了一件事,委托configHandler,生成exporter对象

    1
    ConfigHandler configHandler = ExtensionLoader.getExtensionLoader(ConfigHandler.class).getExtension(MotanConstants.DEFAULT_VALUE); 2 3 exporters.add(configHandler.export(interfaceClass, ref, urls));
     1 public <T> Exporter<T> export(Class<T> interfaceClass, T ref, List<URL> registryUrls) {
     2 
          // embed的属性,embed则是保存了服务URL 3 String serviceStr = StringTools.urlDecode(registryUrls.get(0).getParameter(URLParamType.embed.getName())); 4 URL serviceUrl = URL.valueOf(serviceStr); 5 6 // export service 7 8 String protocolName = serviceUrl.getParameter(URLParamType.protocol.getName(), URLParamType.protocol.getValue());
    // 查找协议,即DefaultRpcProtocol对象
    9 Protocol orgProtocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(protocolName);
    // 创建提供service的provider
    10 Provider<T> provider = getProvider(orgProtocol, ref, serviceUrl, interfaceClass); 11 // 利用protocol decorator来增加filter特性 12 Protocol protocol = new ProtocolFilterDecorator(orgProtocol);
    // 暴露过程 它是委托给具体协议,调用协议类(即DefaultRpcProtocol对象)的export方法来进行暴露
    13 Exporter<T> exporter = protocol.export(provider, serviceUrl); 14 15 // register service 暴露之后注册服务,注意这里的先后顺序。为了保证,通知上线时,已经完成暴露的过程。 16 register(registryUrls, serviceUrl); 17 18 return exporter; 19 }

    我们进到第13行的方法

    1     public <T> Exporter<T> export(Provider<T> provider, URL url) {
          // decorateWithFilter(provider, url)的结果为参数provider本身,filter为null
    2 return protocol.export(decorateWithFilter(provider, url), url); 3 }
     1 public <T> Exporter<T> export(Provider<T> provider, URL url) {
     2         if (url == null) {
     3             throw new MotanFrameworkException(this.getClass().getSimpleName() + " export Error: url is null",
     4                     MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR);
     5         }
     6 
     7         if (provider == null) {
     8             throw new MotanFrameworkException(this.getClass().getSimpleName() + " export Error: provider is null, url=" + url,
     9                     MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR);
    10         }
    11 
           // 这里的url是服务url 12 String protocolKey = MotanFrameworkUtil.getProtocolKey(url); 13 14 synchronized (exporterMap) { 15 Exporter<T> exporter = (Exporter<T>) exporterMap.get(protocolKey); 16 17 if (exporter != null) { 18 throw new MotanFrameworkException(this.getClass().getSimpleName() + " export Error: service already exist, url=" + url, 19 MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR); 20 } 21
    // 在DefaultRpcExporter的类初始化中,根据当前系统的SPI配置,找到EndpointFactory的实现类,并创建一个Server对象,
             // 由Server对象的server.open()最终完成transport的网络层暴露。
    // 网络层暴露的Netty部分,暂时略过 22 exporter = createExporter(provider, url); 23 exporter.init();
    24 25 exporterMap.put(protocolKey, exporter); 26 27 LoggerUtil.info(this.getClass().getSimpleName() + " export Success: url=" + url); 28 29 return exporter; 30 } 31 32 33 }

    接下来,是具体的服务注册部分。

    registryUrls是zookeeper的注册地址,serviceUrl则是提供需要的参数。
     1 private void register(List<URL> registryUrls, URL serviceUrl) {
     2 
     3         for (URL url : registryUrls) {
     4             // 根据check参数的设置,register失败可能会抛异常,上层应该知晓
             // SPI生成ZookeeperRegistryFactory
    5 RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getExtension(url.getProtocol()); 6 if (registryFactory == null) { 7 throw new MotanFrameworkException(new MotanErrorMsg(500, MotanErrorMsgConstant.FRAMEWORK_REGISTER_ERROR_CODE, 8 "register error! Could not find extension for registry protocol:" + url.getProtocol() 9 + ", make sure registry module for " + url.getProtocol() + " is in classpath!")); 10 } 11 Registry registry = registryFactory.getRegistry(url); 12 registry.register(serviceUrl); 13 } 14 }

    根据url得到注册地址的字符串,然后缓存中查询,没有的话,初始化生成ZookeeperRegistry的实例,并返回。

     1 public Registry getRegistry(URL url) {
     2         String registryUri = getRegistryUri(url);
     3         try {
     4             lock.lock();
     5             Registry registry = registries.get(registryUri);
     6             if (registry != null) {
     7                 return registry;
     8             }
    // zookeeper的相关代码封装在下面方法中
    9 registry = createRegistry(url); 10 if (registry == null) { 11 throw new MotanFrameworkException("Create registry false for url:" + url, MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR); 12 } 13 registries.put(registryUri, registry); 14 return registry; 15 } catch (Exception e) { 16 throw new MotanFrameworkException("Create registry false for url:" + url, e, MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR); 17 } finally { 18 lock.unlock(); 19 } 20 }
  • 相关阅读:
    计算机为什么要从 0 开始计数?
    MySQL索引结构为什么是B+树
    expdp导出报错ORA-39127
    expdp 跳过坏块
    (转)没有索引导致的DIRECT PATH READ
    Python的实用场景有哪些
    Oracle索引修复 ,ORA-00600: internal error code, arguments: [6200],
    CentOS7.6静默安装19C实例脚本 ORA-27125 [FATAL] [DBT-10322]
    ORA-00313: 无法打开日志组
    cursor: pin S wait on X等待事件的处理过程(转载)
  • 原文地址:https://www.cnblogs.com/lihao007/p/9825575.html
Copyright © 2020-2023  润新知