12-Dubbo服务调用过程-服务调用方式

专栏目录

1-Dubbo架构设计与底层原理-架构设计
2-Dubbo架构设计与底层原理-SPI源码分析
3-Dubbo架构设计与底层原理-自适应拓展原理
4-Dubbo架构设计与底层原理-服务导出源码分析(上)
5-Dubbo架构设计与底层原理-服务导出源码分析(中)
6-Dubbo架构设计与底层原理-服务导出源码分析(下)
7-Dubbo架构设计与底层原理-服务引用源码分析(上)
8-Dubbo架构设计与底层原理-服务引用(下)
9-Dubbo架构设计与底层原理-集群容错之 Directory
10-Dubbo架构设计与底层原理-集群容错之 Router
11-Dubbo架构设计与底层原理-集群容错之 LoadBalance
12-Dubbo服务调用过程-服务调用方式
13-Dubbo服务调用过程源码分析-服务消费方发送请求
14-Dubbo服务调用过程源码分析-服务提供方接收请求
15-Dubbo服务调用过程源码分析-服务提供方响应请求

服务调用过程

Dubbo 服务调用过程比较复杂,包含众多步骤。比如发送请求、编解码、服务降级、过滤器链处理、序列化、线程派发以及响应请求等步骤。重点分析请求的发送与接收、编解码、线程派发以及响应的发送与接收等过程。

Dubbo 服务调用过程:

在这里插入图片描述

首先服务消费者通过代理对象 Proxy 发起远程调用,接着通过网络客户端 Client 将编码后的请求发送给服务提供方的网络层上,也就是 Server。Server 在收到请求后,首先要做的事情是对数据包进行解码。然后将解码后的请求发送至分发器 Dispatcher,再由分发器将请求派发到指定的线程池上,最后由线程池调用具体的服务。这就是一个远程调用请求的发送与接收过程。

服务调用方式

Dubbo 支持同步和异步两种调用方式,其中异步调用还可细分为“有返回值”的异步调用和“无返回值”的异步调用。所谓“无返回值”异步调用是指服务消费方只管调用,但不关心调用结果,此时 Dubbo 会直接返回一个空的 RpcResult。若要使用异步特性,需要服务消费方手动进行配置。默认情况下,Dubbo 使用同步调用方式。

从 DemoService 接口的代理类开始进行分析。Dubbo 默认使用 Javassist 框架为服务接口生成动态代理类,因此需要先将代理类进行反编译才能看到源码。

public class proxy0 implements ClassGenerator.DC, EchoService, DemoService {
   
    // 方法数组
    public static Method[] methods;
    private InvocationHandler handler;

    public proxy0(InvocationHandler invocationHandler) {
   
        this.handler = invocationHandler;
    }

    public proxy0() {
   
    }

    public String sayHello(String string) {
   
        // 将参数存储到 Object 数组中
        Object[] arrobject = new Object[]{
   string};
        // 调用 InvocationHandler 实现类的 invoke 方法得到调用结果
        Object object = this.handler.invoke(this, methods[0], arrobject);
        // 返回调用结果
        return (String)object;
    }

    /** 回声测试方法 */
    public Object $echo(Object object) {
   
        Object[] arrobject = new Object[]{
   object};
        Object object2 = this.handler.invoke(this, methods[1], arrobject);
        return object2;
    }
}

首先将运行时参数存储到数组中,然后调用 InvocationHandler 接口实现类的 invoke 方法,得到调用结果,最后将结果转型并返回给调用方。

public class InvokerInvocationHandler implements InvocationHandler {
   

    private final Invoker<?> invoker;

    public InvokerInvocationHandler(Invoker<?> handler) {
   
        this.invoker = handler;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
    {
   
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        
        // 拦截定义在 Object 类中的方法(未被子类重写),比如 wait/notify
        if (method.getDeclaringClass() == Object.class) {
   
            return method.invoke(invoker, args);
        }
        
        // 如果 toString、hashCode 和 equals 等方法被子类重写了,这里也直接调用
        if ("toString".equals(methodName) && parameterTypes.length == 0) {
   
            return invoker.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
   
            return invoker.hashCode
Nacos和Dubbo都是阿里巴巴开源的项目,Nacos是一款基于云原生架构的动态服务发现、配置管理和服务管理平台,而Dubbo是一款高性能的分布式服务框架。 在使用Nacos和Dubbo进行服务调用时,需要使用Nacos提供的服务发现功能来获取可用的Dubbo服务,然后使用Dubbo提供的RPC框架进行远程调用。 下面是一个使用Nacos和Dubbo进行服务调用的客户端实现示例: 1. 添加依赖 在项目的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>${nacos.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.version}</version> </dependency> ``` 其中,${nacos.version}和${dubbo.version}需要根据您使用的版本进行替换。 2. 配置Nacos客户端 在使用Nacos之前,需要先配置Nacos客户端。可以在application.properties文件中添加以下配置: ```properties # Nacos配置 spring.cloud.nacos.config.server-addr=localhost:8848 spring.cloud.nacos.config.namespace= spring.cloud.nacos.config.file-extension=properties # Dubbo配置 dubbo.registry.address=nacos://localhost:8848 ``` 其中,spring.cloud.nacos.config.server-addr为Nacos服务器地址,dubbo.registry.address为Dubbo注册中心地址。 3. 获取Dubbo服务 使用Nacos提供的服务发现功能,获取可用的Dubbo服务。可以在代码中添加以下方法: ```java public List<Invoker<?>> getDubboService(String serviceName) throws NacosException { // 创建Nacos服务发现客户端 NamingService namingService = NacosFactory.createNamingService(nacosProperties.getConfigServerAddr()); // 获取可用的Dubbo服务 List<Instance> instances = namingService.getAllInstances(serviceName); if (instances == null || instances.isEmpty()) { throw new RuntimeException("No available Dubbo service"); } // 将Dubbo服务转换为Invoker List<Invoker<?>> invokers = new ArrayList<>(); for (Instance instance : instances) { URL url = new URL("dubbo", instance.getIp(), instance.getPort(), serviceName); Invoker<?> invoker = new DubboInvoker<Object>(Object.class, url, new RpcClientWrapper()); invokers.add(invoker); } return invokers; } ``` 其中,serviceName为Dubbo服务名称。 4. 远程调用Dubbo服务 获取到可用的Dubbo服务之后,就可以使用Dubbo提供的RPC框架进行远程调用。可以在代码中添加以下方法: ```java public Object invokeDubboService(List<Invoker<?>> invokers, String methodName, Object... args) throws RpcException { // 创建Dubbo调用上下文 RpcContext rpcContext = RpcContext.getContext(); // 随机选择一个Dubbo服务 Invoker<?> invoker = invokers.get(new Random().nextInt(invokers.size())); // 设置Dubbo调用上下文 rpcContext.setInvoker(invoker); rpcContext.setMethodName(methodName); rpcContext.setArguments(args); // 远程调用Dubbo服务 Result result = invoker.invoke(new RpcInvocation(methodName, new Class<?>[0], args)); if (result.hasException()) { throw result.getException(); } return result.getValue(); } ``` 其中,invokers为获取到的Dubbo服务列表,methodName为Dubbo服务方法名,args为Dubbo服务方法参数。 使用以上方法,就可以在Nacos和Dubbo的帮助下,轻松实现服务调用客户端。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xianghan收藏册

极简精品作,一分也是一份鼓励哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值