dubbo的重要知识点总结

发布时间:2021-09-09 11:54:50 作者:chen
来源:亿速云 阅读:165

本篇内容主要讲解“dubbo的重要知识点总结”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“dubbo的重要知识点总结”吧!

dubbo架构

Provider: 暴露服务的提供方,可以通过jar或者容器的方式启动服务
Consumer:调用远程服务的服务消费方。
Registry: 服务注册中心和发现中心。
Monitor: 统计服务的调用次数、调用时间
Container:服务运行的容器。

Dubbo的网络传输协议

RPC通讯协议

Dubbo提供的序列化方式

Dubbo的注册中心

默认是zk,其他还有Redis、Multicast、Simple 注册中心,但不推荐。

Dubbo有哪几种配置方式?

Spring 配置方式(XML文件)
Java API 配置方式(注解方式)

Dubbo的核心配置

Timeout的超时时间

在dubbo的provider和consumer的配置文件中,如果都配置了timeout的超时时间,dubbo默认以consumer中配置的时间为准。
如下例子:
在provider.xml的配置:

<dubbo:service timeout="4000" retries="0" interface="com.dingding.tms.bms.service.BillingZfbCodOrderService" ref="billingZfbCodOrderService" registry="globalRegistry"/>

conusmer中的配置:

<dubbo:reference id="billingInterService" interface="com.dingding.tms.bms.service.BillingInterService" protocol="dubbo" check="false" registry="globalRegistry" timeout="3000"/>

最后这个service在调用时的超时时间就是3秒。
另外:
1.consumer会在超过3秒时得到一个调用超时的异常。
2.provider中代码的执行不会因为超时而中断,在执行完毕后,会得到一个dubbo的警告。

在Provider上尽量多配置Consumer端属性

在dubbo的用户手册中,对配置有这样的推荐用法:在Provider上尽量多配置Consumer端属性
原因如下:
作服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数,等等
在Provider配置后,Consumer不配置则会使用Provider的配置值,即Provider配置可以作为Consumer的缺省值。否则,Consumer会使用Consumer端的全局设置,这对于Provider不可控的,并且往往是不合理的
PS: 配置的覆盖规则:

在 Provider 可以配置的 Consumer 端属性有:

Dubbo 启动时如果依赖的服务不可用会怎样?

Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,默认 check="true",可以通过 check="false" 关闭检查。

Dubbo支持的序列化框架

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

Dubbo使用的通信框架

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

Dubbo的集群容错方案

Dubbo的负载均衡策略

注册了多个同一样的服务,如果需要测试指定的某一个服务该怎么做

可以配置环境点对点直连,绕过注册中心,将以服务接口为单位,忽略注册中心的提供者列表。

Dubbo支持服务多协议

Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。
不同服务不同协议:

    <!-- 多协议配置 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <dubbo:protocol name="rmi" port="20980" />

    <!-- 使用dubbo协议暴露服务 -->
    <dubbo:service interface="com.ricky.dubbo.api.DemoService" ref="demoService" protocol="dubbo"/>
    <!-- 使用rmi协议暴露服务 -->
    <dubbo:service interface="com.ricky.dubbo.api.HelloService" ref="helloService" protocol="rmi"/>

同一服务多种协议

    <!-- 多协议配置 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <dubbo:protocol name="rmi" port="20980" />

    <!-- 使用rmi协议暴露服务 -->
    <dubbo:service interface="com.ricky.dubbo.api.HelloService" ref="helloService" protocol="dubbo,rmi"/>

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

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

<dubbo:service interface="…" ref="…" group="实现1" />
<dubbo:service interface="…" ref="…" group="实现2" />

消费端:

<dubbo:reference id="…" interface="…" group="实现1" />
<dubbo:reference id="…" interface="…" group="实现2" />

服务上线怎么兼容旧版本?

可以用版本号(version)过渡,多个不同版本的服务注册到注册中心,版本号不同的服务相互间不引用。这个和服务分组的概念有一点类似。例如:
服务提供方:

<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" />

此外,消费者消费服任意版本的服务时:

<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />

Dubbo的结果缓存机制

Dubbo 提供了声明式缓存,用于加速热门数据的访问速度,以减少用户加缓存的工作量,使用方式:

<dubbo:reference interface="com.foo.BarService" cache="threadlocal" />

Dubbo提供的三种缓存接口的入口,三种方式均继承了 AbstractCacheFactory 接口,分别是:

Dubbo 同步/异步调用

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

Dubbo 同步调用

同步调用是一种阻塞式的调用方式,即 Consumer 端代码一直阻塞等待,直到 Provider 端返回为止;
通常,一个典型的同步调用过程如下:

  1. Consumer 业务线程调用远程接口,向 Provider 发送请求,同时当前线程处于阻塞状态;

  2. Provider 接到 Consumer 的请求后,开始处理请求,将结果返回给 Consumer;

  3. Consumer 收到结果后,当前线程继续往后执行。

这里有 2 个问题:

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

Dubbo 异步调用

dubbo的重要知识点总结

dubbo的重要知识点总结

基于 Dubbo 底层的异步 NIO 实现异步调用,对于 Provider 响应时间较长的场景是必须的,它能有效利用 Consumer 端的资源,相对于 Consumer 端使用多线程来说开销较小。异步调用,对于 Provider 端不需要做特别的配置。
在 Consumer 端配置需要异步调用的方法,均需要使用 <dubbo:method/>标签进行描述:

<dubbo:reference id="asyncService" interface="com.alibaba.dubbo.samples.async.api.AsyncService">
    <dubbo:method name="goodbye" async="true"/>
</dubbo:reference>

Dubbo Consumer 端发起调用后,同时通过RpcContext.getContext().getFuture()获取跟返回结果关联的Future对象,然后就可以开始处理其他任务;当需要这次异步调用的结果时,可以在任意时刻通过future.get(timeout)来获取。
一些特殊场景下,为了尽快调用返回,可以设置是否等待消息发出:

默认为false。配置方式如下:

<dubbo:method name="goodbye" async="true" sent="true" />

如果你只是想异步,完全忽略返回值,可以配置 return="false",以减少 Future 对象的创建和管理成本:

<dubbo:method name="goodbye" async="true" return="false" />

此时,RpcContext.getContext().getFuture()将返回null。

Dubbo 参数回调

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

Provider 端定义 Service 和 Callback:

public interface CallbackService {
    void addListener(String key, CallbackListener listener);
}

public interface CallbackListener {
    void changed(String msg);
}

Provider 端实现 service :

public class CallbackServiceImpl implements CallbackService {

    private final Map<String, CallbackListener> listeners = new ConcurrentHashMap<String, CallbackListener>();

    public CallbackServiceImpl() {
        Thread t = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        for (Map.Entry<String, CallbackListener> entry : listeners.entrySet()) {
                            try {
                                entry.getValue().changed(getChanged(entry.getKey()));
                            } catch (Throwable t) {
                                listeners.remove(entry.getKey());
                            }
                        }
                        Thread.sleep(5000); // timely trigger change event
                    } catch (Throwable t) {
                        t.printStackTrace();
                    }
                }
            }
        });
        t.setDaemon(true);
        t.start();
    }

    public void addListener(String key, CallbackListener listener) {
        listeners.put(key, listener);
        listener.changed(getChanged(key)); // send notification for change
    }

    private String getChanged(String key) {
        return "Changed: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
    }
}

在 Provider 端暴露服务:

<bean id="callbackService" class="com.alibaba.dubbo.samples.callback.impl.CallbackServiceImpl"/>

<dubbo:service interface="com.alibaba.dubbo.samples.callback.api.CallbackService" ref="callbackService" connections="1" callbacks="1000">
    <dubbo:method name="addListener">
        <!-- index 表示参数索引,如下 index=1 ,表示第一个参数是 callback 回调参数 -->
        <dubbo:argument index="1" callback="true"/>
        <!--<dubbo:argument type="com.demo.CallbackListener" callback="true" />-->
    </dubbo:method>
</dubbo:service>

Consumer 端实现 Callback 接口

CallbackService callbackService = ...;
callbackService.addListener("foo.bar", new CallbackListener() {
        public void changed(String msg) {
            System.out.println("callback1:" + msg);
        }
});

Callback 接口的实现类在 Consumer 端,当方法发生调用时,Consumer 端会自动 export 一个 Callback 服务。而 Provider 端在处理调用时,判断如果参数是 Callback,则生成了一个 proxy,因此服务实现类里在调用 Callback 方法的时候,会被传递到 Consumer 端执行 Callback 实现类的代码。

Dubbo 事件通知

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

<bean id="demoCallback" class="com.alibaba.dubbo.samples.notify.impl.NotifyImpl" />

<dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.samples.notify.api.DemoService" version="1.0.0" group="cn">
    <dubbo:method name="sayHello" onreturn="demoCallback.onreturn" onthrow="demoCallback.onthrow"/>
</dubbo:reference>

其中,NotifyImpl 的代码如下:

public class NotifyImpl implements Notify {

    public Map<Integer, String> ret = new HashMap<Integer, String>();
    
    public void onreturn(String name, int id) {
        ret.put(id, name);
        System.out.println("onreturn: " + name);
    }

    public void onthrow(Throwable ex, String name, int id) {
        System.out.println("onthrow: " + name);
    }
}

这里要强调一点,自定义 Notify 接口中的三个方法的参数规则如下:

上述配置中,sayHello方法为同步调用,因此事件通知方法的执行也是同步执行。可以配置 async=true 让方法调用为异步,这时事件通知的方法也是异步执行的。特别强调一下, oninvoke 方法不管是否异步调用,都是同步执行的。

Dubbo 支持分布式事务吗?

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

Dubbo 服务降级(2.2.0以上的版本支持)

可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。
向注册中心写入动态配置覆盖规则:

其中:
mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要的服务不可用时,对调用方的影响。
还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

Dubbo 如何优雅停机?

Dubbo 是通过 JDK 的 ShutdownHook 来完成优雅停机的,所以如果使用 kill -9 PID 等强制关闭指令,是不会执行优雅停机的,只有通过 kill PID 时,才会执行。

Dubbo 的服务提供者能实现失效踢出是什么原理?

服务失效踢出是基于 Zookeeper 的临时节点原理。
zk 中的节点分为临时节点和永久节点,节点的类型在创建时即被确定,并且不能改变。

在分布式系统中,我们常常需要知道某个机器是否可用,传统的开发中,可以通过Ping某个主机来实现,Ping得通说明对方是可用的,相反是不可用的。
在 ZK 中我们让所有的机器都注册一个临时节点,要判断一个节点是否可用,我们只需要判断这个临时节点在 ZK 中是否存在就可以了,不需要直接去连接需要检查的机器,降低系统的复杂度。

Dubbo 服务读写推荐的容错策略是怎样的?

读操作建议使用 Failover 失败自动切换,默认重试两次其他服务器。
写操作建议使用 Failfast 快速失败,发一次调用失败就立即报错。

如何解决服务调用链过长的问题?

Dubbo 可以使用 Pinpoint 和 Apache Skywalking(Incubator) 实现分布式服务追踪,当然还有其他很多方案。

Dubbo 的管理控制台能做什么?

管理控制台主要包含:路由规则,动态配置,服务降级,访问控制,权重调整,负载均衡,等管理功能。

到此,相信大家对“dubbo的重要知识点总结”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

推荐阅读:
  1. JAVA的知识点总结
  2. 面试题总结:可能是全网最好的MySQL重要知识点

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

dubbo

上一篇:怎么解决Git合并冲突的问题

下一篇:怎么通过重启路由的方法切换IP地址

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》