dubbo——回声测试、泛化调用、RPC调用原理

本文详细介绍了Dubbo的回声测试,用于检查服务是否可用;接着讨论了泛化调用的实现及在服务未启动时可能导致的问题及其解决方法;最后探讨了RPC调用的基本原理,包括服务方如何创建中转对象和服务消费端如何生成代理对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

回声测试

检测服务是否可用,dubbo获取的所有服务代理对象都实现了EchoService接口,用于监控
在这里插入图片描述
代码实现

如果没问题返回OK字符串否则抛出异常在这里插入图片描述
输出结果
在这里插入图片描述实际生产中可以部署这样一个接口进行测试service的可用性

泛化调用

当provider发布了某个接口A,但Consumer不知道这个接口A具体内容,但直到其中某个方法时,可采用泛化调用(但不推荐,影响透明化),跨越了消费端的代理对象

在消费端引用接口时开启

<!-- 声明需要暴露的服务接口 -->    
<dubbo:reference id="hystrixService" interface="com.sdcuike.dubbo.learning.service.HystrixService"           generic="true" retries="0"/>

generic="true"这个就是用来表示当前接口是泛化调用的

代码中调用时

//获取上下文
 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring.xml"}); 
 //获取bean,强转成GenericService(这是一个代理对象,dubbo定义的) 
 GenericService hystrixService=(GenericService) context.getBean("hystrixService")
 //调用方法,这里第一个参数是方法名,第二个是参数类型,第三个是实际入参
 Object result = hystrixService.$invoke("testGenerRe", new String[]{"java.lang.String"}, new Object[]{"test"});

1、问题:若泛化调用服务消费端先启动,在服务提供端未启动之前,泛化调用服务消费端某接口(a)进行了一次调用,在后续即使服务提供端成功启动,泛化调用服务消费端依然不能正常访问某接口(a)
2、原因:因为ReferenceConfig实例很重,封装了与注册中心的连接以及与提供者的连接,需要缓存,否则重复生成ReferenceConfig可能造成性能问题并且会有内存和连接泄漏。所以在调用服务时,不论服务提供端接口服务是否存在,ReferenceConfigCache都会缓存ReferenceConfig实例(若调用服务提供端不存在,ReferenceConfig实例的ref参数为空,即不能生成GenericService对象),再下次请求时,即使服务提供端正常提供服务,但因为ReferenceConfigCache已经缓存了ReferenceConfig实例,所以不会再重新创建链接,直接从ReferenceConfigCach缓存中获取GenericService对象,导致GenericService实例一直报空指针(因为ref参数为空),最终导致一直调用不到真正的服务
3、处理方法:在GenericService对象调用方法($invoke)之前,先判断GenericService是否为空,若为空,则调用ReferenceConfigCache对象的destroy方法,下次调用时即会重新生成ReferenceConfig实例,不会再从缓存中取。

RPC调用原理

rpc是一种协议,客户端生成代理对象,服务端暴露中转对象,网络中使用rmi或者socket等协议都可以
在这里插入图片描述
服务方创建中转对象(源码)
在这里插入图片描述
主动暴露(手写)
在这里插入图片描述
在这里插入图片描述
消费端创建代理对象
在这里插入图片描述

Dubbo泛化调用是一种动态调用服务方法的方式,通过这种方式,调用方无需依赖具体的接口类,只需传递服务名、方法名和参数即可。而Dubbo无参的泛化调用,指的是调用方不需要传递具体的参数值,只需指定参数的类型即可。 在Dubbo中,无参的泛化调用可以使用GenericService接口来实现。调用方需要首先获取到GenericService实例,然后使用该实例进行远程调用。具体实现方式如下: 1. 获取GenericService实例 ```java ReferenceConfig<GenericService> reference = new ReferenceConfig<>(); reference.setInterface("com.xxx.service.XxxService"); reference.setGeneric(true); GenericService genericService = reference.get(); ``` 2. 构建请求参数 ```java List<String> parameterTypes = new ArrayList<>(); // 添加方法参数类型 parameterTypes.add("java.lang.String"); parameterTypes.add("com.xxx.model.User"); Object[] arguments = new Object; // 构建参数值 arguments = "test"; User user = new User(); user.setName("test"); arguments = user; // 构建请求对象 GenericServiceRequest request = new GenericServiceRequest(); request.setMethodName("testMethod"); request.setParameterTypes(parameterTypes.toArray(new String)); request.setArguments(arguments); ``` 3. 发起远程调用 ```java Object result = genericService.$invoke("testMethod", parameterTypes.toArray(new String), arguments); ``` 其中,$invoke()方法的第一个参数是方法名,第二个参数是方法参数类型数组,第三个参数是方法参数值数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值