# Dubbo是什么
Dubbo是一个高性能的远程服务调用的分布式框架。
集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
远程通讯:提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
自动发现:基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
# Dubbo能做什么
透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
# Dubbo节点角色
节点 | 角色说明 |
---|---|
Provider | 服务提供者 |
Consumer | 服务消费者 |
Registry | 服务注册与发现中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
# Dubbo核心配置
配置 | 说明 |
---|---|
dubbo:service | 服务配置 |
dubbo:reference | 引用配置 |
dubbo:protocol | 协议配置 |
dubbo:application | 应用配置 |
dubbo:module | 模块配置 |
dubbo:registry | 注册中心配置 |
dubbo:monitor | 监控中心配置 |
dubbo:provider | 提供者配置 |
dubbo:consumer | 消费者配置 |
dubbo:method | 方法配置 |
dubbo:argument | 参数配置 |
# Dubbo协议
协议名称 | 实现描述 | 连接 | 使用场景 |
---|---|---|---|
dubbo | 传输:mina、netty、grizzy 序列化:dubbo、hessian2、java、json | dubbo缺省采用单一长连接和NIO异步通讯 | 1.传入传出参数数据包较小 2.消费者比提供者多 3.常规远程服务方法调用 4.不适合传送大数据量的服务,比如文件、传视频 |
rmi | 传输:java rmi 序列化:java 标准序列化 | 连接个数:多连接 连接方式:短连接 传输协议:TCP/IP 传输方式:BIO | 1.常规RPC调用 2.与原RMI客户端互操作 3.可传文件 4.不支持防火墙穿透 |
hessian | 传输:Serverlet容器 序列化:hessian二进制序列化 | 连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 | 1.提供者比消费者多 2.可传文件 3.跨语言传输 |
http | 传输:servlet容器 序列化:表单序列化 | 连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 | 1.提供者多于消费者 2.数据包混合 |
webservice | 传输:HTTP 序列化:SOAP文件序列化 | 连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 | 1.系统集成 2.跨语言调用 |
thrift | 与thrift RPC实现集成,并在基础上修改了报文头 | 长连接、NIO异步传输 |
# Dubbo支持的序列化方式
序列化方式 | 说明 |
---|---|
dubbo序列化 | 阿里尚未开发成熟的高效java序列化实现,阿里不建议在生产环境使用它 |
hessian2序列化(默认推荐) | hessian是一种跨语言的高效二进制序列化方式。但这里实际不是原生的hessian2序列化,而是阿里修改过的hessian lite,它是dubbo RPC默认启用的序列化方式 |
json序列化 | 目前有两种实现,一种是采用的阿里的fastjson库,另一种是采用dubbo中自己实现的简单json库,但其实现都不是特别成熟,而且json这种文本序列化性能一般不如上面两种二进制序列化。 |
java序列化 | 主要是采用JDK自带的Java序列化实现,性能很不理想。 |
# Dubbo集群容错方案
方案 | 说明 |
---|---|
FailOver Cluster | 失败自动切换,自动尝试其它服务器(默认) |
Failfast Cluster | 快速失败,立即报错 |
Failsafe Cluster | 失败安全,出现异常直接忽略 |
Failback Cluster | 失败自动恢复,记录失败请求,定时重发 |
Forking Cluster | 并行调用多个服务器,只要有一个成功即返回 |
Broadcast Cluster | 广播逐个调用所有服务提供者,任意一个报错即报错 |
# Dubbo负载均衡方案
负载均衡方案 | 说明 |
---|---|
Random LoadBalance | 随机,按权重设置随机概率 |
RoundRobin LoadBalance | 轮询,按公约后的权重设置轮询比例 |
LeastActive LoadBalance | 最少活跃数调用,相同活跃数的随机 |
ConsistentHash LoadBalance | 一致性hash,相同参数的请求总是发送到同一提供者 |
# Dubbo使用的设计模式
# 责任链模式
责任链模式在Dubbo中发挥的作用举足轻重,就像是Dubbo框架的骨架。Dubbo的调用链组织是用责任链模式串连起来的。责任链中的每个节点实现Filter
接口,然后由ProtocolFilterWrapper
,将所有Filter
串连起来。Dubbo的许多功能都是通过Filter
扩展实现的,比如监控、日志、缓存、安全、telnet以及RPC本身都是。如果把Dubbo比作一列火车,责任链就像是火车的各车厢,每个车厢的功能不同。如果需要加入新的功能,增加车厢就可以了,非常容易扩展。
# 观察者模式
Dubbo中使用观察者模式最典型的例子是RegistryService
。消费者在初始化的时候回调用subscribe方法,注册一个观察者,如果观察者引用的服务地址列表发生改变,就会通过NotifyListener
通知消费者。此外,Dubbo的InvokerListener
、ExporterListener
也实现了观察者模式,只要实现该接口,并注册,就可以接收到consumer端调用refer和provider端调用export的通知。Dubbo的注册/订阅模型和观察者模式就是天生一对。
# 修饰器模式
Dubbo中还大量用到了修饰器模式。比如ProtocolFilterWrapper
类是对Protocol类的修饰。在export和refer方法中,配合责任链模式,把Filter组装成责任链,实现对Protocol功能的修饰。其他还有ProtocolListenerWrapper
、 ListenerInvokerWrapper
、InvokerWrapper
等。个人感觉,修饰器模式是一把双刃剑,一方面用它可以方便地扩展类的功能,而且对用户无感,但另一方面,过多地使用修饰器模式不利于理解,因为一个类可能经过层层修饰,最终的行为已经和原始行为偏离较大。
# 工厂方法模式
CacheFactory
的实现采用的是工厂方法模式。CacheFactory
接口定义getCache方法,然后定义一个AbstractCacheFactory
抽象类实现CacheFactory
,并将实际创建cache的createCache方法分离出来,并设置为抽象方法。这样具体cache的创建工作就留给具体的子类去完成。
# 抽象工厂模式
ProxyFactory
及其子类是Dubbo中使用抽象工厂模式的典型例子。ProxyFactory
提供两个方法,分别用来生产Proxy
和Invoker
(这两个方法签名看起来有些矛盾,因为getProxy方法需要传入一个Invoker对象,而getInvoker方法需要传入一个Proxy
对象,看起来会形成循环依赖,但其实两个方式使用的场景不一样)。AbstractProxyFactory
实现了ProxyFactory
接口,作为具体实现类的抽象父类。然后定义了JdkProxyFactory
和JavassistProxyFactory
两个具体类,分别用来生产基于jdk代理机制和基于javassist代理机制的Proxy
和Invoker
。
# 适配器模式
为了让用户根据自己的需求选择日志组件,Dubbo自定义了自己的Logger接口,并为常见的日志组件(包括jcl, jdk, log4j, slf4j)提供相应的适配器。并且利用简单工厂模式提供一个LoggerFactory
,客户可以创建抽象的Dubbo自定义Logger
,而无需关心实际使用的日志组件类型。在LoggerFactory初始化时,客户通过设置系统变量的方式选择自己所用的日志组件,这样提供了很大的灵活性。
# 代理模式
Dubbo consumer使用Proxy
类创建远程服务的本地代理,本地代理实现和远程服务一样的接口,并且屏蔽了网络通信的细节,使得用户在使用本地代理的时候,感觉和使用本地服务一样。