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

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

接着上篇继续分析doExport()

。。。前面的部分就做了一件事,将相关配置信息转换成URL类。。。
下面的两行也就做了一件事,委托configHandler,生成exporter对象 1 ConfigHandler configHandler = ExtensionLoader.getExtensionLoader(ConfigHandler.class).getExtension(MotanConstants.DEFAULT_VALUE); exporters.add(configHandler.export(interfaceClass, ref, urls));
 public <T> Exporter<T> export(Class<T> interfaceClass, T ref, List<URL> registryUrls) {

      // embed的属性,embed则是保存了服务URL
String serviceStr = StringTools.urlDecode(registryUrls.get(0).getParameter(URLParamType.embed.getName()));
URL serviceUrl = URL.valueOf(serviceStr); // export service String protocolName = serviceUrl.getParameter(URLParamType.protocol.getName(), URLParamType.protocol.getValue());
// 查找协议,即DefaultRpcProtocol对象
Protocol orgProtocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(protocolName);
// 创建提供service的provider
Provider<T> provider = getProvider(orgProtocol, ref, serviceUrl, interfaceClass);
// 利用protocol decorator来增加filter特性
Protocol protocol = new ProtocolFilterDecorator(orgProtocol);
// 暴露过程 它是委托给具体协议,调用协议类(即DefaultRpcProtocol对象)的export方法来进行暴露
Exporter<T> exporter = protocol.export(provider, serviceUrl); // register service 暴露之后注册服务,注意这里的先后顺序。为了保证,通知上线时,已经完成暴露的过程。
register(registryUrls, serviceUrl); return exporter;
}

我们进到第13行的方法

     public <T> Exporter<T> export(Provider<T> provider, URL url) {
      // decorateWithFilter(provider, url)的结果为参数provider本身,filter为null
return protocol.export(decorateWithFilter(provider, url), url);
}
 public <T> Exporter<T> export(Provider<T> provider, URL url) {
if (url == null) {
throw new MotanFrameworkException(this.getClass().getSimpleName() + " export Error: url is null",
MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR);
} if (provider == null) {
throw new MotanFrameworkException(this.getClass().getSimpleName() + " export Error: provider is null, url=" + url,
MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR);
}

       // 这里的url是服务url
String protocolKey = MotanFrameworkUtil.getProtocolKey(url); synchronized (exporterMap) {
Exporter<T> exporter = (Exporter<T>) exporterMap.get(protocolKey); if (exporter != null) {
throw new MotanFrameworkException(this.getClass().getSimpleName() + " export Error: service already exist, url=" + url,
MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR);
}

// 在DefaultRpcExporter的类初始化中,根据当前系统的SPI配置,找到EndpointFactory的实现类,并创建一个Server对象,
         // 由Server对象的server.open()最终完成transport的网络层暴露。
// 网络层暴露的Netty部分,暂时略过
22 exporter = createExporter(provider, url);
23 exporter.init(); exporterMap.put(protocolKey, exporter); LoggerUtil.info(this.getClass().getSimpleName() + " export Success: url=" + url); return exporter;
} }

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

registryUrls是zookeeper的注册地址,serviceUrl则是提供需要的参数。
 private void register(List<URL> registryUrls, URL serviceUrl) {

         for (URL url : registryUrls) {
// 根据check参数的设置,register失败可能会抛异常,上层应该知晓
         // SPI生成ZookeeperRegistryFactory
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getExtension(url.getProtocol());
if (registryFactory == null) {
throw new MotanFrameworkException(new MotanErrorMsg(500, MotanErrorMsgConstant.FRAMEWORK_REGISTER_ERROR_CODE,
"register error! Could not find extension for registry protocol:" + url.getProtocol()
+ ", make sure registry module for " + url.getProtocol() + " is in classpath!"));
}
Registry registry = registryFactory.getRegistry(url);
registry.register(serviceUrl);
}
}

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

 public Registry getRegistry(URL url) {
String registryUri = getRegistryUri(url);
try {
lock.lock();
Registry registry = registries.get(registryUri);
if (registry != null) {
return registry;
}
// zookeeper的相关代码封装在下面方法中
registry = createRegistry(url);
if (registry == null) {
throw new MotanFrameworkException("Create registry false for url:" + url, MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR);
}
registries.put(registryUri, registry);
return registry;
} catch (Exception e) {
throw new MotanFrameworkException("Create registry false for url:" + url, e, MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR);
} finally {
lock.unlock();
}
}

深入学习Motan系列(三)——服务发布的更多相关文章

  1. 深入学习Motan系列(二)——服务发布

    闯关经验: 袋鼠走过了第一关,顺利搭建出了Demo,信心爆棚.不过之后,心想怎么去研究这个框架呢.查了一下,官方文档,好像没什么东西可以研究啊.后来,又搜了搜博客,因为这是微博的框架嘛,所以搜索时用百 ...

  2. 深入学习Motan系列(四)—— 客户端

    困惑的袋鼠,对框架的把握有些茫然,但是仍然一步步向前,行动总比一直迷茫停止不前要好,您说呢,各位客官? 这篇开始客户端的分析.有些地方的代码,就不每段都标出了,中间有跳跃的地方,请自己对照代码来看.鄙 ...

  3. 深入学习Motan系列(一)——入门及知识zookeeper储备

    背景以及说明: 最近逮到个RPC框架,打算深入学习,框架千千万,只有懂得内部原理,才能应对复杂的业务,进行自定义化系统. 这个系列的Motan文章也是自己慢慢摸索的轨迹,将这个过程记录下来,一是提升自 ...

  4. 深入学习Motan系列(五)—— 序列化与编码协议

    一.序列化 1.什么是序列化和反序列化? 序列化:将对象变成有序的字节流,里面保存了对象的状态和相关描述信息. 反序列化:将有序的字节流恢复成对象. 一句话来说,就是对象的保存与恢复. 为什么需要这个 ...

  5. ActiveMQ入门系列三:发布/订阅模式

    在上一篇<ActiveMQ入门系列二:入门代码实例(点对点模式)>中提到了ActiveMQ中的两种模式:点对点模式(PTP)和发布/订阅模式(Pub & Sub),详细介绍了点对点 ...

  6. RabbitMQ学习笔记(三) 发布与订阅

    发布与订阅 在我们使用手机发送消息的时候,即可以选择给单个手机号码发送消息,也可以选择多个手机号码,群发消息. 前面学习工作队列的时候,我们使用的场景是一个消息只能被一个消费者程序实例接收并处理,但是 ...

  7. Dubbo源码学习总结系列三 dubbo-cluster集群模块

    Dubbo集群模块的目的是将集群Invokers构造一个透明的Invoker对象,其中包含了容错机制.负载均衡.目录服务(服务地址集合).路由机制等,为RPC层提供高可用.高并发.自动发现.可治理的S ...

  8. Redis系列(三)-Redis发布订阅及客户端编程

    阅读目录 发布订阅模型 Redis中的发布订阅 客户端编程示例 0.3版本Hredis 发布订阅模型 在应用级其作用是为了减少依赖关系,通常也叫观察者模式.主要是把耦合点单独抽离出来作为第三方,隔离易 ...

  9. Telegram学习解析系列(三) : Build Telegram报错分析总结

    正好通过这次 Telegram 的运行,很想把常见的项目运行的错误好好的总结一下,在前面的博客中,又星星散散的总结过错误和一些警告的消除方法,这次把错误处理一下,还有Telegram项目中有999+的 ...

随机推荐

  1. MyBatis进阶(三)

    MyBatis批量新增数据 1. 传统的JDBC批量插入数据 使用for循环 创建连接 获取连接 创建sql语句,交给连接 使用for循环新增数据 提交连接 使用批处理 两者都存在严重的效率问题,代码 ...

  2. 3、zabbix配置入门

    Zabbix模板 zabbix组件:    zabbix-server    zabbix-database    zabbix-web    zabbix-agent    zabbix-proxy ...

  3. MapReduce编程:平均成绩

    问题描述 现在有三个文件分别代表学生的各科成绩,编程求各位同学的平均成绩.                     编程思想 map函数将姓名作为key,成绩作为value输出,reduce根据key ...

  4. [BOZJ2721]樱花

    题目求\(\frac{1}{x}+\frac{1}{y}=\frac{1}{n!}\)已知n, x和y的正整数解的个数 设z=\(n!\) \(\frac{1}{x}+\frac{1}{y}=\fra ...

  5. 两个python安装模块后 ImportError: No module named

    问题描述:我的电脑安装了默认的arcgis自带的python,还自己安装了anaconda,所以有两个位置的python2.7 我自己使用arcgis的程序的时候,调用默认的那些是可以用的,但想使用d ...

  6. DAY13 迭代器与生成器

    一.迭代器 定义:器:包含了多个值的容器 迭代:循环反馈(一次从容器中取出一个值) 迭代器:从装有多个值的容器中一次取出一个值给外界 优点:不依赖索引,完成取值 缺点:不能计算长度,不能指定位取值(只 ...

  7. C++类的大小计算

    转自http://www.tuicool.com/articles/uiUJry 一个空的class在内存中多少字节?如果加入一个成员函数后是多大?这个成员函数存储在内存中什么部分? 一个Class对 ...

  8. HDU - 1575——矩阵快速幂问题

    HDU - 1575 题目: A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973.  Input数据的第一行是一个T,表示有T组数据. 每组数据的第一行有n( ...

  9. 『TensorFlow』SSD源码学习_其二:基于VGG的SSD网络前向架构

    Fork版本项目地址:SSD 参考自集智专栏 一.SSD基础 在分类器基础之上想要识别物体,实质就是 用分类器扫描整张图像,定位特征位置 .这里的关键就是用什么算法扫描,比如可以将图片分成若干网格,用 ...

  10. netty-socketio(一)之helloworld,与springboot整合

    netty-socketio是一个开源的Socket.io服务器端的一个java的实现, 它基于Netty框架. 1.参考资料 (1)netty-socketio项目github地址: https:/ ...