Dubbo精要

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 againcheckInvokers(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

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

@Overridepublic 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

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

@Overridepublic 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

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

源码如下:

@Overrideprotected 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() {@Overridepublic 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.xsdhttp://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 threadnew 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.xsdhttp://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 {@Overridepublic 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 {@DubboReferenceprivate 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.mzph.cn/pingmian/53530.shtml

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

相关文章

局域网设备自动发现常用方法

文章目录 需求实现方法ARP (Address Resolution Protocol)Ping ip的流程抓包如下代码实现 mDNS 对比测试Avahi 介绍Avahi 安装Avahi 使用测试代码 需求 局域网设备自动发现是软件开发中的一个常见且重要的需求&#xff0c;它简化了设备间的协作机制&#xff0c;降低了软件各模…

实验九 多线程的处理

实验目的及要求 目的&#xff1a;理解线程的概念&#xff0c;掌握Java的多线程机制&#xff0c;会用多线程编写Java程序。 要求&#xff1a; 理解线程的概念会用Thread类创建线程会使用Runnable接口创建多线程对两种实现多线程方式的方式进行对比掌握线程的同步 二、实验环境…

Pygame中Sprite类实现多帧动画3-3

4 使用自定义类MySprite 使用自定义类MySprite实现多帧动画的步骤是首先创建MySprite类的实例&#xff0c;之后使用相关函数对该实例进行操作。 4.1 创建MySprite类的实例 创建MySprite类的实例的代码如图12所示。 图12 创建MySprite类的实例的代码 其中&#xff0c;变量dr…

TortoiseGit无法安装解决方案

Win11安装TortoiseGit报错&#xff0c;错误码&#xff1a;2503&#xff0c;如下图&#xff1a; 开始-右键-Windows PowerShell&#xff08;管理员&#xff09;/终端 (管理员) 输入 msiexec /package 安装程序所在绝对路径&#xff0c; 例如 : msiexec /package D:\我的资料…

利用鸢尾花数据集介绍PCA算法

PCA&#xff1a; 主成分分析&#xff08;PCA, Principal Component Analysis&#xff09;是一种常用的数据降维技术&#xff0c;它可以将高维数据转换为较低维数据&#xff0c;同时尽可能保留数据的主要信息。PCA通过寻找数据的主要方向&#xff0c;即方差最大的方向&#xff0…

小小GCD、LCM拿下拿下

目录 最大公约数&#xff08;GCD&#xff09; 最大公约数&#xff08;GCD&#xff09;求解&#xff1a; 一、辗转相除法 二、三目运算符 三、位运算 最大公约数&#xff08;GCD&#xff09;模板&#xff1a; 最大公约数&#xff08;GCD&#xff09;例题&#xff1a; 最…

stm32之硬件SPI读写W25Q64存储器应用案例

系列文章目录 1. stm32之SPI通信协议 2. stm32之软件SPI读写W25Q64存储器应用案例 3. stm32之SPI通信外设 文章目录 系列文章目录前言一、电路接线图二、应用案例代码三、应用案例代码分析3.1 基本思路3.2 相关库函数介绍3.3 MySPI模块3.3.1 模块初始化3.3.2 SPI基本时序单元模…

丰巢“闯关”港交所上市

社区中随处可见的智能快递柜&#xff0c;即将捧出一个IPO。 近日&#xff0c;丰巢控股有限公司&#xff08;下称“丰巢控股”或“丰巢”&#xff09;正式向港交所递交了招股书&#xff0c;华泰国际担任其独家保荐人。这将是继顺丰控股、顺丰房托、嘉里物流、顺丰同城之后&…

微服务CI/CD实践(六)Jenkins Docker 自动化构建部署Java微服务

微服务CI/CD实践系列&#xff1a; 微服务CI/CD实践&#xff08;一&#xff09;环境准备及虚拟机创建 微服务CI/CD实践&#xff08;二&#xff09;服务器先决准备 微服务CI/CD实践&#xff08;三&#xff09;gitlab部署及nexus3部署 微服务CI/CD实践&#xff08;四&#xff09…

未来餐饮革命:加入我们的智能餐厅代理、自主开拓市场计划!

系统开发集成商&#xff1a;如果您正在开发智慧餐厅系统&#xff0c;忙于寻找各种消费终端接入、那么我们将可以为您提供整套智慧餐厅系统解决方案&#xff0c;从前厅消费到后厨的明厨亮灶的解决方案。 集团公司&#xff1a;想集团化控制子公司食堂运营&#xff0c;又想以最低…

【LeetCode每日一题】——LCR 168.丑数

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目注意】六【题目示例】七【题目提示】八【解题思路】九【时间频度】十【代码实现】十一【提交结果】 一【题目类别】 优先队列 二【题目难度】 中等 三【题目编号】 LCR 168.丑数 四【题目描述…

【大数据】Hadoop里的“MySQL”——Hive,干货满满

【大数据】Hadoop里的“MySQL”——Hive&#xff0c;干货满满 文章脉络 Hive架构 HQL 表类型 创建表语法 分区 数据导入导出 函数 内置函数 UDF Java Python 在阅读本文前&#xff0c;请确保已经对Hadoop的三大组件&#xff08;HDFS、MapReduce、YARN&#xff09;有…

分布式协调服务--ZooKeeper

文章目录 ZooKeeperzk的由来zk解决了什么问题 ZK工作原理ZK数据模型zk功能1.命名服务2.状态同步3.配置中心4.集群管理 zk部署单机启动zk验证zk zk集群集群角色选举过程1.节点角色状态2.选举ID3.具体过程4.心跳机制5.ZAB协议 ZooKeeper 选举示例1.第一轮投票&#xff1a;2.节点收…

Unity TextMeshPro 设置竖排

默认竖排是这样的 但是我们要的竖排效果并不是这样我们要是竖排连续的根据文本限制来进行换行 第一步我们先设置文本的旋转Z轴为90如下图 然后我们给文本加一个Tag <rotate270> 如下图 但是这个效果还是不是我们想要的效果我们可以使用TexeMeshPro提供的一个选项EnableR…

Python画笔案例-041 绘制正方形阶梯

1、绘制正方形阶梯 通过 python 的turtle 库绘制正方形阶梯&#xff0c;如下图&#xff1a; 2、实现代码 绘制正方形阶梯&#xff0c;以下为实现代码&#xff1a; """正方形阶梯.py """ import turtledef draw_square(length):for _ in range(6…

以太网--TCP/IP协议(一)

概述 以太网是局域网的一种&#xff0c;其他的比如还有令牌环、FDDI。和局域网对应的就是广域网&#xff0c;如Internet&#xff0c;城域网等。 从网络层次看&#xff0c;局域网协议主要偏重于低层&#xff08;业内一般把物理层、数据链路层归为低层&#xff09;。以太网协议…

Qt工程使用MQTT-C库与mqtt服务器数据通信

实现mqtt订阅与发布话题&#xff0c;与mqtt服务器进行数据通信 编译环境&#xff1a;Qt5.15.2 vs2019 需要mqttc库&#xff1a;mqttc.lib, mqttc.dll&#xff08;根据MQTT-C源码编译出来的库&#xff0c;参考cmake编译MQTT-C源码-CSDN博客&#xff09; 一、Qt pro文件编写 …

数据结构C //线性表ADT结构及相关函数

数据结构&#xff08;C语言版&#xff09;严蔚敏 吴伟民 线性表ADT结构及相关函数 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块&#xff08;头文件&#xff0c;函数文件&#xff0c;主文件&#xff09; list.h头文件 /****…

LeetCode 2181.合并零之间的节点

题目描述 给你一个链表的头节点 head &#xff0c;该链表包含由 0 分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足 Node.val 0 。 对于每两个相邻的 0 &#xff0c;请你将它们之间的所有节点合并成一个节点&#xff0c;其值是所有已合并节点的值之和。然后将所有 0 …

浏览器百科:网页存储篇-如何在Chrome中打开IndexedDB窗格(十一)

1.引言 在现代Web开发中&#xff0c;网页存储技术扮演着至关重要的角色。IndexedDB作为一种低级API&#xff0c;允许客户端存储大量结构化数据&#xff0c;并提供高性能的搜索能力。在上一篇文章中&#xff0c;我们深入探讨了IndexedDB的基础知识及其应用场景。为了更有效地调…