随着服务化的进一步发展,服务越来越多,服务之间的调用和依赖关系也越来越 
复杂,诞生了面向服务的架构体系(SOA),
也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通信 
协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架。
就这样为分布式系统的服务治理框架就出现了,Dubbo 也就这样产生了。
SOA与服务治理
SOA(面向服务的体系结构)概念由来已久,在10多年前便开始进入到我们广大软件开发者的视线中。SOA是一种粗粒度、松耦合服务架构,服务之间通过简单、精确定义接口进行通讯,不涉及底层编程接口和通讯模型。SOA可以看作是B/S模型、Web Service技术之后的自然延伸。
服务治理,也称为SOA治理,是指用来管理SOA的采用和实现的过程。以下是在2006年时IBM对于服务治理要点的总结:
服务定义(服务的范围、接口和边界)
服务部署生命周期(各个生命周期阶段)
服务版本治理(包括兼容性)
服务迁移(启用和退役)
服务注册中心(依赖关系)
服务消息模型(规范数据模型)
服务监视(进行问题确定)
服务所有权(企业组织)
服务测试(重复测试)
服务安全(包括可接受的保护范围)
限于当时的技术发展水平,广大软件设计与开发人员对于SOA和服务治理的技术认知还主要停留在Web Service和ESB总线等技术和规范上,并没有真正在软件开发中得以充分落地。
Dubbo开源
直到2011年10月27日,阿里巴巴开源了自己的SOA服务化治理方案的核心框架Dubbo,服务治理和SOA的设计理念开始逐渐在国内软件行业中落地,并被广泛应用。
Dubbo作为阿里巴巴内部的SOA服务化治理方案的核心框架,在2012年时已经每天为2000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。Dubbo自2011年开源后,已被许多非阿里系公司使用,其中既有当当网、网易考拉等互联网公司,也有中国人寿、青岛海尔等传统企业。
Dubbo简介
Dubbo是一个高性能服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案,使得应用可通过高性能RPC实现服务的输出和输入功能,和Spring框架可以无缝集成。
作为一个分布式服务框架,以及SOA治理方案,Dubbo其核心功能主要包括:
#remoting:远程通讯基础,提供对多种NIO框架抽象封装,包括“同步转异步”和“请求-响应”模式的信息交换方式。
#Cluster: 服务框架核心,提供基于接口方法的远程过调用,包括多协议支持,并提供软负载均衡和容错机制的集群支持。
#registry: 服务注册中心,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器
下图来自Dubbo官网,描述了服务注册中心、服务提供方、服务消费方、服务监控中心之间的调用关系,具体如下图所示:


这里我们只是补充一下从源码具体实现角度来看的某些细节方面,包括Invoker、Extensier等方面。任何官方已经介绍过的细节,我们不做画蛇添足,官方文档已经足够详实了,这篇文档的定位是补充实现的相关细节,是基于我在往Dubbo添加web service协议过程中,所碰到过的一些困难。
服务提供者暴露一个服务的详细过程

上图是服务提供者暴露服务的主过程:
首先ServiceConfig类拿到对外提供服务的实际类ref(如:HelloWorldImpl),然后通过ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到Invoker的转化。接下来就是Invoker转换到Exporter的过程。
Dubbo处理服务暴露的关键就在Invoker转换到Exporter的过程(如上图中的红色部分),下面我们以Dubbo和RMI这两种典型协议的实现来进行说明:
Dubbo的实现
Dubbo协议的Invoker转为Exporter发生在DubboProtocol类的export方法,它主要是打开socket侦听服务,并接收客户端发来的各种请求,通讯细节由Dubbo自己实现。
RMI的实现
RMI协议的Invoker转为Exporter发生在RmiProtocol类的export方法,它通过Spring或Dubbo或JDK来实现RMI服务,通讯细节这一块由JDK底层来实现,这就省了不少工作量。
服务消费者消费一个服务的详细过程

上图是服务消费的主过程:
首先ReferenceConfig类的init方法调用Protocol的refer方法生成Invoker实例(如上图中的红色部分),这是服务消费的关键。接下来把Invoker转换为客户端需要的接口(如:HelloWorld)。
关于每种协议如RMI/Dubbo/Web service等它们在调用refer方法生成Invoker实例的细节和上一章节所描述的类似。
满眼都是Invoker
由于Invoker是Dubbo领域模型中非常重要的一个概念,很多设计思路都是向它靠拢。这就使得Invoker***在整个实现代码里,对于刚开始接触Dubbo的人,确实容易给搞混了。
下面我们用一个精简的图来说明最重要的两种Invoker:服务提供Invoker和服务消费Invoker:

为了更好的解释上面这张图,我们结合服务消费和提供者的代码示例来进行说明:
服务消费者代码
#服务消费者代码 public class DemoClientAction { private DemoService demoService; public void setDemoService(DemoService demoService) { this.demoService = demoService; } public void start() { String hello = demoService.sayHello("world" + i); } }
上面代码中的’DemoService’就是上图中服务消费端的proxy,用户代码通过这个proxy调用其对应的Invoker(DubboInvoker、 HessianRpcInvoker、 InjvmInvoker、 RmiInvoker、 WebServiceInvoker中的任何一个),而该Invoker实现了真正的远程服务调用。
#服务提供者代码 public class DemoServiceImpl implements DemoService { public String sayHello(String name) throws RemoteException { return "Hello " + name; } }
上面这个类会被封装成为一个AbstractProxyInvoker实例,并新生成一个Exporter实例。这样当网络通讯层收到一个请求后,会找到对应的Exporter实例,并调用它所对应的AbstractProxyInvoker实例,从而真正调用了服务提供者的代码。
Dubbo里还有一些其他的Invoker类,但上面两种是最重要的。
Extensier的完整分析
Extensier是Dubbo中一个非常重要的类,刚接触Dubbo源码的人看这个类的时候也多少会有点困惑,这个类非常重要,它就像是厨房里的“大厨”,按照用户的随时需要把各种“食材”烹调出来。
我们结合具体代码详细说一下Extensier的实现,下面是ServiceConfig类里的一行代码:
private static final Protocol protocol = Extensier.getExtensier(Protocol.class).getAdaptiveExtension();
上面代码的程序流程图如下所示(假定是第一次执行这行代码):

在这个过程中最重要的两个方法是getExtensionClasses和createAdaptiveExtensionClass(图中红色部分),下面详细对这两个方法进行分析:
#getExtensionClasses
这个方法主要读取META-INF/services/目录下对应文件内容,在本示例代码中,是读取META-INF/services/com.alibaba.dubbo.rpc.Protocol文件中的内容,具体内容如下:
com.alibaba.dubbo.registry.support.RegistryProtocol com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol com.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocol它分析该文件中的每一行(每一行对应一个类),分析这些类,如果发现有哪个类的Annotation是@Adaptive,则找到对应的AdaptiveClass了,但由于Protocol文件里没有哪个类的Annotation是@Adaptive,所以在这个例子中该方法没找到对应的AdaptiveClass。
br/>它分析该文件中的每一行(每一行对应一个类),分析这些类,如果发现有哪个类的Annotation是@Adaptive,则找到对应的AdaptiveClass了,但由于Protocol文件里没有哪个类的Annotation是@Adaptive,所以在这个例子中该方法没找到对应的AdaptiveClass。
该方法是在getExtensionClasses方法找不到AdaptiveClass的情况下被调用,该方法主要是通过字节码的方式在内存中新生成一个类,它具有AdaptiveClass的功能,Protocol就是通过这种方式获得AdaptiveClass类的。

©著作权归作者所有:来自51CTO博客作者mb5fcf1f02dcdd1的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. GlusterFs 启动报错,调试方法和处理
  2. 一个正确的编程学习方法
  3. 世界上有哪些代码量很少,但很牛逼很经典的算法或项目案例?
  4. RFM分析-用户价值细分的精准运营方法
  5. 双指针的魅力!四行代码求解「盛最多水的容器」
  6. 「总结」LeetCode 上一行代码就能解决的智力算法题
  7. 超简单的博弈算法题,一行代码解决!
  8. GitHub的注册,代码仓库的创建,用小乌龟上传代码(个人认为比较适合新
  9. 再来 6 个例子教你重构 Python 代码

随机推荐

  1. android adb配置环境变量
  2. Android ADB server didn't ACK * failed
  3. Android共享数据ContentProvider的使用
  4. 求 在独立service 中 调用contentprovide
  5. Android 解决setRequestedOrientation之
  6. 10.ScrollView
  7. Android线程调度机制
  8. 识别你的手机 Android的属性系统
  9. android View 重绘机制
  10. Android cocos2d-x开发(三)之创建Android工