Dubbo精要

news2024/11/18 23:42:50

1、为什么需要 Dubbo?

  • 分布式系统中的服务调用和协调问题:在分布式系统中,服务之间的相互依赖会导致复杂的通信和协调问题。Dubbo提供了高效的服务调用和自动注册、发现等功能,使得构建分布式应用程序更加容易。
  • 服务治理和服务调用链追踪:Dubbo可以帮助我们实现服务治理、服务调用链追踪、服务降级、服务熔断等功能,这对于复杂的服务环境非常重要。
  • 服务拆分和扩展性:随着用户量的增多,应用服务器可能会面临负载压力。此时,我们可以使用Dubbo进行服务拆分,通过增加应用服务器来提高系统的扩展性。
  • 动态服务发现和负载均衡:Dubbo提供了动态的服务注册和发现机制,以及负载均衡功能,这可以帮助我们在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖。
  • 服务间依赖关系的可视化:当服务的调用量越来越大,服务的容量问题就暴露出来。Dubbo可以帮助我们自动画出应用间的依赖关系图,以帮助架构师理清理关系。

2、Dubbo 的主要应用场景?

      通常有四点,如下: RPC 分布式服务,拆分应用进行服务化,提高开发效率,调优性能,节省竞争资源配置管理,解 决服务的地址信息剧增,配置困难的问题 服务依赖,解决服务间依赖关系错踪复杂的问题 服务扩容,解决随着访问量的不断增大,动态扩展服务提供方的机器的问题。

3、Dubbo 的核心功能?

Dubbo主要就是如下 3 个核心功能:

(1)Remoting:网络通信框架,提供对多种 NIO 框架抽象封装,包括“同步转异步”和“请求-响应”模式 的信息交换方式。

(2)Cluster:服务框架,提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均 衡,失败容错,地址路由,动态配置等集群支持。

(3)Registry:服务注册,基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透 明,使服务提供方可以平滑增加或减少机器。

4、Dubbo 服务注册与发现的流程?

     流程说明: Provider(提供者)绑定指定端口并启动服务 指供者连接注册中心,并发本机IP、端口、应用信息和提供服务信息发送至注册中心存储 Consumer(消费者),连接注册中心 ,并发送应用信息、所求服务信息至注册中心 注册中心根据 消费 者所求服务信息匹配对应的提供者列表发送至Consumer 应用缓存。 Consumer 在发起远程调用时基于缓存的消费者列表择其一发起调用。 Provider 状态变更会实时通知注册中心、在由注册中心实时推送至Consumer。

    设计的原因: Consumer 与Provider 解偶,双方都可以横向增减节点数。 注册中心对本身可做对等集群,可动态增减节点,并且任意一台宕掉后,将自动切换到另一台去中 心化,双方不直接依懒注册中心,即使注册中心全部宕机短时间内也不会影响服务的调用服务提供 者无状态,任意一台宕掉后,不影响使用。

5、Dubbo 的服务调用流程?

1) 从client到server经历了编码,序列化,反序列化,解码 的正常网络调用流程, 在nettyServer中处理。 

2) client采用代理的机制 。

3) server处理请求的方式通常为分发请求到线程池,同步阻塞或异步非阻塞返回结果。

6、Dubbo 支持哪些协议,每种协议的应用场景、优缺点?

 dubbo默认:

7、Dubbo 有些哪些注册中心?

推荐使用 Zookeeper 、Nacos作为注册中心,还有 Redis、Multicast、Simple 注册中心,但不推荐。

8、Dubbo 的注册中心集群挂掉,如何正常消费?

可以的,消费者在启动时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。 每次调用时,按照本地存储的地址进行调用。 消费者本地有一个生产者的列表,他会按照列表继续工作,倒是无法从注册中心去同步最新的服务列 表,短期的注册中心挂掉是不要紧的,但一定要尽快修复。 挂掉是不要紧的,但前提是你没有增加新的服务(节点没有变动),如果你要调用新的服务,则是不能 办到的。

9、Dubbo 集群提供了哪些负载均衡策略?

  • Random LoadBalance: 随机选取提供者策略,有利于动态调整提供者权重。截面碰撞率高,调用次数越多,分布越均匀。
  • RoundRobin LoadBalance: 轮循选取提供者策略,平均分布,但是存在请求累积的问题。
  • LeastActive LoadBalance: 最少活跃调用策略,解决慢提供者接收更少的请求。
  • ConstantHash LoadBalance: 一致性 Hash 策略,使相同参数请求总是发到同一提供者,一台机器宕机,可以基于虚拟节点,分摊至其他提供者,避免引起提供者的剧烈变动。

默认为 Random 随机调用。

10、Dubbo 的集群容错方案有哪些?

  • Failover Cluster失败自动切换: dubbo的默认容错方案,当调用失败时自动切换到其他可用的节点,具体的重试次数和间隔时间可用通 过引用服务的时候配置,默认重试次数为1是只调用一次。

  • Failback Cluster失败自动恢复: 在调用失败,记录日志和调用信息,然后返回空结果给consumer,并且通过定时任务每隔5秒对失败的 调用进行重试

  • Failfast Cluster快速失败: 只会调用一次,失败后立刻抛出异常

  • Failsafe Cluster失败安全: 调用出现异常,记录日志不抛出,返回空结果 Forking Cluster并行调用多个服务提供者: 通过线程池创建多个线程,并发调用多个provider,结果保存到阻塞队列,只要有一个provider成功返 回了结果,就会立刻返回结果

  • Broadcast Cluster广播模式: 逐个调用每个provider,如果其中一台报错,在循环调用结束后,抛出异常。 

第一个,failover

这也是Dubbo中默认的一个集群容错技术,failover翻译成中文叫故障转移,见名思义,它是指发现服务提供者不可用时会尝试调用集群中其他的服务提供者,dubbo中默认重试2次。源码如下:

public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
   
        List<Invoker<T>> copyInvokers = invokers;
        checkInvokers(copyInvokers, invocation);
        String methodName = RpcUtils.getMethodName(invocation);
        //获取重试次数,默认2次 加当前调用,总共3次
        int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
        if (len <= 0) {
   
            len = 1;
        }
        // retry loop.
        RpcException le = null; // last exception.
        List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
        Set<String> providers = new HashSet<String>(len);
        //循环重试调用
        for (int i = 0; i < len; i++) {
   
            //Reselect before retry to avoid a change of candidate `invokers`.
            //NOTE: if `invokers` changed, then `invoked` also lose accuracy.
            if (i > 0) {
   
                checkWhetherDestroyed();
                copyInvokers = list(invocation);
                // check again
                checkInvokers(copyInvokers, invocation);
            }
            Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
            invoked.add(invoker);
            RpcContext.getContext().setInvokers((List) invoked);
            try {
   
                Result result = invoker.invoke(invocation);
                if (le != null && logger.isWarnEnabled()) {
   
                    logger.warn("Although retry the method " + methodName
                            + " in the service " + getInterface().getName()
                            + " was successful by the provider " + invoker.getUrl().getAddress()
                            + ", but there have been failed providers " + providers
                            + " (" + providers.size() + "/" + copyInvokers.size()
                            + ") from the registry " + directory.getUrl().getAddress()
                            + " on the consumer " + NetUtils.getLocalHost()
                            + " using the dubbo version " + Version.getVersion() + ". Last error is: "
                            + le.getMessage(), le);
                }
                return result;
            } catch (RpcException e) {
   
                if (e.isBiz()) {
    // biz exception.
                    throw e;
                }
                le = e;
            } catch (Throwable e) {
   
                le = new RpcException(e.getMessage(), e);
            } finally {
   
                providers.add(invoker.getUrl().getAddress());
            }
        }
        throw new RpcException(le.getCode(), "Failed to invoke the method "
                + methodName + " in the service " + getInterface().getName()
                + ". Tried " + len + " times of the providers " + providers
                + " (" + providers.size() + "/" + copyInvokers.size()
                + ") from the registry " + directory.getUrl().getAddress()
                + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
                + Version.getVersion() + ". Last error is: "
                + le.getMessage(), le.getCause() != null ? le.getCause() : le);
    }

 第二个,fastfail

这种是快速失败机制,就是调用失败时立即报错,通常用于非幂等的操作。

@Override
    public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
   
        checkInvokers(invokers, invocation);
        Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
        try {
   
            return invoker.invoke(invocation);
        } catch (Throwable e) {
   
            if (e instanceof RpcException && ((RpcException) e).isBiz()) {
    // biz exception.
                throw (RpcException) e;
            }
            //失败了,直接抛异常
            throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0,
                    "Failfast invoke providers " + invoker.getUrl() + " " + loadbalance.getClass().getSimpleName()
                            + " select from all providers " + invokers + " for service " + getInterface().getName()
                            + " method " + invocation.getMethodName() + " on consumer " + NetUtils.getLocalHost()
                            + " use dubbo version " + Version.getVersion()
                            + ", but no luck to perform the invocation. Last error is: " + e.getMessage(),
                    e.getCause() != null ? e.getCause() : e);
        }
    }

第三个,failsafe

这种是失败安全机制,失败之后不抛异常也不重试,而是忽略异常,单纯记录一下日志,返回空结果。源码如下:

@Override
    public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
   
        try {
   
            checkInvokers(invokers, invocation);
            Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
            return invoker.invoke(invocation);
        } catch (Throwable e) {
   
            //忽略异常,记录日志,返回空结果
            logger.error("Failsafe ignore exception: " + e.getMessage(), e);
            return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore
        }
    }
 第四个,broadcast

这种是广播调用,任何一个服务提供者报错就报错。这种集群容错方式的使用场景是用来更新本地缓存,如果某个数据在某台服务器更新了,可用同步到集群中的其他服务器。

public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
   
        checkInvokers(invokers, invocation);
        RpcContext.getContext().setInvokers((List) invokers);
        RpcException exception = null;
        Result result = null;
        //调用所有服务提供者
        for (Invoker<T> invoker : invokers) {
   
            try {
   
                result = invoker.invoke(invocation);
            } catch (RpcException e) {
   
                exception = e;
                logger.warn(e.getMessage(), e);
            } catch (Throwable e) {
   
                exception = new RpcException(e.getMessage(), e);
                logger.warn(e.getMessage(), e);
            }
        }
        //只要有一台异常,就报错
        if (exception != null) {
   
            throw exception;
        }
        return result;
    }
第五个,failback

这种是失败降级,失败后会记录请求并且定时重试,忽略异常后返回空

源码如下:

@Override
    protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
   
        Invoker<T> invoker = null;
        try {
   
            checkInvokers(invokers, invocation);
            invoker = select(loadbalance, invocation, invokers, null);
            return invoker.invoke(invocation);
        } catch (Throwable e) {
   
            logger.error("Failback to invoke method " + invocation.getMethodName() + ", wait for retry in background. Ignored exception: "
                    + e.getMessage() + ", ", e);
            //新增失败的任务 到时间轮队列
            addFailed(loadbalance, invocation, invokers, invoker);
            return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore
        }
    }

 第六个,forking

这种是并行调用,只要有1个成功就成功,全部失败才算失败,可通过forks="2" 来设置最大并行数。

源码如下:

//循环每个服务提供者,多线程并行调用
for (final Invoker<T> invoker : selected) {
   
                executor.execute(new Runnable() {
   
                    @Override
                    public void run() {
   
                        try {
   
                            Result result = invoker.invoke(invocation);
                            ref.offer(result);
                        } catch (Throwable e) {
   
                            int value = count.incrementAndGet();
                            //失败次数大于等于了提供者数量,说明全部失败
                            if (value >= selected.size()) {
   
                                ref.offer(e);
                            }
                        }
                    }
                });
            }
try {
   
                Object ret = ref.poll(timeout, TimeUnit.MILLISECONDS);
                //如果有失败记录,说明全部都失败了则失败
                if (ret instanceof Throwable) {
   
                    Throwable e = (Throwable) ret;
                    throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0, "Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e.getCause() != null ? e.getCause() : e);
                }
                //否则返回成功
                return (Result) ret;
            } catch (InterruptedException e) {
   
                throw new RpcException("Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e);
            }

11、Dubbo 支持哪些序列化方式?

  • Dubbo:单一长连接和 NIO 异步通讯,适合大并发小数据量的服务调用,以及消费者远大于提供者。传输协议 TCP,异步 Hessian 序列化。Dubbo推荐使用dubbo协议。
  • RMI:采用 JDK 标准的 RMI 协议实现,传输参数和返回参数对象需要实现 Serializable 接口,使用 Java 标准序列化机制,使用阻塞式短连接,传输数据包大小混合,消费者和提供者个数差不多,可传文件,传输协议 TCP。多个短连接 TCP 协议传输,同步传输,适用常规的远程服务调用和 RMI 互操作。在依赖低版本的 Common-Collections 包,Java 序列化存在安全漏洞。
  • WebService:基于 WebService 的远程调用协议,集成 CXF 实现,提供和原生 WebService 的互操作。多个短连接,基于 HTTP 传输,同步传输,适用系统集成和跨语言调用。
  • HTTP:基于 Http 表单提交的远程调用协议,使用 Spring 的 HttpInvoke 实现。多个短连接,传输协议 HTTP,传入参数大小混合,提供者个数多于消费者,需要给应用程序和浏览器 JS 调用。
  • Hessian:集成 Hessian 服务,基于 HTTP 通讯,采用 Servlet 暴露服务,Dubbo 内嵌 Jetty 作为服务器时默认实现,提供与 Hession 服务互操作。多个短连接,同步 HTTP 传输,Hessian 序列化,传入参数较大,提供者大于消费者,提供者压力较大,可传文件。
  • Memcache:基于 Memcache实现的 RPC 协议。
  • Redis:基于 Redis 实现的RPC协议。

12、说说一次 Dubbo 服务请求流程?

13、说说 Dubbo 工作原理

工作原理分 10 层:

第一层:service 层,接口层,给服务提供者和消费者来实现的(留给开发人员来实现);

第二层:config 层,配置层,主要是对 Dubbo 进行各种配置的,Dubbo 相关配置;

第三层:proxy 层,服务代理层,透明生成客户端的 stub 和服务单的 skeleton,调用的是接口,实现 类没有,所以得生成代理,代理之间再进行网络通讯、负责均衡等;

第四层:registry 层,服务注册层,负责服务的注册与发现;

第五层:cluster 层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服 务;

第六层:monitor 层,监控层,对 rpc 接口的调用次数和调用时间进行监控;

第七层:protocol 层,远 程调用层,封装 rpc 调用;

第八层:exchange 层,信息交换层,封装请求响应模式,同步转异步;

第九层:transport 层,网络传输层,抽象 mina 和 netty 为统一接口;

第十层:serialize 层,数据序列化层。

14、注册中心挂了,consumer 还能不能调用 provider?

因为刚开始初始化的时候,consumer 会将需要的所有提供者的地址等信息拉取到本地缓存,所以注册 中心挂了可以继续通信。 但是 provider 挂了,那就没法调用了。

15、怎么实现动态感知服务下线的呢?

服务订阅通常有 pull 和 push 两种方式:

pull 模式需要客户端定时向注册中心拉取配置;

push 模式采用注册中心主动推送数据给客户端。

Dubbo ZooKeeper 注册中心采用是事件通知与客户端拉取方式。 服务第一次订阅的时候将会拉取对应目录下全量数据,然后在订阅的节点注册一个 watcher。 一旦目录节点下发生任何数据变化, ZooKeeper 将会通过 watcher 通知客户端。 客户端接到通知,将会重新拉取该目录下全量数据,并重新注册 watcher。

利用这个模式,Dubbo 服务就可以做到服务的动态发现。 注意:ZooKeeper 提供了“心跳检测”功能,它会定时向各个服务提供者发送一个请求(实际上建立的是 一个 socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其剔除。

16、服务提供者没挂,但在注册中心里看不到?

首先,确认服务提供者是否连接了正确的注册中心,不只是检查配置中的注册中心地址,而且要检查实 际的网络连接。 其次,看服务提供者是否非常繁忙,比如压力测试,以至于没有CPU片段向注册中心发送心跳,这种情 况减小压力将自动恢复。

17、说说Dubbo的优先级配置

配置优先级别

1.以timeout为例,显示了配置的查找顺序,其他retries,loadbalance等类似。

(1) 方法级优先,接口级次之,全局配置在次之

(2) 如果级别一样,则消费方优先,提供方次之

(3) 其中,服务提供方配置,通过URL经由注册中心传递给消费方

2.建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方 同时引用多个服务,就不需要关心每个服务的超时设置。

18、聊聊Dubbo SPI机制?

SPI(Service Provider Interface),是一种服务发现机制,其实就是将结构的实现类写入配置当中,在服 务加载的时候将配置文件独处,加载实现类,这样就可以在运行的时候,动态的帮助接口替换实现类。 Dubbo的SPI其实是对java的SPI进行了一种增强,可以按需加载实现类之外,增加了 IOC 和 AOP 的特 性,还有自适应扩展机制。 SPI在dubbo应用很多,包括协议扩展、集群扩展、路由扩展、序列化扩展等等。 Dubbo对于文件目录的配置分为了三类。

1.META-INF/services/ 目录: 该目录下的 SPI 配置文件是为了用来兼容 Java SPI 。

2.META-INF/dubbo/ 目录: 该目录存放用户自定义的 SPI 配置文件。

3.META-INF/dubbo/internal/ 目录: 该目录存放 Dubbo 内部使用的 SPI 配置文件。

19、Dubbo的SPi和JAVA的SPI有什么区别?

Java Spi Java SPI 在查找扩展实现类的时候,遍历 SPI 的配置文件,并且将实现类全部实例化 Dubbo Spi

1,对 Dubbo 进行扩展,不需要改动 Dubbo 的源码

2,延迟加载,可以一次只加载自己想要加载的扩展实现。

3,增加了对扩展点 IOC 和 AOP 的支持,一个扩展点可以直接 setter 注入其它扩展点。

4,Dubbo 的扩展机制能很好的支持第三方 IoC 容器,默认支持 Spring Bean。

20、说下Dubbo的服务引用的流程。

1.Dubbo客户端根据config文件里的信息从注册中心里订阅服务,并缓存到本地,后续的服务相关信息 的会动态更新到本地。

2.DubboProtocol根据provider的地址和接口连接到服务端server,开启客户端client,再创建 invoker。

3.用invoker为服务接口生成代理对象,这个代理对象是用来远程调用。 相关流程如下图所示。

21、dubbo配置

1. XML配置

Dubbo的XML配置是最早的配置方式,在配置过程中需要编写XML文件,指定Dubbo相关的标签和属性。其中,最基本的配置是服务提供者和服务消费者的相关配置,如下:

<!-- 服务提供者注册到注册中心 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>

<!-- 暴露服务 -->
<dubbo:service interface="com.xxx.xxxService" ref="xxxServiceImpl" timeout="3000" />

<!-- 引用服务 -->
<dubbo:reference interface="com.xxx.xxxService" id="xxxService" timeout="3000" />

在这段XML配置中,我们首先在标签中指定了注册中心的地址信息,然后在标签中指定了服务提供者的接口和实现类,以及引用服务的接口和实现。timeout属性用于设置超时时间。

除了服务提供者和服务消费者的相关配置外,还有其他相关的配置。比如,可以使用dubbo:protocol标签指定Dubbo使用的协议类型和端口号,同时也可以在dubbo:method标签中为方法单独指定超时时间等参数。

  • 服务提供者:
  • DemoService.java:
package org.apache.dubbo.demo;

public interface DemoService {
    String sayHello(String name);
}
  • 在服务提供方实现接口
  • DemoServiceImpl.java:
package org.apache.dubbo.demo.provider;
import org.apache.dubbo.demo.DemoService;

public class DemoServiceImpl implements DemoService {
    public String sayHello(String name) {
        return "Hello " + name;
    }
}
  •  用 Spring 配置声明暴露服务
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder/>

    <dubbo:application name="demo-provider"/>

    <dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/>

    <dubbo:provider token="true"/>

    <bean id="demoService" class="org.apache.dubbo.samples.basic.impl.DemoServiceImpl"/>

    <dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService" ref="demoService"/>

</beans>
  • 加载 Spring 配置
public class Application {

    public static void main(String[] args) throws InterruptedException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-demo-provider.xml");
        context.start();

        System.out.println("dubbo service started");
        // to hang up main thread
        new CountDownLatch(1).await();
    }
}
  • 服务消费者
  • 通过 Spring 配置引用远程服务 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder/>

    <dubbo:application name="demo-consumer"/>

    <dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/>

    <dubbo:reference id="demoService" check="true" interface="org.apache.dubbo.samples.basic.api.DemoService"/>

</beans>
  • 加载 Spring 配置,并调用远程服务 
public class Application {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-demo-consumer.xml");
        context.start();
        GreetingsService greetingsService = (GreetingsService) context.getBean("greetingsService");

        String message = greetingsService.sayHi("dubbo");
        System.out.println("Receive result ======> " + message);
        System.in.read();
        System.exit(0);
    }

}
2. 注解配置

注解配置是一种比较简便的配置方式,可以直接在Java代码中使用注解指定Dubbo相关的配置信息。使用注解配置时,需要在配置类中添加@EnableDubbo注解开启Dubbo相关功能,示例如下:

@Configuration
@EnableDubbo(scanBasePackages = "com.xxx.service.impl")
public class DubboConfig {
}

其中,scanBasePackages属性指定了Dubbo扫描的包路径。然后就可以在服务提供者和服务消费者的实现类中使用Dubbo提供的注解进行配置,示例如下:

@Service(timeout = 3000)
public class XxxServiceImpl implements XxxService {
    
    @Override
    public String hello(String name) {
        return "Hello " + name;
    }
}

对于服务消费者,则可以使用@DubboReference注解引用服务,示例如下:

@Service
public class XxxConsumer {
@DubboReference(timeout = 3000)
private XxxService xxxService;

public String hello(String name) {
    return xxxService.hello(name);
}
}

在这个例子中,我们使用@DubboReference注解指定了服务的接口和超时时间,然后在XxxConsumer类中通过xxxService调用服务。

3. 属性配置

属性配置是一种比较灵活的配置方式,它允许我们在配置文件中定义属性,然后在代码中读取这些属性并进行相关操作。使用属性配置时,我们需要在代码中创建一个DubboProperties对象,并将其中的属性值通过@ConfigurationProperties注解注入到该对象中。示例如下:

@Component
@ConfigurationProperties(prefix = "dubbo")
public class DubboProperties {
private String registryAddress;

// get/set方法省略
}

然后,我们可以使用这个DubboProperties对象中定义的属性配置Dubbo相关的参数,示例如下:

@Service(timeout = "#{dubboProperties.timeout}")
public class XxxServiceImpl implements XxxService {

@Autowired
private DubboProperties dubboProperties;

@Override
public String hello(String name) {
    return "Hello " + name;
}
}

在这个例子中,我们使用了#{dubboProperties.timeout}的方式,读取DubboProperties对象中的timeout属性来指定服务超时时间。我们还可以在DubboProviders对象中定义其他属性,在需要的地方使用${}的方式读取这些属性。

常用注解

@DubboService 注解

定义好 Dubbo 服务接口后,提供服务接口的实现逻辑,并用 @DubboService 注解标记,就可以实现 Dubbo 的服务暴露

@DubboService
public class DemoServiceImpl implements DemoService {}

如果要设置服务参数,@DubboService 也提供了常用参数的设置方式。如果有更复杂的参数设置需求,则可以考虑使用其他设置方式

@DubboService(version = "1.0.0", group = "dev", timeout = 5000)
public class DemoServiceImpl implements DemoService {}

 @DubboReference 注解

@Component
public class DemoClient {
    @DubboReference
    private DemoService demoService;
}

@DubboReference 注解将自动注入为 Dubbo 服务代理实例,使用 demoService 即可发起远程服务调用

@EnableDubbo 注解

@EnableDubbo 注解必须配置,否则将无法加载 Dubbo 注解定义的服务,@EnableDubbo 可以定义在主类上

@SpringBootApplication
@EnableDubbo
public class ProviderApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

 Spring Boot 注解默认只会扫描 main 类所在的 package,如果服务定义在其它 package 中,需要增加配置 EnableDubbo(scanBasePackages = {"org.apache.dubbo.springboot.demo.provider"})

22、Dubbo容器

23、Dubbo日式组件设计

适配众多日志框架,包括自定义日志打印格式。

24、Dubbo的状态统计/监控

25、集成Nacos https://cn.dubbo.apache.org/zh-cn/overview/mannual/java-sdk/reference-manual/metadata-center/nacos/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2132853.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6 递归——509. 斐波那契数 ★

6 递归 509. 斐波那契数 斐波那契数列从0和1开始,后面的每一项数字都是前面两项数字的和。F(0) = 0,F(1) = 1,当n > 1时,F(n) = F(n − 1) + F(n − 2)。给定n,请计算 F(n)。 示例 1: 输入:n = 2 输出:1 解释:F(2) = F(1) + F(0) = 1 + 0 = 1 示例 2: 输入:n …

[000-01-008].第05节:OpenFeign特性-重试机制

我的后端学习大纲 SpringCloud学习大纲 1.1.重试机制的默认值&#xff1a; 1.重试机制默认是关闭的&#xff0c;给了默认值 1.2.测试重试机制的默认值&#xff1a; 1.3.开启Retryer功能&#xff1a; 1.修改配置文件YML的配置&#xff1a; 2.新增配置类&#xff1a; packa…

CentOs 入门必备基础知识详细讲解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; CentOS&#xff08;Community ENTerprise Operating System&#xff09;是一个基于 Red Hat Enterprise Linux (RHEL) 源代码的开源操作系统&#xff0c;主要用于服务器和企业环境。下面是一个详细的入门知识…

JDBC数据库连接技术

JDBC数据库连接技术 基础篇 一、引言 1.1 数据的存储 我们在开发Java程序时&#xff0c;数据都是存储在内存中&#xff0c;属于临时存储&#xff0c;当程序停止或重启时&#xff0c;内存中的数据就丢失了&#xff01;我们为了解决数据的长期存储问题&#xff0c;有如下解决方…

【Prompt Enhancer】如何优化prompt的内容

背景 在使用LLM的时候&#xff0c;提示词的好坏对模型的输出质量影响很大&#xff0c;提示词又是一个复杂工程&#xff0c;要写出优秀的提示词&#xff0c;需要丰富的经验。正因如此&#xff0c;各类Agent平台都会有自己的提示词增强功能&#xff0c;帮助用户编写提示词。 最…

Linux驱动.之platform平台总线驱动框架(二),正点原子

第五十四章 platform设备驱动实验 我们在前面几章编写的设备驱动都非常的简单&#xff0c;都是对IO进行最简单的读写操作。像I2C、SPI、LCD等这些复杂外设的驱动就不能这么去写了&#xff0c;Linux系统要考虑到驱动的可重用性&#xff0c;因此提出了驱动的分离与分层这样的软件…

数据结构与算法-17高级数据结构_图论(迪杰斯特拉算法)

迪杰斯特拉算法 1 是什么&#xff1f; 迪杰斯特拉算法&#xff08;Dijkstra’s Algorithm&#xff09;&#xff0c;又称狄克斯特拉算法&#xff0c;是由荷兰计算机科学家埃德加狄克斯特拉&#xff08;Edsger Dijkstra&#xff09;于1959年提出的一种用于解决有权图中最短路径…

GPT-4与ChatGPT:人工智能对话的新时代【含国内可用gpt】

随着人工智能&#xff08;AI&#xff09;技术的不断突破&#xff0c;人与机器的交互方式正发生深刻的变革。在这股技术浪潮中&#xff0c;GPT-4和基于它的ChatGPT成为了令人瞩目的焦点&#xff0c;推动了对话式AI的快速发展。通过这些技术&#xff0c;我们不仅看到了AI在语言理…

【MySQL】MySQL和Workbench版本兼容问题

1、安装MySQL WorkBench 最新版本下载&#xff1a;https://dev.mysql.com/downloads/workbench/ 历史版本下载&#xff1a;https://downloads.mysql.com/archives/workbench/ 2、问题描述 本人在Windows下安装了一个旧版本的MySQL&#xff08;5.1&#xff09;&#xff0c;同…

全球NAND原厂闪存市场格局变化

根据市场研究机构TrendForce的最新跟踪报告&#xff0c;三星&#xff08;Samsung&#xff09;和SK海力士&#xff08;SK hynix-Solidigm&#xff09;在过去的一个季度中扩大了他们在NAND闪存市场的份额&#xff0c;这主要得益于抢占了铠侠&#xff08;Kioxia&#xff09;与西部…

Threejs之加载3D模型(下)

本文目录 前言一、代码示例1.1 FBXLoader1.1.1 代码1.1.2 效果1.1.3 动画1.1.3.1 动画效果 1.2 ColladaLoader1.2.1 代码1.2.2 效果 前言 本篇博客基于Threejs之加载3D模型&#xff08;上&#xff09;追加常用模型加载示例。 一、代码示例 1.1 FBXLoader 构造函数 FBXLoader(…

【C++指南】作用域限定符 :: 使用详解

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 目录 引言 1. 访问全局变量 2. 命名空间中的成员访问 3. 类的静态成员访问 4. 嵌套命名空间/类中的…

钾盐矿开采与加工过程中的机电设备选型及管理指南

创作不易&#xff0c;您的打赏、关注、点赞、收藏和转发是我坚持下去的动力&#xff01; 在钾盐矿的开采和加工过程中&#xff0c;需要使用多种机电设备以确保生产的顺利进行。这些设备主要用于矿石开采、破碎、运输、选矿以及矿物产品的深加工等过程。以下是钾盐矿常用的一些机…

vulnhub靶机:Holynix: v1

下载 下载地址&#xff1a;https://www.vulnhub.com/entry/holynix-v1,20/ 打开虚拟机 选择下载解压之后的文件打开 新添加一张 NAT 网卡&#xff0c;mac 地址修改如下 00:0c:29:bc:05:de 给原来的桥接网卡&#xff0c;随机生成一个 mac 地址 然后重启虚拟机 信息收集 主…

C++多态讲解

多态 多态的概念 通俗来说&#xff0c;就是多种形态。多态分为编译时多态(静态多态)和运行时多态(动态多态)这里重点讲运行时多态。 运行时多态 运行时多态&#xff0c;具体点就是去完成某个行为(函数)&#xff0c;可以传不同的对象就会完成不同的行为&#xff0c;就达到多种形…

在VMware上怎么安装Windows11?看这个教程就足够了

前言 Windows11与Windows10或以下版本有个最大的不同&#xff0c;就是有配置要求。 它就是TPM 2.0。 TPM的全称是Trusted Platform Module&#xff0c;中文名称为&#xff1a;可信赖平台模块。 其中TPM 2.0与上一代的版本&#xff08;TPM 1.2&#xff09;有什么区别&#xf…

使用视图方式操作MySQL数据表

7.1  认识视图 7.1.1  视图的含义 视图是一种常用的数据库对象&#xff0c;可以把它看成从一个或几个源表导出的虚表或存储在数据库中的查询&#xff0c;对视图所引用的源表来说&#xff0c;视图的作用类似于筛选。 视图一经定义后&#xff0c;就可以像源表一样被查询、修…

如何看待 IBM 中国研发部裁员

一、引言 在全球信息技术飞速发展的时代&#xff0c;跨国科技企业一直扮演着重要的角色。IBM&#xff0c;作为全球知名的信息技术和业务解决方案公司&#xff0c;在中国市场也有着长期的发展历程。然而&#xff0c;近日 IBM 中国宣布撤出在华两大研发中心&#xff0c;进行大规…

Python画笔案例-045 绘制渐变圆盘

1、绘制 渐变圆盘 通过 python 的turtle 库绘制 渐变圆盘&#xff0c;如下图&#xff1a; 2、实现代码 绘制 渐变圆盘&#xff0c;以下为实现代码&#xff1a; """本程序需要coloradd模块支持,安装方法pip install coloradd """ import turtle …

本地电脑自定义数据使用yolov8数据对象检测

1.环境&#xff1a;本地电脑配置有GPU&#xff0c;python3.10&#xff0c;pytorch2.3.1&#xff0c;opencv_contrib_python-4.10.0.82&#xff0c;pycharm-community-2024.1.4&#xff0c;ultralytics-8.2.78源代码包 2.使用X-AnyLabeling标注数据&#xff0c;把标注后数据转成…