dubbo面试题
RPC
什么是RPC
概念+作用
RPC(Remote Procedure Call)远程过程调用,是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。是分布式系统常见的一种通信方法(RPC是一种技术思想而非一种规范或协议)
使用RPC可以实现客户端像调用本地服务(方法)一样调用远程服务器的服务(方法)。
网络通信原理
网络通信都是通过传输协议和网络IO来实现,传输协议比较出名的有http、tcp、udp等,网络IO,主要有bio、nio、aio三种方式,所有的分布式应用通讯都基于这个原理而实现
数据传输协议
数据传输协议不是指传输层的协议,而是数据传输过程中用到的协议,根据不同的实现方法会用到不同的协议
应用层的:FTP(文件传输协议)、SMTP(简单邮件传输协议)、HTTP(超文本传输协议)等
传输层的:tcp、udp等
分布式系统通信方式
Socket,http,rpc,mq等
RPC架构组件
一个基本的RPC架构里面应该至少包含以下4个组件:
1、客户端(Client):服务调用方(服务消费者)
2、客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端
3、服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理
4、服务端(Server):服务的真正提供者
具体调用过程:
- 服务消费者(client客户端)通过调用本地服务的方式调用需要消费的服务;
- 客户端存根(client stub)接收到调用请求后负责将方法、入参等信息序列化(组装)成能够进行网络传输的消息体;
- 客户端存根(client stub)找到远程的服务地址,并且将消息通过网络发送给服务端;
- 服务端存根(server stub)收到消息后进行解码(反序列化操作);
- 服务端存根(server stub)根据解码结果调用本地的服务进行相关处理;
- 本地服务执行具体业务逻辑并将处理结果返回给服务端存根(server stub);
- 服务端存根(server stub)将返回结果重新打包成消息(序列化)并通过网络发送至消费方;
- 客户端存根(client stub)接收到消息,并进行解码(反序列化);
- 服务消费方得到最终结果;
而RPC框架的实现目标则是将上面的第2-9步完好地封装起来,也就是把调用、编码/解码的过程给封装起来,让用户感觉上像调用本地服务一样的调用远程服务。
总结:RPC框架把请求序列化,网络发送,请求的解码,调用本地服务,结果序列化,结果解码等过程进行封装来提高远程服务的易用性。
有哪些RPC框架
有很多RPC框架:gRPC、Thrift、Dubbo/Dubbox等等。基本上他们
分为两种类别:
- 跨语言的。
- 单一语言的,如果你的分布式应用架构主体都是Java应用,显然我们不应该使用跨语言的RPC来多一层中转浪费效率。
RMI(JDK自带): JDK自带的RPC,在java.rmi包
WebServices:通过http协议请求和响应xml格式数据的RPC实现
HTTPClient::通过http协议实现RPC调用
Dubbo:阿里开源的rpc框架,正在逐步支持多语言
Hessian:轻量级的RPC框架,基于HTTP协议传输,使用Hessian二进制序列化
Thrift: Apache Thrift是Facebook开源的跨语言的RPC通信框架,基于tcp协议传输
gRPC:Google公布的开源软件,基于最新的HTTP2.0协议,并支持常见的众多编程语言。
如何进行选择:
是否允许代码侵入: 即需要依赖相应的代码生成器生成代码,比如Thrift。
是否需要长连接获取高性能: 如果对于性能需求较高,那么可以果断选择基于TCP的Thrift、Dubbo。
是否需要跨越网段、跨越防火墙: 这种情况一般选择基于HTTP协议的Hessian和Thrift的HTTP Transport。
RPC涉及的协议
RPC的实现需要基于传输协议和序列化协议来完成
传输协议:RPC 可以直接基于 TCP/UDP协议,也可以基于 HTTP 协议进行传输
序列化协议:xml,json,hessian等
dubbo默认是基于 hessian 作为序列化协议,使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。
dubbo涉及的协议有那些
Dubbo支持dubbo、rmi、hessian、http、webservice、thrift、memcached、redis、rest等多种协议,但是Dubbo官网是推荐我们使用Dubbo协议的。
dubbo协议:
dubbo默认采用dubbo协议,dubbo协议采用单一长连接和NIO异步通讯,基于 hessian 作为序列化协议,使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。
rmi 协议:
走 Java 二进制序列化,多个短连接,适合消费者和提供者数量差不多的情况,适用于文件的传输,一般较少用。
hessian 协议:
走 hessian 序列化协议,多个短连接,适用于提供者数量比消费者数量还多的情况,适用于文件的传输,一般较少用。
http 协议:
走 json 序列化。
webservice:
走 SOAP 文本
RPC调用和HTTP调用
http调用是基于应用层的http协议来完成远程方法访问
http协议是实现RPC调用的一种传输协议,RPC还可以基于tcp或udp等传输协议完成
可以把 HTTP 调用看作是一种 RPC 的http协议实现
如果是使用RPC的应用框架如dubbo可以方便调用接口的管理也更加的安全
一般使用rpc的连接方式是长连接、传输效率较高,可定制化路由,适用于内部系统互联;
http调用使用的短连接,协议标准化且易读,容易对接外部系统,适用于上层业务模块
RPC调用和webservice调用
WebService是一种跨语言和跨操作系统的远程调用技术。
传统的WebService通过http协议发送请求和接收结果时,发送的请求内容和结果内容都采用xml格式封装
Web Service 就是基于 HTTP 协议的 RPC,它具有良好的跨平台性,也是一种RPC的实现。
Dubbo协议特点
连接个数:单连接
连接方式:长连接(消费方与提供方及注册中心之间使用长连接。)
传输协议:TCP
传输方式:NIO异步传输
序列化:Hessian二进制序列化(二进制的与语言无关的序列化协议)
适用范围:小数据量(建议小于100K)大并发,消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大文件或超大字符串。
适用场景:常规远程服务方法调用
约束:参数及返回值需实现 Serializable 接口
nio:是面向缓冲的,基于事件驱动的,非阻塞的io,适用于连接数目较多,连接时间短的应用
aio:适合连接数目多,这些连接每次只是发送少量的数据且连接比较长的场景
在dubbo协议中nio提供异步非阻塞复用连接的作用,长连接不是nio的长处,通过其他方式和谐了(TODO)
为什么采用单一长连接:
因为服务的现状大都是服务提供者少,通常只有几台机器,而服务的消费者多,通过单一连接,保证单一消费者不会压死提供者,长连接,减少连接握手验证等,并使用异步IO,复用线程池
Dubbo序列化方式?
Hessian 序列化:是修改过的 hessian lite,默认启用,推荐使用
json 序列化:使用 FastJson 库
java 序列化:JDK 提供的序列化,性能不理想
dubbo 序列化:未成熟的高效 java 序列化实现,不建议在生产环境使用
长连接和短连接
短连接:
通讯双方有数据交互时,就建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送。
长连接:
指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是短连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,下次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接
像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。
dubbo简介
介绍+原理
Dubbo是阿里开源的基于 Java 的高性能 RPC 分布式服务框架,dubbo是实现RPC技术思想的应用级别框架
利用dubbo可以很方便的进行远程方法调用
应用场景:多应用系统之间的方法调用
dubbo的特点/功能
- 实现透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。基于接口的远程调用。
提供了软负载均衡功能及容错机制(服务消费者根据软负载均衡算法选择服务端调用,调用失败调其他服务端)。
3. 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
dubbo的容错机制
为什么使用dubbo
使用 Dubbo 可以将核心业务抽取出来,作为独立的服务,形成稳定的服务中心,可用于提高业务复用,方便管理
Dubbo和http调用应用场景
内部系统服务模块之间用dubbo
调用第三方服务用http
dubbo 有效地特性是支持长连接,这样避免了多次重复创建TCP连接的开销
dubbo支持容错机制,调用一个机器失败调用其他的
Dubbo 的设计目的是为了满足高并发小数据量的 rpc 调用,在大数据量下的性能表现并不好,建议使用 rmi 或 http 协议。
dubbo服务组件角色
- Provider(生产者):暴露服务的服务提供方。
- Consumer(消费者): 调用远程服务的服务消费方。
- Registry(注册中心):服务注册与发现的注册中心。
- Monitor(监控中心): 统计服务的调用次调和调用时间的监控中心。可以用来显示接口暴露,注册情况,也可以看接口的调用明细,调用时间等。独立于生产者和消费者安装monitor项目
- Container: 服务运行容器。负责启动,加载,运行服务提供者。该组件借助spring来完成功能
dubbo的原理/调用过程
调用关系说明:
0服务容器负责启动,加载,运行服务提供者。
1服务提供者在启动时,向注册中心注册自己提供的服务。
2服务消费者在启动时,向注册中心订阅自己所需的服务。
3注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Dubbo默认使用的是什么通信框架
Dubbo 默认使用 Netty 框架,也是推荐的选择,另外内容还集成有Mina、Grizzly。
Dubbo有哪几种集群容错方案
配置多个服务,如果测试指定的某一个服务
可以配置环境点对点直连,绕过注册中心,将以服务接口为单位,忽略注册中心的提供者列表。
Dubbo支持服务多协议吗?
Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。
当一个服务接口有多种实现时怎么做?
当一个接口有多种实现时,可以用 group 属性来分组,服务提供方和消费方都指定同一个 group 即可。
服务上线怎么兼容旧版本?
可以用版本号(version)过渡,多个不同版本的服务注册到注册中心,版本号不同的服务相互间不引用。这个和服务分组的概念有一点类似。
Dubbo可以对结果进行缓存吗?
可以,Dubbo 提供了声明式缓存,用于加速热门数据的访问速度,以减少用户加缓存的工作量。
Dubbo服务之间的调用是阻塞的吗?
默认是同步等待结果阻塞的,支持异步调用。
Dubbo 是基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个 Future 对象。
Dubbo支持分布式事务吗?
目前暂时不支持
Dubbo如何优雅停机?
Dubbo 是通过 JDK 的 ShutdownHook 来完成优雅停机的,所以如果使用 kill -9 PID 等强制关闭指令,是不会执行优雅停机的,只有通过 kill PID 时,才会执行。
服务提供者能实现失效踢出是什么原理?
服务失效踢出基于 Zookeeper 的临时节点原理。
容错机制有哪些
Failover 失败自动切换,默认重试两次其他服务器。适合读业务
Failback失败返回空,调用失败后,返回一个空结果。并通过定时任务对失败的调用进行重试(重试根据负载均衡不一定到那台机器),适合执行消息通知等操作。
Failsafe失败安全是指,当调用过程中出现异常时,仅会打印异常,而不会抛出异常。适用于写入审计日志等操作。
Failfast 快速失败,,发一次调用失败就立即报错。适合写业务
Forking并行调用多个服务提供者会在运行时通过线程池创建多个线程,并发调用多个服务提供者。只要有一个服务提供者成功返回了结果,方法就会立即结束运行。
Broadcast 逐个调用每个服务提供者,如果其中一台报错,在循环调用结束后抛出异常。该类通常用于通知所有提供者更新缓存或日志等本地资源信息。
服务读写推荐的容错策略是怎样的?
读操作建议使用 Failover 失败自动切换,默认重试两次其他服务器。(默认的容错机制)
写操作建议使用 Failfast 快速失败,发一次调用失败就立即报错。
Dubbo必须依赖的包有哪些?
Dubbo 必须依赖 JDK,其他为可选。
Dubbo的管理控制台能做什么?
管理控制台主要包含:路由规则,动态配置,服务降级,访问控制,权重调整,负载均衡,接口监控等管理功能。
服务降级
当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。
可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。
dubbo注册中心
如果本地的tomcat同时启动了消费者和生产者应用,可以不配置注册中心调用
dubbo支持的注册中心:
- Multicast注册中心
- Zookeeper注册中心
- Redis注册中心
Simple注册中心
Multicast注册中心:
组播受网络结构限制,只适合小规模应用或开发阶段使用。
Zookeeper注册中心:
适合生产环境使用
redis注册中心:
要求服务器时间必须相同,否则可能出现集群失败问题,
Simple注册中心:
不支持集群
推荐使用zookeeper注册中心
注册中心提供的功能:
注册中心负责服务地址的注册与查找,维护服务,
服务提供者和消费者只在启动时与注册中心交互,
注册中心不转发请求,压力较小
特点:
1.当提供者出现断电等异常停机时,注册中心能自动删除提供者信息。
2.当注册中心重启时,能自动恢复注册数据,以及订阅请求。
3.当会话过期时,能自动恢复注册数据,以及订阅请求。
注册中心挂掉
Dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,发布者和订阅者之间还能通信么?
可以通信的,启动dubbo时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用;
但前提是你没有增加新的服务,如果你要调用新的服务,则是不能办到的。
dubbo的服务治理
服务治理:对服务化架构的管理的一系列行为
服务治理的主要行为:管理服务的生命周期,服务的监控,服务调用控制
dubbo可以使用dubbo-admain通过web界面进行服务治理
dubbo可以使用dubbo-monitor对服务进行监控
dubbo的负载均衡算法
Dubbo提供了4种负载均衡机制:
权重随机算法:RandomLoadBalance
最少活跃调用数算法:LeastActiveLoadBalance
一致性哈希算法:ConsistentHashLoadBalance
加权轮询算法:RoundRobinLoadBalance
默认的负载均衡算法是权重随机算法
权重随机算法:权重越高被调用的几率越大
最少活跃调用数算法:最少调用的优先调用,调用相同的使用权重随机算法
一致性哈希算法:让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求,容灾能力强:当有节点挂掉影响小
加权轮询算法:轮询的基础上加上权重,权重大的访问的频率高
我们有服务器【A、B、C】,权重分别是【1、2、3】。面对6次请求,它们负载均衡的结果如下:【A、B、C、B、C、C】。
一致性哈希算法的数据倾斜:节点数量较少时,由于节点不够分散,导致大量请求落在同一个节点,而其他节点只会接受到少量请求
解决数据倾斜:引入虚拟节点
Dubbo启动时如果依赖的服务不可用会怎样
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,默认 check="true",可以通过 check="false" 关闭检查。
|
关闭某个服务的启动时检查 (没有提供者时报错): <dubbo:reference interface="com.foo.BarService" check="false" /> 关闭所有服务的启动时检查 (没有提供者时报错): <dubbo:consumer check="false" /> 关闭注册中心启动时检查 (注册订阅失败时报错): <dubbo:registry check="false" /> |
dubbo的使用
编写服务提供方和服务消费方都需要使用的接口api
服务提供方引入dubbo需要的jar包需要编写api的实现类
通过spring的dubbo配置进行向zookeeper注册服务
消费方引入dubbo需要的jar包和api的包在spring的配置文件中配置dubbo的接口注册地址等就可以在类中做引用使用了
Dubbo有哪几种配置方式?
1)Spring 配置方式
2)Java API 配置方式
Dubbo 核心的配置有哪些
生产者配置:
生产者应用名称,注册中心地址,暴露的服务接口,服务的实现类,暴露的dubbo服务端口
消费者配置:
消费者应用名称,注册中心地址,要调用的服务接口
|
<!-- 提供方应用信息,用于计算依赖关系 --> <dubbo:application name="hello-world-app" /> <!-- 使用multicast广播注册中心暴露服务地址 --> <dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 声明需要暴露的服务接口 --> <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" /> <!-- 和本地bean一样实现服务 --> <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" /> |
|
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 --> <dubbo:application name="consumer-of-helloworld-app" /> <!-- 使用multicast广播注册中心暴露发现服务地址 --> <dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 生成远程服务代理,可以和本地bean一样使用demoService --> <dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" /> |
集群容错:
失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。
如何设置:
<dubbo:service retries="2" />或
<dubbo:reference retries="2" />或
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>
Provider 上可以配置的 Consumer 端的属性有哪些
1)timeout:方法调用超时
2)retries:失败重试次数,默认重试 2 次
3)loadbalance:负载均衡算法,默认随机
4)actives 消费者端,最大并发调用限制

浙公网安备 33010602011771号