一、介绍
Dubbo是一个分布式服务架构,致力于提供高性能和透明化的PRC远程服务调用方案,以及SOA服务治理方案(面向服务的架构,它将应用程序的不同服务通过这些服务之间定义良好的接口和契约联系起来),
二、RPC(远程过程调用)与RMI(远程方法调用)的区别
1:方法调用方式不同:
RMI中是通过在客户端的stub对象作为远程接口进行远程方法的调用。每个远程方法都具有方法签名。
RPC中是通过网络服务协议向远程主机发送请求,请求包含了一个参数集和一个文本值,通常形成“classname.methodname(参数集)”的形式。RPC远程主机就去搜索与之相匹配的类和方法,找到后就执行方法并把结果编码,通过网络协议发回。
2:适用语言范围不同:RMI只用于Java; RPC是网络服务协议,与操作系统和语言无关。
3:调用结果的返回形式不同:
Java是面向对象的,所以RMI的调用结果可以是对象类型或者基本数据类型;
RMI的结果统一由外部数据表示 (External Data Representation, XDR) 语言表示
三、系统远程调用的方式
- Webservice:效率不高基于soap协议。项目中不推荐使用。
- 使用restful形式的服务:http+json。很多项目中应用。如果服务太多,服务之间调用关系混乱,需要治疗服务。
- 使用dubbo:使用rpc协议进行远程调用,直接使用socket通信。传输效率高,并且可以统计出系统之间的调用关系、调用次数。
四、Dubbo与SpringCloud的区别
SpringCloud工作方式:
-
所有请求都统一通过 API 网关(Zuul)来访问内部服务。
扫描二维码关注公众号,回复: 2726811 查看本文章 -
网关接收到请求后,从注册中心(Eureka)获取可用服务。
-
由 Ribbon 进行均衡负载后,分发到后端的具体实例。
-
微服务之间通过 Feign 进行通信处理业务
五、Dubbo与Dubbox的区别
- 支持REST风格远程调用(HTTP + JSON/XML);
- 支持基于Kryo和FST的Java高效序列化实现;
- 支持基于Jackson的JSON序列化;
- 支持基于嵌入式Tomcat的HTTP remoting体系;
- 升级Spring至3.x;
- 升级ZooKeeper客户端;
- 支持完全基于Java代码的Dubbo配置
六、Dubbo架构
七、Dubbo优缺点
优点:
- 透明化的远程方法调用:像调用本地方法一样调用远程方法;只需简单配置,没有任何API侵入。
- 软负载均衡及容错机制:可在内网替代F5等硬件负载均衡器。
- 服务注册中心自动注册和配置管理:不需要写死服务提供者地址,注册中心基于接口名自动查询提供者ip。 使用类似zookeeper等分布式协调服务作为服务注册中心,可以将绝大部分项目配置移入zookeeper集群。
- 服务接口监控与治理:Dubbo-admin与Dubbo-monitor提供了完善的服务接口管理与监控功能,针对不同应用的不同接口,可以进行 多版本,多协议,多注册中心管理。
缺点:只支持JAVA语言
八、Dubbo常用配置介绍
- <dubbo:application/> 应用配置,用于配置当前应用信息,不管该应用是提供者还是消费者。
- <dubbo:registry/> 注册中心配置,用于配置连接注册中心相关信息。
- <dubbo:protocol/> 协议配置,用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受。
- <dubbo:service/> 服务配置,用于暴露服务。
- <dubbo:reference/> 引用配置,用于创建一个远程服务代理
- <dubbo:provider/> 提供方的缺省值,当ProtocolConfig和ServiceConfig某属性没有配置时,采用此缺省值,可选。
- <dubbo:consumer/> 消费方缺省配置,当ReferenceConfig某属性没有配置时,采用此缺省值,可选。
- <dubbo:method/> 方法配置,用于ServiceConfig和ReferenceConfig指定方法级的配置信息。
- <dubbo:argument/> 用于指定方法参数配置。
- <dubbo:module/> 模块配置,用于配置当前模块信息,可选。
- <dubbo:monitor/> 监控中心配置,用于配置连接监控中心相关信息,可选。
九、Dubbo注册中心
- Zookeeper注册中心:基于分布式协调系统Zookeeper实现,采用Zookeeper的watch机制实现数据变更;
- Multicast注册中心: Multicast注册中心不需要任何中心节点,只要广播地址,就能进行服务注册和发现。基于网络中组播传输实现;
- redis注册中心: 基于redis实现,采用key/Map存储,住key存储服务名和类型,Map中key存储服务URL,value服务过期时间。基于redis的发布/订阅模式通知数据变更;
- Simple注册中心
Dubbo注册中心配置主要通过<dubbo:registry> 标签进行配置。<dubbo:registry address="zookeeper://10.20.153.10:2181"/> 或 <dubbo:registry protocol="zookeeper" address="10.20.153.10:2181" />
多注册中心: Dubbo 支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。
十、Dubbo配置规则
10.1 配置的覆盖规则:
- 方法级配置别优于接口级别
- Consumer端配置 优于 Provider配置 优于 全局配置,最后是Dubbo Hard Code的配置值。例如在provider和consumer的配置文件中,如果都配置了timeout的超时时间,dubbo默认以consumer中配置的时间为准。
10.2 推荐配置:在Provider上尽量多配置Consumer端属性。原因如下:
- 作服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数,等等
- 在Provider配置后,Consumer不配置则会使用Provider的配置值,即Provider配置可以作为Consumer的缺省值。否则,Consumer会使用Consumer端的全局设置,这对于Provider不可控的,并且往往是不合理的
- 配置的覆盖规则
10.3 Provider可以配置的Consumer端属性有
- timeout,方法调用超时
- retries,失败重试次数,缺省是2(表示加上第一次调用,会调用3次)
- loadbalance,负载均衡算法(有多个Provider时,如何挑选Provider调用),缺省是随机(random)。还可以有轮训(roundrobin)、最不活跃优先(leastactive,指从Consumer端并发调用最好的Provider,可以减少的反应慢的Provider的调用,因为反应更容易累积并发的调用)
- actives,消费者端,最大并发调用限制,即当Consumer对一个服务的并发调用到上限后,新调用会Wait直到超时。在方法上配置(dubbo:method )则并发限制针对方法,在接口上配置(dubbo:service),则并发限制针对服务。
<dubbo:service interface="com.alibaba.hello.api.WorldService" version="1.0.0" ref="helloService"
timeout="300" retry="2" loadbalance="random" actives="0" >
<dubbo:method name="findAllPerson" timeout="10000" retries="9" loadbalance="leastactive" actives="5" />
<dubbo:service/>
Provider上可以配置的Provider端属性有:
- threads,服务线程池大小
- executes,一个服务提供者并行执行请求上限,即当Provider对一个服务的并发调用到上限后,新调用会Wait(Consumer可能到超时)。在方法上配置(dubbo:method )则并发限制针对方法,在接口上配置(dubbo:service),则并发限制针对服务
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService"
executes="200" >
<dubbo:method name="findAllPerson" executes="50" />
</dubbo:service>
10.4 Dubbo超时时间设置:
- 在dubbo的provider和consumer的配置文件中,如果都配置了timeout的超时时间,dubbo默认以consumer中配置的时间为准。
- consumer会在超过指定时得到一个调用超时的异常。provider中代码的执行不会因为超时而中断,在执行完毕后,会得到一个dubbo的警告
十一、Dubbo支持的协议
11.1 dubbo:// (默认使用)
连接个数:单连接
连接方式:长连接
传输协议:TCP
传输方式:NIO异步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较小(建议小于100K),尽量不要用dubbo协议传输大文件或超大字符串。
适用场景:适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况
11.2 rmi://
RMI协议采用JDK标准的java.rmi.*实现,采用阻塞式短连接和JDK标准序列化方式,Java标准的远程调用协议。
连接个数:多连接
连接方式:短连接
传输协议:TCP
传输方式:同步传输
序列化:Java标准二进制序列化
适用场景:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
11.3 hessian://
Hessian协议用于集成Hessian的服务,Hessian底层采用Http通讯,采用Servlet暴露服务,Dubbo缺省内嵌Jetty作为服务器实现
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大
适用场景:页面传输,文件传输
11.4 http://
采用Spring的HttpInvoker实现
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:表单序列化(JSON)
适用范围:传入传出参数数据包大小混合,提供者比消费者个数多,暂不支持传文件。
适用场景:需同时给应用程序和浏览器JS使用的服务。
11.5 webservice://
基于CXF的frontend-simple和transports-http实现
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:SOAP文本序列化
适用场景:系统集成,跨语言调用。
还有 thrift:// memcached:// redis://
十二、Dubbo序列化框架
默认使用Hessian序列化,还有Duddo、FastJson、JDK自带序列化。
- Hessian序列化:一种跨语言的高效二进制的序列化方式,但这里实际不是原生的hessian2序列化,而是阿里修改过的hessian lite
- dubbo序列化:阿里尚不成熟的java序列化实现
- FastJson序列化:文本二进制,不如二进制序列化高效
- JDK序列化:性能不理想
十三、Dubbo通信框架
默认使用netty框架,其他的通信框架有mina以及基于servlet等方式
详情访问https://blog.csdn.net/qq_33314107/article/details/81321438
十四、Dubbo集群负载均衡策略
- Random LoadBalance: 随机选取提供者策略,有利于动态调整提供者权重(权重可以在dubbo管控台配置)。截面碰撞率高,调用次数越多,分布越均匀;
- RoundRobin LoadBalance: 轮循选取提供者策略,平均分布,但是存在请求累积的问题;
- LeastActive LoadBalance: 最少活跃调用策略,解决慢提供者接收更少的请求;
- ConstantHash LoadBalance: 一致性Hash策略,使相同参数请求总是发到同一提供者,一台机器宕机,可以基于虚拟节点,分摊至其他提供者,避免引起提供者的剧烈变动;
十五、Dubbo容错机制
读操作建议使用Failover失败自动切换,默认重试两次其他服务器。写操作建议使用Failfast快速失败,发一次调用失败就立即报错
1)Failover Cluster(默认):失败自动切换,当出现失败,重试其它服务器。(缺省)通常用于读操作,但重试会带来更长延迟。可通过retries="2"来设置重试次数(不含第一次)
<dubbo:service retries="2" cluster="failover"/>
或:<dubbo:reference retries="2" cluster="failover"/> //cluster可不写
2)Failfast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录
<dubbo:service cluster="failfast"/>
或:<dubbo:reference cluster="failfast"/>
//cluster="failfast"和 把cluster="failover"、retries="0"是一样的效果,retries="0"就是不重试
3) Failsafe Cluster:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作
<dubbo:service cluster="failsafe"/>
或:<dubbo:reference cluster="failsafe"/>
4)Failback Cluster:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作
<dubbo:service cluster="failback"/>
或:<dubbo:reference cluster="failback"/>
5)Forking Cluster:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks="2"来设置最大并行数
<dubbo:service cluster=“forking" forks="2"/>
或:<dubbo:reference cluster=“forking" forks="2"/>
6)Broadcast Cluster:2.1.0开始支持。广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息
十六、Dubbo健壮性
- 监控中心宕掉不影响使用,只是丢失部分采样数据
- 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
- 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
- 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
- 服务提供者无状态,任意一台宕掉后,不影响使用
- 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
十七、Dubbo伸缩性
-
注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心
-
服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者
十八、问题总结
1、Dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,发布者和订阅者之间还能通信么?
可以,启动dubbo时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用
2、Dubbo在安全机制方面是如何解决的?
Dubbo通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。Dubbo还提供服务黑白名单,来控制服务所允许的调用方
3、Dubbo连接注册中心和直连的区别
在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,
点对点直联方式:服务消费者直接连接指定服务提供者,忽略注册中心的提供者列表,
连接注册中心:服务消费者从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。如果有变更,注册中心将基于长连接推送变更数据给消费者。实现了动态地注册和发现服务,且实现软负载均衡和容错(注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外)
4、Dubbo通信协议Dubbo协议为什么要消费者比提供者个数多?
因dubbo协议采用单一长连接,假设网络为千兆网卡(1024Mbit=128MByte),根据测试经验数据每条连接最多只能压满7MByte(不同的环境可能不一样,供参考),理论上1个服务提供者需要20个服务消费者才能压满网卡。
5、Dubbo通信协议Dubbo协议为什么不能传大包?
因dubbo协议采用单一长连接,如果每次请求的数据包大小为500KByte,假设网络为千兆网卡(1024Mbit=128MByte),每条连接最大7MByte(不同的环境可能不一样,供参考),单个服务提供者的TPS(每秒处理事务数)最大为:128MByte / 500KByte = 262。单个消费者调用单个服务提供者的TPS(每秒处理事务数)最大为:7MByte / 500KByte = 14。如果能接受,可以考虑使用,否则网络将成为瓶颈。
6、Dubbo通信协议Dubbo协议为什么采用异步单一长连接?
因为服务的现状大都是服务提供者少,通常只有几台机器,而服务的消费者多,可能整个网站都在访问该服务,比如Morgan的提供者只有6台提供者,却有上百台消费者,每天有1.5亿次调用,如果采用常规的hessian服务,服务提供者很容易就被压跨,通过单一连接,保证单一消费者不会压死提供者,长连接,减少连接握手验证等,并使用异步IO,复用线程池,防止C10K问题
7、服务调用是阻塞的吗?
默认是阻塞的,可以异步调用,没有返回值的可以这么做
8、服务提供者能实现失效踢出是什么原理?
服务失效踢出基于zookeeper的临时节点原理,详情https://www.jianshu.com/p/f42c69e4bd3e?fromApp=1
9、服务上线怎么不影响旧版本?
采用多版本开发,不影响旧版本,详情https://blog.csdn.net/whereismatrix/article/details/53784464
当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
在低压力时间段,先升级一半提供者为新版本
再将所有消费者升级为新版本
然后将剩下的一半提供者升级为新版本
<dubbo:service interface="com.foo.BarService" version="1.0.0" />
<dubbo:service interface="com.foo.BarService" version="2.0.0" />
<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />
<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />
不区分版本:(2.2.0以上版本支持)
<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />
10、如何解决服务调用链过长的问题?
可以结合zipkin实现分布式服务追踪 ,详情https://blog.csdn.net/liaokailin/article/details/52077620
11、同一个服务多个注册的情况下可以直连某一个服务吗?
可以直连,修改配置即可,也可以通过telnet直接某个服务