目录
一、RPC泛化调用的应用场景
二、Dubbo RPC泛化调用的实现原理
三、Dubbo RPC泛化调用的实现步骤
四、示例代码
五、泛化调用怎么发现提供该接口的服务及服务的IP和端口?
Dubbo的RPC泛化调用是一种在调用方没有服务方提供的API的情况下,对服务方进行调用并获取结果的技术。主要用于实现一个通用的远程服务Mock框架,通过实现GenericService接口来处理所有服务请求。以下是对Dubbo RPC泛化调用的详细解释:
一、RPC泛化调用的应用场景
- 网关服务:在搭建网关服务时,网关需要作为所有RPC服务的调用端。由于网关本身不应依赖于服务提供方的接口API(否则每个新的服务发布都需要修改网关代码并重新部署),因此需要泛化调用支持。
- 测试平台:在搭建可以测试RPC调用的平台时,用户可以通过输入分组名、接口、方法名等信息来测试对应的RPC服务。此时,泛化调用可以方便地实现对不同服务的测试。
二、Dubbo RPC泛化调用的实现原理
泛化调用本质是在filter过滤链上执行的序列化和反序列化操作。
- 消费者端:通过GenericImplFilter类,在调用的invocation对象中设置generic为true,表示这是一个泛化调用。
- 生产者端:通过GenericFilter类,当发现invocation对象中的generic为true时,会进行反序列化参数,并根据方法名和参数类型调用相应的服务实现。
三、Dubbo RPC泛化调用的实现步骤
- 配置pom.xml:引入Dubbo依赖和注册中心依赖(如Zookeeper)。
- 配置application.yml:在服务提供者的application.yml中配置Dubbo相关信息,如应用名称、注册中心地址、协议名称和端口等。
- 定义服务接口:在服务接口中定义需要调用的方法。这些方法可以是原生数据类型参数、DTO对象参数或DTO对象集合参数等。
- 实现服务接口:在服务提供者的实现类中实现这些方法。这些方法的具体实现将作为远程服务被调用。
- 配置泛化调用:在服务消费者的代码中,通过ReferenceConfig配置泛化调用。设置application、interface、generic和url等属性。其中,interface属性设置为服务接口的全限定名,generic属性设置为true表示启用泛化调用。
- 调用远程服务:通过GenericService的invoke方法调用远程服务。invoke方法接受方法名、参数类型和参数值等作为输入,并返回调用结果。
四、示例代码
以下是一个简单的Dubbo RPC泛化调用的示例代码:
服务提供者代码
1、首先,我们定义服务提供者的HelloService接口和实现类:
public interface HelloService {
String sayHello(String name);
}
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name + "!";
}
}
2、然后,在服务提供者的配置文件中注册这个服务(这里以XML配置为例):
<dubbo:application name="hello-service-provider" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:service interface="com.example.HelloService" ref="helloService" />
<bean id="helloService" class="com.example.HelloServiceImpl" />
3、yaml配置:
dubbo:
application:
name: dev-dubbo-server
version: 1.0.0
registry:
address: zookeeper://127.0.0.1:2181 # N/A - 无zookeeper可配置 N/A 走直连模式测试
protocol:
name: dubbo
port: 20881
scan:
base-packages: cn.dev.dubbo.api
4、客户端泛化调用代码
在客户端,我们不需要知道HelloService接口的具体定义,而是可以通过GenericService接口进行泛化调用。以下是一个客户端泛化调用的例子:
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;
public class DubboGenericClient {
public static void main(String[] args) {
// 配置应用信息
ApplicationConfig application = new ApplicationConfig();
application.setName("hello-service-consumer");
// 配置注册中心信息
RegistryConfig registry = new RegistryConfig();
registry.setAddress("zookeeper://127.0.0.1:2181");
// 配置泛化引用
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
reference.setApplication(application);
reference.setRegistry(registry);
reference.setInterface("com.example.HelloService");
reference.setGeneric(true); // 声明为泛化接口
// 获取泛化服务实例
GenericService genericService = reference.get();
// 准备调用参数
String methodName = "sayHello";
String[] parameterTypes = new String[]{"java.lang.String"};
Object[] arguments = new Object[]{"World"};
// 执行泛化调用
Object result = genericService.$invoke(methodName, parameterTypes, arguments);
// 输出调用结果
System.out.println(result); // 输出: Hello, World!
}
}
说明
配置应用信息和注册中心信息:在客户端,我们需要配置应用名称和注册中心的地址,以便Dubbo能够找到服务提供者。
配置泛化引用:通过ReferenceConfig配置泛化引用,设置接口名称并声明为泛化接口(setGeneric(true))。
获取泛化服务实例:调用reference.get()获取GenericService实例。
准备调用参数:指定要调用的方法名称、参数类型数组和参数值数组。
执行泛化调用:通过GenericService的$invoke方法执行泛化调用,并获取调用结果。
五、泛化调用怎么发现提供该接口的服务及服务的IP和端口?
在Dubbo的泛化调用中,服务消费者发现提供特定接口的服务及其IP和端口的过程主要依赖于Dubbo的服务注册与发现机制。以下是该过程的详细解释:
-
服务提供者注册服务:
- 当服务提供者启动时,它会根据配置文件中的信息(如应用名称、服务接口、版本、协议、端口等)实例化服务,并将其注册到指定的注册中心(如ZooKeeper)。
- 注册中心会存储服务提供者的元数据,包括服务接口、应用名称、版本、IP地址、端口号以及调用方式等。
-
服务消费者订阅服务:
- 服务消费者在启动时,会根据配置文件中的信息(如应用名称、注册中心地址等)连接到注册中心。
- 消费者会向注册中心订阅它感兴趣的服务接口和版本,注册中心会返回当前可用的服务提供者列表及其元数据。
-
服务发现与调用:
- 当服务消费者需要调用某个服务时,它会通过注册中心获取当前可用的服务提供者列表。
- 消费者会根据负载均衡策略(如随机、轮询、一致性哈希等)选择一个服务提供者进行调用。
- 在调用过程中,消费者会使用Dubbo提供的通信协议(如Dubbo协议、REST协议等)与服务提供者进行通信。
- 具体的IP地址和端口号是由注册中心提供的,消费者不需要手动配置。
-
泛化调用的特殊性:
- 在泛化调用中,消费者不需要提前知道服务的具体实现类,只需要知道服务接口和调用的方法名、参数类型及返回值类型。
- Dubbo提供了
GenericService
接口来支持泛化调用,消费者可以通过该接口进行动态的服务调用。 - 在进行泛化调用时,消费者仍然需要依赖注册中心来发现服务提供者,并根据注册中心提供的元数据来进行调用。
综上所述,Dubbo的泛化调用中服务消费者发现提供特定接口的服务及其IP和端口的过程主要依赖于Dubbo的服务注册与发现机制以及注册中心提供的元数据。消费者不需要手动配置服务提供者的IP地址和端口号,而是通过注册中心动态获取这些信息。
参考:
从零开始手写 dubbo rpc 框架-12-generic-泛化调用_genericservice.$invoke-CSDN博客
dubbo 泛型调用示例 (dubbo generic call) - walle搬砖 - 博客园
dubbo接口泛化调用例子 - zhaojiatao - 博客园
dubbo实现rpc调用 dubbo rpc调用示例_mob64ca14144dde的技术博客_51CTO博客
什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!-CSDN博客
dubbo的RPC调用方式 dubbo rpc调用流程_mob6454cc6575fa的技术博客_51CTO博客
一看就会!Dubbo 泛化调用简明教程——含不同类型入参处理_dubbo泛化调用-CSDN博客
DUBBO接口获取请求ip dubbo接口调用原理_mob64ca14193248的技术博客_51CTO博客
dubbo服务暴露及服务调用流程 dubbo如何发现服务_mob64ca13f937ae的技术博客_51CTO博客
java dubbo接口获取调用来源ip_mob64ca12f6aae1的技术博客_51CTO博客
Dubbo 3中的接口级地址发现与应用级地址发现:概念与实践-百度开发者中心