Dubbo——面试问题集(1~3)

    xiaoxiao2022-07-12  150

    1、默认使用的是什么通信框架,还有别的选择吗?

    Dubbo默认使用netty,还支持mina, grizzy

    配置方式:

    <dubbo:protocol name=“dubbo” port=“9090” server=“netty” client=“netty” codec=“dubbo” serialization=“hessian2” charset=“UTF-8” threadpool=“fixed” threads=“100” queues=“0” iothreads=“9” buffer=“8192” accepts=“1000” payload=“8388608” />

    Transporter: mina, netty, grizzySerialization: dubbo, hessian2, java, jsonDispatcher: all, direct, message, execution, connectionThreadPool: fixed, cached

    Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。

    Mina:

    Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架。当前发行的 Mina 版本2.04支持基于 Java NIO 技术的 TCP/UDP 应用程序开发、串口通讯程序,Mina 所支持的功能也在进一步的扩展中。目前,正在使用 Mina的应用包括:Apache Directory Project、AsyncWeb、AMQP(Advanced Message Queuing Protocol)、RED5 Server(Macromedia Flash Media RTMP)、ObjectRADIUS、 Openfire等等。

    Netty:

    Netty是一款异步的事件驱动的网络应用框架和工具,用于快速开发可维护的高性能、高扩展性协议服务器和客户端。也就是说,Netty是一个NIO客户端/服务器框架,支持快速、简单地开发网络应用,如协议服务器和客户端。它极大简化了网络编程,如TCP和UDP套接字服务器。

    Grizzly:

    Grizzly是一种应用程序框架,专门解决编写成千上万用户访问服务器时候产生的各种问题。使用JAVA NIO作为基础,并隐藏其编程的复杂性。容易使用的高性能的API。带来非阻塞socketd到协议处理层。利用高性能的缓冲和缓冲管理使用高性能的线程池。

    2、服务调用是阻塞的吗?

    Dubbo默认为同步阻塞调用,但是也支持异步调用(有返回值、无返回值两种)

    异步无返回值: 所谓“无返回值”异步调用是指服务消费方只管调用,但不关心调用结果,此时 Dubbo 会直接返回一个空的 RpcResult。若要使用异步特性,需要服务消费方手动进行配置。

    异步有返回值: 返回一个Future

    服务调用过程如下:

    public class DubboInvoker<T> extends AbstractInvoker<T> { private final ExchangeClient[] clients; protected Result doInvoke(final Invocation invocation) throws Throwable { RpcInvocation inv = (RpcInvocation) invocation; final String methodName = RpcUtils.getMethodName(invocation); // 设置 path 和 version 到 attachment 中 inv.setAttachment(Constants.PATH_KEY, getUrl().getPath()); inv.setAttachment(Constants.VERSION_KEY, version); ExchangeClient currentClient; if (clients.length == 1) { // 从 clients 数组中获取 ExchangeClient currentClient = clients[0]; } else { currentClient = clients[index.getAndIncrement() % clients.length]; } try { // 获取异步配置 boolean isAsync = RpcUtils.isAsync(getUrl(), invocation); // isOneway 为 true,表示“单向”通信 boolean isOneway = RpcUtils.isOneway(getUrl(), invocation); int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT); // 异步无返回值 if (isOneway) { boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false); // 发送请求 currentClient.send(inv, isSent); // 设置上下文中的 future 字段为 null RpcContext.getContext().setFuture(null); // 返回一个空的 RpcResult return new RpcResult(); } // 异步有返回值 else if (isAsync) { // 发送请求,并得到一个 ResponseFuture 实例 ResponseFuture future = currentClient.request(inv, timeout); // 设置 future 到上下文中 RpcContext.getContext().setFuture(new FutureAdapter<Object>(future)); // 暂时返回一个空结果 return new RpcResult(); } // 同步调用 else { RpcContext.getContext().setFuture(null); // 发送请求,得到一个 ResponseFuture 实例,并调用该实例的 get 方法进行等待 return (Result) currentClient.request(inv, timeout).get(); } } catch (TimeoutException e) { throw new RpcException(..., "Invoke remote method timeout...."); } catch (RemotingException e) { throw new RpcException(..., "Failed to invoke remote method: ..."); } } // 省略其他方法 }

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

    推荐使用zookeeper注册中心,还有Multicast、Redis和Simple等。

    3.1 zookeeper 注册中心

    Zookeeper 是 Apacahe Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用 [1]。 流程说明:

    服务提供者启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址服务消费者启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址监控中心启动时: 订阅 /dubbo/com.foo.BarService 目录下的所有提供者和消费者 URL 地址。

    支持以下功能:

    当提供者出现断电等异常停机时,注册中心能自动删除提供者信息当注册中心重启时,能自动恢复注册数据,以及订阅请求当会话过期时,能自动恢复注册数据,以及订阅请求当设置 <dubbo:registry check=“false” /> 时,记录失败注册和订阅请求,后台定时重试可通过 <dubbo:registry username=“admin” password=“1234” /> 设置 zookeeper 登录信息可通过 <dubbo:registry group=“dubbo” /> 设置 zookeeper 的根节点,不设置将使用无根树支持 * 号通配符 <dubbo:reference group="" version="" />,可订阅服务的所有分组和所有版本的提供者
    3.2 Multicast 注册中心:

    Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现。

    提供方启动时广播自己的地址消费方启动时广播订阅请求提供方收到订阅请求时,单播自己的地址给订阅者,如果设置了 unicast=false,则广播给订阅者消费方收到提供方地址时,连接该地址进行 RPC 调用。

    组播受网络结构限制,只适合小规模应用或开发阶段使用。组播地址段: 224.0.0.0 - 239.255.255.255

    3.3 Redis 注册中心

    基于 Redis 实现的注册中心。 使用 Redis 的 Key/Map 结构存储数据结构:

    主 Key 为服务名和类型Map 中的 Key 为 URL 地址Map 中的 Value 为过期时间,用于判断脏数据,脏数据由监控中心删除 [3]

    使用 Redis 的 Publish/Subscribe 事件通知数据变更:

    通过事件的值区分事件类型:register, unregister, subscribe, unsubscribe普通消费者直接订阅指定服务提供者的 Key,只会收到指定服务的 register, unregister 事件监控中心通过 psubscribe 功能订阅 /dubbo/*,会收到所有服务的所有变更事件

    调用过程:

    服务提供方启动时,向 Key:/dubbo/com.foo.BarService/providers 下,添加当前提供者的地址

    并向 Channel:/dubbo/com.foo.BarService/providers 发送 register 事件

    服务消费方启动时,从 Channel:/dubbo/com.foo.BarService/providers 订阅 register 和 unregister 事件

    并向 Key:/dubbo/com.foo.BarService/consumers 下,添加当前消费者的地址

    服务消费方收到 register 和 unregister 事件后,从 Key:/dubbo/com.foo.BarService/providers 下获取提供者地址列表

    服务监控中心启动时,从 Channel:/dubbo/* 订阅 register 和 unregister,以及 subscribe 和unsubsribe事件

    服务监控中心收到 register 和 unregister 事件后,从 Key:/dubbo/com.foo.BarService/providers 下获取提供者地址列表

    服务监控中心收到 subscribe 和 unsubsribe 事件后,从 Key:/dubbo/com.foo.BarService/consumers 下获取消费者地址列表

    可靠性声明 阿里内部并没有采用 Redis 做为注册中心,而是使用自己实现的基于数据库的注册中心,即:Redis 注册中心并没有在阿里内部长时间运行的可靠性保障,此 Redis 桥接实现只为开源版本提供,其可靠性依赖于 Redis 本身的可靠性。

    3.4 Simple 注册中心

    Simple 注册中心本身就是一个普通的 Dubbo 服务,可以减少第三方依赖,使整体通讯方式一致。

    配置 将 Simple 注册中心暴露成 Dubbo 服务:

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!-- 当前应用信息配置 --> <dubbo:application name="simple-registry" /> <!-- 暴露服务协议配置 --> <dubbo:protocol port="9090" /> <!-- 暴露服务配置 --> <dubbo:service interface="org.apache.dubbo.registry.RegistryService" ref="registryService" registry="N/A" ondisconnect="disconnect" callbacks="1000"> <dubbo:method name="subscribe"><dubbo:argument index="1" callback="true" /></dubbo:method> <dubbo:method name="unsubscribe"><dubbo:argument index="1" callback="false" /></dubbo:method> </dubbo:service> <!-- 简单注册中心实现,可自行扩展实现集群和状态同步 --> <bean id="registryService" class="org.apache.dubbo.registry.simple.SimpleRegistryService" /> </beans>

    引用 Simple Registry 服务:

    <dubbo:registry address="127.0.0.1:9090" />

    或者:

    <dubbo:service interface="org.apache.dubbo.registry.RegistryService" group="simple" version="1.0.0" ... >

    或者:

    <dubbo:registry address="127.0.0.1:9090" group="simple" version="1.0.0" />
    最新回复(0)