Dubbo面试题

  1. 什么是RPC
    RPC(Remote Procedure Call)是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。简言之,RPC使得程序能够像访问本地系统资源一样,去访问远端系统资源。

  2. RPC框架需要解决的问题

    1. 如何确定客户端和服务端之间的通信协议?
    2. 如何更高效地进行网络通信?
    3. 服务端提供的服务如何暴露给客户端?
    4. 客户端如何发现这些暴露的服务?
    5. 如何更高效地对请求对象和响应结果进行序列化和反序列化操作?
  3. RPC的实现基础

    1、需要有非常高效的网络通信,比如一般选择Netty作为网络通信框架;

    2、需要有比较高效的序列化框架,比如谷歌的Protobuf序列化框架;

    3、可靠的寻址方式(主要是提供服务的发现),比如可以使用Zookeeper来注册服务等等;

    4、如果是带会话(状态)的RPC调用,还需要有会话和状态保持的功能;

  4. RPC使用了哪些关键技术

    • 动态代理

      生成Client Stub(客户端存根)和Server Stub(服务端存根)的时候需要用到Java动态代理技术,可以使用JDK提供的原生的动态代理机制,也可以使用开源的:CGLib代理,Javassist字节码生成技术。

    • 序列化和反序列化

      在网络中,所有的数据都将会被转化为字节进行传送,所以为了能够使参数对象在网络中进行传输,需要对这些参数进行序列化和反序列化操作。

      • 序列化:把对象转换为字节序列的过程称为对象的序列化,也就是编码的过程。
      • 反序列化:把字节序列恢复为对象的过程称为对象的反序列化,也就是解码的过程。
    • NIO通信

      出于并发性能的考虑,传统的阻塞式 IO 显然不太合适。可以选择Netty或者MINA来解决NIO数据传输的问题。

  5. Dubbo核心组件

    dubbo-architecture.jpg
    组件 说明
    Provider 服务提供者
    Consumer 服务消费者
    Registry 服务注册与发现的注册中心
    Monitor 统计服务的调用次数和调用时间的监控中心
    Container 服务运行容器
    1. 服务容器负责启动,加载,运行服务提供者。
    2. 服务提供者在启动时,向注册中心注册自己提供的服务。
    3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
    4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
    5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
    6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

    Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。

  6. 为什么要Dubbo(为什么需要RPC)

    为什么微服务化?横向扩展、并行开发、服务治理、服务编排、负载均衡

  7. 默认是什么通信框架,还有别的选择吗?默认使用的序列化框架,你还知道哪些

    Dubbo 默认使用 Netty 框架,也是推荐的选择,另外内容还集成有Mina、Grizzly

    协议 序列化协议 场景
    dubbo://(默认) hessian 单一长连接(建立连接后,持续发送使用)和NIO异步通信,适合于数据量小但高并发的服务调用,不适合大数据量的服务,如文件传输
    rmi:// JDK 标准序列化 传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件;常规远程服务方法调用,与原生RMI服务互操作
    hessian:// hessian 传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件;页面传输,文件传输,或与原生hessian服务互操作
    http:// 表单序列化 传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看
    webservice:// SOAP 文本序列化 系统集成,跨语言调用
  8. 服务调用是阻塞的吗

    Dubbo 缺省协议采用单一长连接,底层实现是 Netty 的 NIO 异步通讯机制;基于这种机制,Dubbo 实现了以下几种调用方式:

    • 同步调用:一种阻塞式的调用方式,即 Consumer 端代码一直阻塞等待,直到 Provider 端返回为止;

      其实,Dubbo 的底层 IO 操作都是异步的。Consumer 端发起调用后,得到一个 Future 对象。对于同步调用,业务线程通过Future#get(timeout),阻塞等待 Provider 端将结果返回;timeout则是 Consumer 端定义的超时时间。当结果返回后,会设置到此 Future,并唤醒阻塞的业务线程;当超时时间到结果还未返回时,业务线程将会异常返回。

    • 异步调用: 基于 Dubbo 底层的异步 NIO 实现异步调用,对于 Provider 响应时间较长的场景是必须的,它能有效利用 Consumer 端的资源,相对于 Consumer 端使用多线程来说开销较小。

      
          
      
      
      AsyncService service = ...;
      String result = service.goodbye("samples");// 这里的返回值为空,请不要使用
      Future future = RpcContext.getContext().getFuture();
      ... // 业务线程可以开始做其他事情
      result = future.get(); // 阻塞需要获取异步结果时,也可以使用 get(timeout, unit) 设置超时时间
      

      Dubbo Consumer 端发起调用后,同时通过RpcContext.getContext().getFuture()获取跟返回结果关联的Future对象,然后就可以开始处理其他任务;当需要这次异步调用的结果时,可以在任意时刻通过future.get(timeout)来获取。

    • 参数回调: 参数回调有点类似于本地 Callback 机制,但 Callback 并不是 Dubbo 内部的类或接口,而是由 Provider 端自定义的;Dubbo 将基于长连接生成反向代理,从而实现从 Provider 端调用 Consumer 端的逻辑。

    • 事件通知: 事件通知允许 Consumer 端在调用之前、调用之后或出现异常时,触发 oninvokeonreturnonthrow 三个事件。 可以通过在配置 Consumer 时,指定事件需要通知的方法,如:

      
      
      
          
      
      
  9. 一般使用什么注册中心?还有别的选择吗?

    • Multicast注册中心: Multicast注册中心不需要任何中心节点,只要广播地址,就能进行服务注册和发现。 组播受网络结构限制,只适合小规模应用或开发阶段使用。组播地址段: 224.0.0.0 - 239.255.255.255
    • Zookeeper注册中心: 基于分布式协调系统Zookeeper实现,采用Zookeeper的watch机制实现数据变更
    • redis注册中心: 基于redis实现,采用key/Map存储,key存储服务名和类型,Map中key存储服务URL,value服务过期时间。基于redis的发布/订阅模式通知数据变更
  10. Dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,那发布者和订阅者还能通信吗

    可以的,为什么呢?zookeeper的信息会缓存到本地作为一个缓存文件,并且转换成properties对象方便使用.

  11. 服务提供者实现失效踢出是什么原理

    Zookeeper中节点是有生命周期的.具体的生命周期取决于节点的类型.节点主要分为持久节点(Persistent)临时节点(Ephemeral).

    • 临时节点: 临时节点的生命周期和客户端会话绑定,也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉
    • 持久节点:所谓持久节点,是指在节点创建后,就一直存在,直到有删除操作来主动清除这个节点,也就是说不会因为创建该节点的客户端会话失效而消失

    ZK 中我们让所有的机其都注册一个临时节点,我们判断一个机器是否可用,我们只需要判断这个节点在ZK中是否存在就可以了,不需要直接去连接需要检查的机器,降低系统的复杂度

  12. 如何解决调用链过长的问题

    Dubbo 可以使用 Pinpoint 和 Apache Skywalking(Incubator) 实现分布式服务追踪

  13. 核心的配置有哪些

    • dubbo:consumer
      1. timeout 远程服务调用超时时间(毫秒)
      2. retries 远程服务调用重试次数,不包括第一次调用,不需要重试请设为0,仅在cluster为failback/failover时有效
      3. loadbalance 负载均衡策略,可选值:random,roundrobin,leastactive,分别表示:随机,轮询,最少活跃调用
      4. async 是否缺省异步执行,不可靠异步,只是忽略返回值,不阻塞执行线程
    • dubbo:provider(Provider 上可以配置的 Consumer 端的属性有哪些)
      1. protocol 协议名称
      2. threads 服务线程池大小(固定大小)
      3. serialization dubbo协议缺省为hessian2,rmi协议缺省为java,http协议缺省为json
      4. threadpool 线程池类型,可选:fixed/cached/limit
      5. retries 远程服务调用重试次数,不包括第一次调用,不需要重试请设为0
      6. actives 消费者端,最大并发调用限制
      7. loadbalance:负载均衡算法,默认随机
      8. timeout:方法调用超时
  14. Dubob集群容错有几种方案?

    • Failover Cluster:失败自动切换,当出现失败,重试其它服务器 [1]。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。
    • Failfast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
    • Failsafe Cluster:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
    • Failback Cluster:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
    • Forking Cluster:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。
    • Broadcast Cluster:广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。
  15. Dubbo服务降级,失败重试怎么做?

    可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。 如电商促销中,屏蔽“商品推荐”这些边缘业务,减少一定的并发

    RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
    Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
    registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));
    
    • mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
    • 还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
  16. Dubbo使用了哪些设计模式

  1. Dubbo SPI与 Java SPI区别

    SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。

    JAVA:

    1. public interface Robot {
          void sayHello();
      }
      public class OptimusPrime implements Robot {
          
          @Override
          public void sayHello() {
              System.out.println("Hello, I am Optimus Prime.");
          }
      }
      
      public class Bumblebee implements Robot {
      
          @Override
          public void sayHello() {
              System.out.println("Hello, I am Bumblebee.");
          }
      }
      
    2. META-INF/services 文件夹下创建一个文件,名称为 Robot 的全限定名 org.apache.spi.Robot

      org.apache.spi.OptimusPrime
      org.apache.spi.Bumblebee
      
    3. 加载并使用

      public class JavaSPITest {
      
          @Test
          public void sayHello() throws Exception {
              ServiceLoader serviceLoader = ServiceLoader.load(Robot.class);
              System.out.println("Java SPI");
              serviceLoader.forEach(Robot::sayHello);
          }
      }
      

    Dubbo SPI 示例

    Dubbo 并未使用 Java SPI,而是重新实现了一套功能更强的 SPI 机制。Dubbo SPI 的相关逻辑被封装在了 ExtensionLoader 类中,通过 ExtensionLoader,我们可以加载指定的实现类。Dubbo SPI 所需的配置文件需放置在 META-INF/dubbo 路径下,配置内容如下。

    optimusPrime = org.apache.spi.OptimusPrime
    bumblebee = org.apache.spi.Bumblebee
    

    与 Java SPI 实现类配置不同,Dubbo SPI 是通过键值对的方式进行配置,这样我们可以按需加载指定的实现类。另外,在测试 Dubbo SPI 时,需要在 Robot 接口上标注 @SPI 注解。下面来演示 Dubbo SPI 的用法:

    public class DubboSPITest {
    
        @Test
        public void sayHello() throws Exception {
            ExtensionLoader extensionLoader = 
                ExtensionLoader.getExtensionLoader(Robot.class);
            Robot optimusPrime = extensionLoader.getExtension("optimusPrime");
            optimusPrime.sayHello();
            Robot bumblebee = extensionLoader.getExtension("bumblebee");
            bumblebee.sayHello();
        }
    }
    
  1. Dubbo支持分布式事务吗?

    目前暂时不支持,后续可能采用基于 JTA/XA 规范实现

  2. Dubbo如何优雅停机

    优雅停机是指在停止应用时,执行的一系列保证应用正常关闭的操作。这些操作往往包括等待已有请求执行完成、关闭线程、关闭连接和释放资源等,优雅停机可以避免非正常关闭程序可能造成数据异常或丢失,应用异常等问题。优雅停机本质上是JVM即将关闭前执行的一些额外的处理代码。

    Provider在接收到停机指令后

    • 从注册中心上注销所有服务;
    • 从配置中心取消监听动态配置;
    • 向所有连接的客户端发送只读事件,停止接收新请求;
    • 等待一段时间以处理已到达的请求,然后关闭请求处理线程池;
    • 断开所有客户端连接。

    Consumer在接收到停机指令后

    • 拒绝新到请求,直接返回调用异常;
    • 等待当前已发送请求执行完毕,如果响应超时则强制关闭连接。
  3. Dubbo与Spring Cloud区别

    Dubbo确实类似于Spring Cloud的一个子集,Dubbo功能和文档完善。 对于类似于电商等同步调用场景多并且能支撑搭建Dubbo 这套比较复杂环境的成本的产品而言,Dubbo 确实是一个可以考虑的选择

    Spring Cloud由众多子项目组成,如Spring Cloud Config、Spring Cloud Netflix、Spring Cloud Consul 等,提供了搭建分布式系统及微服务常用的工具,如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性token、全局锁、选主、分布式会话和集群状态等,满足了构建微服务所需的所有解决方案

  4. 当一个服务接口有多种实现时怎么做

    当一个接口有多种实现时,可以用 group 属性来分组,服务提供方和消费方都指定同一个 group 即可

  5. 服务的本地暴露和远程暴露

  6. Dubbo在安全机制方面是如何解决的

    Dubbo通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。Dubbo还提供服务黑白名单,来控制服务所允许的调用方。

你可能感兴趣的:(Dubbo面试题)