dubbo深刻学习的一些总结

 

Dubbo 源文件主要包含以上这么多包,其中:java

首先对dubbo-2.8.4.jar 源码的一个截图spring

dubbo-common

公共逻辑模块,包括 Util 类和通用模型。网络

dubbo-remoting

远程通信模块,至关于 Dubbo 协议的实现,若是 RPC 用 RMI 协议 则不须要使用此包。并发

Dubbo缺省协议采用单一长链接和NIO异步通信,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的状况。app

缺省协议,使用基于netty3.2.2+hessian3.2.1交互。

    链接个数:单链接
    链接方式:长链接
    传输协议:TCP
    传输方式:NIO异步传输
    序列化:Hessian二进制序列化
    适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者没法压满提供者,尽可能不要用dubbo协议传输大文件或超大字符串。
    适用场景:常规远程服务方法调用负载均衡

一、为何要消费者比提供者个数多
    因dubbo协议采用单一长链接,
    假设网络为千兆网卡(1024Mbit=128MBytae),
    根据测试经验数据每条链接最多只能压满7MByte(不一样的环境可能不同,供参考),
    理论上1个服务提供者须要20个服务消费者才能压满网卡。异步

二、为何不能传大包
    因dubbo协议采用单一长链接,若是每次请求的数据包大小为500KByte,假设网络为千兆网卡(1024Mbit=128MByte),每条链接最大7MByte(不一样的环境可能不同,供参考),
    单个服务提供者的TPS(每秒处理事务数)最大为:128MByte / 500KByte = 262。
    单个消费者调用单个服务提供者的TPS(每秒处理事务数)最大为:7MByte / 500KByte = 14。
    若是能接受,能够考虑使用,不然网络将成为瓶颈。ide

为何采用异步单一长链接:
    由于服务的现状大都是服务提供者少,一般只有几台机器, 而服务的消费者多,可能整个网站都在访问该服务,
    好比Morgan的提供者只有6台提供者,却有上百台消费者,天天有1.5亿次调用, 若是采用常规的hessian服务,服务提供者很容易就被压跨, 经过单一链接,保证单一消费者不会压死提供者,长链接,减小链接握手验证等,
并使用异步IO,复用线程池,防止C10K问题。函数

约束:测试

 参数及返回值需实现Serializable接口

参数及返回值需有无参构造函数(能够是private的)或者有参构造全部函数容许传入null值。

参数及返回值不能自定义实现List, Map, Number, Date, Calendar等接口,只能用JDK自带的实现,由于hessian会作特殊处理,自定义实现类中的属性值都会丢失。
Hessian序列化,只传成员属性值和值的类型,不传方法或静态变量,兼容状况:

 数据通信     状况     结果
    A->B     类A多一种 属性(或者说类B少一种 属性)     不抛异常,A多的那 个属性的值,B没有, 其余正常
    A->B     枚举A多一种 枚举(或者说B少一种 枚举),A使用多 出来的枚举进行传输     抛异常
    A->B     枚举A多一种 枚举(或者说B少一种 枚举),A不使用 多出来的枚举进行传输     不抛异常,B正常接 收数据
    A->B     A和B的属性 名相同,但类型不相同     抛异常
    A->B     serialId 不相同     正常传输

dubbo-rpc

远程调用模块,抽象各类协议,以及动态代理,只包含一对一的调用, 不关心集群的管理。

dubbo-cluster

集群模块,将多个服务提供方假装为一个提供方,包括:负载均衡, 容 错,路由等,集群的地址列表能够是静态配置的,也能够是由注册中心下发。

dubbo-monitor

监控模块,统计服务调用次数,调用时间的,调用链跟踪的服务。

dubbo-container 

容器模块,是一个 Standlone 的容器,以简单的 Main 加载 Spring 启动,由于服务一般不须要 Tomcat/JBoss 等 Web 容器的特性,不必用 Web 容器去加 载服务。

服务容器只是一个简单的Main方法,并加载一个简单的Spring容器,用于暴露服务。 

服务容器的加载内容能够扩展,内置了spring, jetty, log4j等加载,可经过Container扩展点进行扩展

Container 包含:Spring Container    Jetty Container   Log4j Container

简单介绍一下Spring Container的使用  

    1)自动加载META-INF/spring目录下的全部Spring配置。 

    或者  2)配置:(配在java命令-D参数或者dubbo.properties中) 
        dubbo.spring.config=classpath*:META-INF/spring/*.xml ----配置spring配置加载位置 

默认缺省加载Spring Container 缘由:

在dubbo-2.8.4.jar中  在META-INT/dubbo/internal/com.alibba.dubbo.container.Container

spring=com.alibaba.dubbo.container.spring.SpringContainer  有此配置!!!

代码:

/** 
* 主线程启动 
*/ 
public class TestMain { 

    public static void main(String[] args) throws Exception { 
        com.alibaba.dubbo.container.Main.main(args); 
    } 

dubbo-registry

注册中心模块,基于注册中心下发地址的集群方式,以及对各类注 册中心的抽象。

对于服务提供方,它须要发布服务,并且因为应用系统的复杂性,服务的数量、类型也不断膨胀;对于服务消费方,它最关心如何获取到它所须要的服务,而面对复杂的应用系统,须要管理大量的服务调用。并且,对于服务提供方和服务消费方来讲,他们还有可能兼具这两种角色,即既须要提供服务,有须要消费服务。
经过将服务统一管理起来,能够有效地优化内部应用对服务发布/使用的流程和管理。服务注册中心能够经过特定协议来完成服务对外的统一。Dubbo提供的注册中心有以下几种类型可供选择:

  • Multicast注册中心
  • Zookeeper注册中心
  • Redis注册中心
  • Simple注册中心
  • default注册中心即为dubbo-2.8.4.jar 中com.dubbo.registry.dubbo.*

服务首先暴露在服务端,而后调用Registry的register方法在注册中心(它是一个服务协调中心,dubbo之外的独立服务端,dubbo提供了客户端实现)注册服务,而后用户经过配置文件中配置的service的url去subscribe(订阅服务),Registry接收到订阅消息后会往url对应的的List<NotifyListener>中塞入当前NotifyListener,反之从这个list中移除listener就是取消订阅。registry会调用据consumer的订阅状况调用notify方法推送服务列表给Consumer。

Provider初始化时会调用doRegister方法向注册中心发起注册。那么客户端又是怎么subscribe在注册中心订阅服务的呢?答案是服务消费者在初始化ConsumerConfig时会调用RegistryProtocol的refer方法进一步调用RegistryDirectory的subscribe方法最终调用ZookeeperRegistry的subscribe方法向注册中心订阅服务。

注意:

看以下配置发布服务:

<dubbo:registry protocol=”dubbo” address="127.0.0.1:9090" />

<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" protocol=”dubbo”  />

1. 指定了哪一种的注册中心,是基于dubbo协议的,指定了注册中心的地址以及端口号

2. 发布DemoService服务,服务的实现为DemoServiceImpl

每一个<dubbo:service/>在spring内部都会生成一个ServiceBean实例,ServiceBean的实例化过程当中调用export方法来暴露服务

1. 经过loadRegistries获取注册中心registryUrls

registry://127.0.0.1:9090/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.5.4-SNAPSHOT&owner=william&pid=7084&registry=dubbo&timestamp=1415711791506

用统一数据模型URL表示:

protocol=registry表示一个注册中心url

注册中心地址127.0.0.1:9090

调用注册中心的服务RegistryService

注册中心协议是registry=dubbo

2. 构建发布服务的URL

dubbo://192.168.0.102:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.5.4-SNAPSHOT&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7084&side=provider&timestamp=1415712331601

发布协议protocol =dubbo

服务提供者的地址为192.168.0.102:20880

发布的服务为com.alibaba.dubbo.demo.DemoService

3. 遍历registryUrls向注册中心注册服务

给每一个registryUrl添加属性key为export,value为上面的发布服务url获得以下registryUrl

registry://127.0.0.1:9098/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.5.4-SNAPSHOT& export=dubbo%3A%2F%2F192.168.0.102%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26dubbo%3D2.5.4-SNAPSHOT%26generic%3Dfalse%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26loadbalance%3Droundrobin%26methods%3DsayHello%26owner%3Dwilliam%26pid%3D7084%26side%3Dprovider%26timestamp%3D1415712331601&owner=william&pid=7084&registry=dubbo&timestamp=1415711791506

4. 由发布的服务实例,服务接口以及registryUrl为参数,经过代理工厂proxyFactory获取Invoker对象,Invoker对象是dubbo的核心模型,其余对象都向它靠拢或者转换成它。

5. 经过Protocol对象暴露服务protocol.export(invoker)

经过DubboProtocol暴露服务的监听(不是此节内容)

经过RegistryProtocol将服务地址发布到注册中心,并订阅此服务

RegistryProtocol.export(Invoker)暴露服务

消费者引用服务

< dubbo:registry protocol = ”dubbo” address = "127.0.0.1:9098" />

< dubbo:reference id = "demoService" interface = "com.alibaba.d ubbo.demo.DemoService" />

1. 指定了哪一种的注册中心,是基于dubbo协议的,指定了注册中心的地址以及端口号

2. 引用远程DemoService服务

每一个<dubbo:reference/>标签spring加载的时候都会生成一个Referenc eBean。

如上图ReferenceBean实现了spring的FactoryBean接口, 实现了此接口的Bean经过spring的BeanFactory.getBean(“beanName”)获取的对象不是配置的bean自己而是经过FactoryBean.getObject()方法返回的对象,此接口在spring内部被普遍使用,用来获取代理对象等等。这里getObjec t方法用来生成对远程服务调用的代理

1. loadRegistries()获取配置的注册中心的registryUrls

2. 遍历registryUrls集合,给registryUrl加上refer key就是要引用的远程服务

[ registry ://127.0.0.1:9098/com.alibaba.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.0&pid=2484& refer =application%3Ddemo-consumer%26dubbo%3D2.0.0%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26methods%3DsayHello%26pid%3D2484%26side%3Dconsumer%26timestamp%3D1415879965901&registry=dubbo&timestamp=1415879990670]

3. 遍历registryUrls集合,使用Protocol.refer(interface,regist ryUrl)的到可执行对象invoker

4. 若是注册中心有多个的话, 经过集群策略Cluser.join()将多个invoke r假装成一个可执行invoker, 这里默认使用available策略

5. 利用代理工厂生成代理对象proxyFactory.getProxy(invoker)

基于 Spring 可扩展 Schema 提供自定义配置支持(spring 配置文件中 配置标签支持) 

以上标签

未完待续.........

相关文章
相关标签/搜索