Dubbo 和 SpringCloud技术选型

问题1: spi的原理是什么 dubbo哪些地方用到了

文章参考: 如何优化RPC网络通信?

RPC 通信是大型服务框架的核心

微服务的核心是远程通信和服务治理。远程通信提供了服务之间通信的桥梁,服务治理则提供了服务的后勤保障。所以,我们在做技术选型时,更多要考虑的是这两个核心的需求。目前,很多微服务框架中的服务通信是基于 RPC 通信实现的,在没有进行组件扩展的前提下,SpringCloud 是基于 Feign 组件实现的 RPC 通信(基于 Http+Json 序列化实现),Dubbo 是基于 SPI 扩展了很多 RPC 通信框架,包括 RMI、Dubbo、Hessian 等 RPC 通信框架(默认是 Dubbo+Hessian 序列化)。不同的业务场景下,RPC 通信的选择和优化标准也不同。例如,开头我提到的我们部门在选择微服务框架时,选择了 Dubbo。当时的选择标准就是RPC 通信可以支持抢购类的高并发,在这个业务场景中,请求的特点是瞬时高峰、请求量大和传入、传出参数数据包较小。而 Dubbo 中的 Dubbo 协议就很好地支持了这个请求。以下是基于 Dubbo:2.6.4 版本进行的简单的性能测试。分别测试 Dubbo+Protobuf 序列化以及 Http+Json 序列化的通信性能(这里主要模拟单一 TCP 长连接 +Protobuf 序列化和短连接的 Http+Json 序列化的性能对比)。为了验证在数据量不同的情况下二者的性能表现,我分别准备了小对象和大对象的性能压测,通过这样的方式我们也可以间接地了解下二者在 RPC 通信方面的水平。RT(RESPONSE TIME) 代表响应时长

 

 通过以上测试结果可以发现:无论从响应时间还是吞吐量上来看,单一 TCP 长连接
+Protobuf 序列化实现的 RPC 通信框架都有着非常明显的优势。

Dubbo 与 Feign 都依赖注册中心、负载均衡。
二、区别
1、协议
Dubbo:支持多传输协议(Dubbo、Rmi、http、redis等等),可以根据业务场景选择最佳的方式。非常灵活。
默认的Dubbo协议:利用Netty,TCP传输,单一、异步、长连接,适合数据量小、高并发和服务提供者远远少于消费者的场景。

Feign:基于Http传输协议,短连接,不适合高并发的访问。

2、负载均衡
Dubbo:
支持4种算法(随机、轮询、活跃度、Hash一致性),而且算法里面引入权重的概念。
配置的形式不仅支持代码配置,还支持Dubbo控制台灵活动态配置。
负载均衡的算法可以精准到某个服务接口的某个方法。

Feign:
只支持N种策略:轮询、随机、ResponseTime加权。
负载均衡算法是Client级别的。

3、容错策略
Dubbo:支持多种容错策略:failover、failfast、brodecast、forking等,也引入了retry次数、timeout等配置参数。
Feign:利用熔断机制来实现容错的,处理的方式不一样。

拓展: RMI-JDK 自带的 RPC 通信框架

RMI(Remote Method Invocation)是 JDK 中最先实现了 RPC 通信的框架之一,RMI
的实现对建立分布式 Java 应用程序至关重要,是 Java 体系非常重要的底层技术,很多开
源的 RPC 通信框架也是基于 RMI 实现原理设计出来的,包括 Dubbo 框架中也接入了
RMI 框架。接下来我们就一起了解下 RMI 的实现原理,看看它存在哪些性能瓶颈有待优
化。

RMI 在高并发场景下的性能瓶颈

1> Java 默认序列化
RMI 的序列化采用的是 Java 默认的序列化方式,我在 09 讲中详细地介绍过 Java 序列
化,我们深知它的性能并不是很好,而且其它语言框架也暂时不支持 Java 序列化。

2> TCP 短连接

由于 RMI 是基于 TCP 短连接实现,在高并发情况下,大量请求会带来大量连接的创建和销
毁,这对于系统来说无疑是非常消耗性能的。

3> 阻塞式网络 I/O

在 08 讲中,我提到了网络通信存在 I/O 瓶颈,如果在 Socket 编程中使用传统的 I/O 模
型,在高并发场景下基于短连接实现的网络通信就很容易产生 I/O 阻塞,性能将会大打折
扣。


 

Dubbo底层是使用 Netty NIO 框架,基于 TCP 协议传输配合以 Hessian 序列化的 RPC 分布式服务框架  

Dubbo 和 Spring Cloud 有什么区别?

1)通信方式不同   

Dubbo 使用的是 RPC 通信,而 Spring Cloud 使用的是 HTTP RESTFul 方式。

Dubbo,RPC的性能比HTTP的性能更好,并发能力更强,经过深度优化的RPC服务框架,性能和并发能力是更好一些。很多中小型公司而言,其实稍微好一点的性能,Dubbo一次请求10ms,Spring Cloud耗费20ms,对很多中小型公司而言,性能、并发,并不是最主要的因素,Spring Cloud这套架构原理,走HTTP接口和HTTP请求,就足够满足性能和并发的需要了,没必要使用高度优化的RPC服务框架

2)组成部分不同

640?wx_fmt=png

4、dubbo都支持什么通讯协议,推荐用哪种?

HTTP连接
      HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用
      HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
      1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
      2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。
      由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求

协议名称实现描述连接使用场景
dubbo传输:mina、netty、grizzy

序列化:dubbo、hessian2 二进制序列化(默认)、java、json

    dubbo缺省采用单一长连接和NIO异步通讯   

  • 连接个数:单连接
  • 连接方式:长连接
  • 传输协议:TCP
  • 传输方式:NIO 异步传输

1.传入传出参数数据包较小

2.消费者 比提供者多(dubbo协议采用单一长连接保证)

3.常规远程服务方法调用

4.不适合传送大数据量的服务,比如文件、传视频

rmi (少用)传输:java  rmi

序列化:java 标准二进制序列化
    

连接个数:多连接

连接方式:短连接

传输协议:TCP

传输方式:BIO

1.常规RPC调用

2.与原RMI客户端互操作

3.可传文件

4.不支持防火墙穿透
hessian 
传输:Serverlet容器

序列化:hessian二进制序列化
   

    连接个数:多连接
    连接方式:短连接
    传输协议:HTTP
    传输方式:同步传输

   


1.提供者比消费者多

2.可传文件

3.跨语言传输

约束:

  • 参数及返回值不能自定义实现 ListMapNumberDateCalendar 等接口,只能用 JDK 自带的实现,因为 hessian 会做特殊处理,自定义实现类中的属性值都会丢失。

Hessian 是 Caucho 开源的一个 RPC 框架,其通讯效率高于 WebService 和 Java 自带的序列化

http

基于 HTTP 表单的远程调用协议,采用 Spring 的 HttpInvoker 实现 


传输:servlet容器

序列化:表单序列化
    连接个数:多连接
    连接方式:短连接
    传输协议:HTTP
    传输方式:同步传输

1.提供者多余消费者

2.数据包混合

分析请求的发送与接收、编解码、线程派发以及响应的发送与接收等过程,至于服务降级、过滤器链和序列化3.可用表单或URL传入参数,暂不支持传文件。

webservice
传输:HTTP

序列化:SOAP文件序列化
    连接个数:多连接
    连接方式:短连接
    传输协议:HTTP
    传输方式:同步传输

1.系统集成

2.跨语言调用
thrift
    与thrift RPC实现集成,并在基础上修改了报文头   

长连接、NIO异步传输   

1>  默认就是走dubbo协议的,单一长连接,NIO异步通信,基于hessian作为序列化协议

适用的场景就是:传输数据量很小(每次请求在100kb以内),但是并发量很高

为什么采用异步单一长连接?

因为服务的现状大都是服务提供者少,通常只有几台机器,而服务的消费者多,可能整个网站都在访问该服务,通过单一连接,保证单一消费者不会压死提供者,长连接,减少连接握手验证等 然后基于长连接NIO异步通信,可以支撑高并发请求 否则如果上亿次请求每次都是短连接的话,服务提供者会扛不住。

为什么不能传大包?

因 dubbo 协议采用单一长连接,网络将成为瓶颈

5. Dubbo里面有哪几种节点角色以及服务注册与发现的流程图?

  0. 服务容器负责启动,加载,运行服务提供者。
· 1. 服务提供者在启动时,向注册中心注册自己提供的服务。
· 2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
· 3. 注册中心返回服务提供者地址列表(
注册的生产者的地址接口)给消费者,消费者缓存到本地,调用服务时不会每次都去zk中查询而是在本地cache文件中查询. 如果有变更(watch 机制),注册中心将基于长连接推
送变更数据给消费者,告知哪台服务器挂了。
· 4. 服务消费者从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,
如果调用失败,再选另一台调用(dubbo 在调用服务不成功时,默认是会重试两次)。
· 5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计
数据到监控中心。

注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时注册中心交互,注册中心不转发请求,服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外,注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者 
注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表 
注册中心和监控中心都是可选的,服务消费者可以直连服务提供者

640?wx_fmt=png

640?wx_fmt=png

 Dubbo 服务调用过程

/dev-guide/images/dubbo-extension.jpg

服务消费者通过代理工厂ProxyFactory生成的代理对象Proxy (服务接口),经过过滤器去集群拿服务列表,在经过复杂均衡策略选取服务, 经过通讯协议dubbo hessian发起远程调用, 接着通过网络客户端将编码后的请求发送到服务提供方server,server收到请求后, 现将数据进行解码,然后将解码后的请求发送到分发器Dispatcher, 在通过分发器将请求发送发到指定的线程池上,最后有线程池调用具体的服务 

6.Dubbo默认使用什么注册中心,还有别的选择吗?

推荐使用 Zookeeper 作为注册中心

  • Multicast 注册中心:Multicast 注册中心不需要任何中心节点,只要广播地址,就能进行服务注册和发现,基于网络中组播传输实现。
  • Zookeeper 注册中心:基于分布式协调系统 Zookeeper 实现,采用 Zookeeper 的 watch 机制实现数据变更
  • Redis 注册中心:基于 Redis 实现,采用 key/map 存储, key 存储服务名和类型,map 中 key 存储服务 url,value 服务过期时间。基于 Redis 的发布/订阅模式通知数据变更。
  • Simple 注册中心。

7.Dubbo 核心的配置有哪些?

我曾经面试就遇到过面试官让你写这些配置,我也是蒙逼。。

640?wx_fmt=png

8. 在 Provider 上可以配置的 Consumer 端的属性有哪些?

1)timeout:方法调用超时
2)retries:失败重试次数,默认重试 2 次
3)loadbalance:负载均衡算法,默认随机
4)actives 消费者端,最大并发调用限制

consumer的优先级高于provider

服务端:

客户端

8.1 dubbo 数据传输大小配置

<dubbo:protocol name="${dubbo.protocol.name}" port="${dubbo.protocol.port}" payload ="${dubbo.protocol.dubbo.payload}" />

下面大概说一下dubbo:protocol里面的属性
  threadpool:线程池类型,可选:fixed/cached ,默认fixed 。
  threads :服务线程池大小(固定大小) ,默认为100
  payload:请求及响应数据包大小限制,单位:字节,默认为88388608(=8M)  1M=1048576不是最大值
  如:

<dubbo:protocol name="dubbo" port="4021"  server="netty" client="netty" serialization="hessian2" charset="UTF-8" threadpool="cached" threads="20000"  queues="0" iothreads="25" buffer="8192" accepts="20000" payload="8388608" />

ThreadPool
       fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)
       cached 缓存线程池,空闲一分钟自动删除,需要时重建。
       limited可伸缩线程池,但池中的线程数只会增长不会收缩。(为避免收缩时突然来了大流量引起的性能问题)。

buffer 网络读写缓冲区大小
iothreads io线程池大小(固定大小)
threads 服务线程池大小(固定大小)
accepts 服务提供方最大可接受连接数

9. Dubbo推荐使用什么序列化框架,你知道的还有哪些?

推荐使用Hessian序列化,还有Duddo、FastJson、Java自带序列化。

10. Dubbo有哪几种负载均衡策略,默认是哪种?

640?

 Random LoadBalance

    随机,按权重设置随机概率。可以对provider不同实例设置不同的权重,会按照权重来负载均衡,权重越大分配流量越高,一般就用这个默认的就可以了。(权重可以在dubbo管控台配置)

 RoundRobin LoadBalance

    轮循,按公约后的权重设置轮循比率。存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

 LeastActive LoadBalance

   最少活跃调用数,这个就是自动感知一下,如果某个机器性能越差,那么接收的请求越少,越不活跃,此时就会给不活跃的性能差的机器更少的请求 ( 相同活跃数的随机,活跃数指调用前后计数差。使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。 )

 ConsistentHash LoadBalance

一致性Hash,相同参数的请求总是发到同一provider提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。缺省只对第一个参数Hash,如果要修改,请配置

11. dubbo集群容错策略
  1)failover cluster模式

     失败自动切换,自动重试其他机器,默认就是这个,常见于读操作

 2) failfast cluster模式
一次调用失败就立即失败,常见于写操作

3)failsafe cluster模式

   出现异常时忽略掉,常用于不重要的接口调用,比如记录日志

4)failback cluster模式

失败了后台自动记录请求,然后定时重发,比较适合于写消息队列这种

5)forking cluster

并行调用多个provider,只要一个成功就立即返回

6)broadcacst cluster

 逐个调用所有的provider

12 dubbo动态代理策略
默认使用javassist动态字节码生成,创建代理类

但是可以通过spi扩展机制配置自己的动态代理策略

13. Dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,发布者和订阅者之间还能通信么? 

可以的,启动dubbo时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用 注册中心全部宕掉,服务提供者和消费者仍可以通过本地缓存通讯 

使用dubbo遇到过哪些问题?

增加提供服务版本号和消费服务版本号

这个具体来说不算是一个问题,而是一种问题的解决方案,通过版本号找到对应的服务.

<dubbo:serviceinterface="com.xxx.XxxService" ref="xxxService" version="1.0"/>
<dubbo:referenceid="xxxService" interface="com.xxx.XxxService" version="1.0"/>

史上最全 40 道 Dubbo 面试题及答案,看完碾压面试官!_java面试笔试-CSDN博客

dubbo支持哪些通信协议和序列化协议 - __Meng - 博客园

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值