微服务框架(十八)Dubbo领域模型、调用链及调用方式

简介: 此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。本文为Dubbo领域模型、调用链及调用方式Protocol是服务域,它是 Invoker 暴露和引用的主功能入口,它负责Invoker的生命周期管理。Invoker是实体域

  此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。
  本文为Dubbo领域模型、调用链及调用方式

本系列文章中所使用的框架版本为Spring Boot 2.0.3-RELEASE,Spring 5.0.7-RELEASE,Dubbo 2.6.2。

Dubbo领域模型

在 Dubbo 的核心领域模型中:

  • Protocol 是服务域,它是 Invoker 暴露和引用的主功能入口,它负责 Invoker 的生命周期管理。
  • Invoker是实体域,它是Dubbo的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起invoke调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。
  • Invocation 是会话域,它持有调用过程中的变量,比如方法名,参数等。

Dubbo调用链

在这里插入图片描述

Dubbo协议请求数据发送全调用链

  1. 由实体域(Invoker)执行会话域(Invocation)的集群实现
  2. 拦截器(Filter)链的拦截过滤
  3. 监听器(Listener)的监听指向
  4. Dubbo调用(DubboInvoker)的实现
  5. 协议头交互客户端(HeaderExchangeClient)
  6. Netty通信

Dubbo协议请求数据发送全调用链

proxy0#sayHello(String)
  —> InvokerInvocationHandler#invoke(Object, Method, Object[])
    —> MockClusterInvoker#invoke(Invocation)
      —> AbstractClusterInvoker#invoke(Invocation)
        —> FailoverClusterInvoker#doInvoke(Invocation, List<Invoker<T>>, LoadBalance)
          —> Filter#invoke(Invoker, Invocation)  // 包含多个 Filter 调用
            —> ListenerInvokerWrapper#invoke(Invocation) 
              —> AbstractInvoker#invoke(Invocation) 
                —> DubboInvoker#doInvoke(Invocation)    //Dubbo同异步调用
                  —> ReferenceCountExchangeClient#request(Object, int)
                    —> HeaderExchangeClient#request(Object, int)    //协议头交互Client
                      —> HeaderExchangeChannel#request(Object, int)
                        —> AbstractPeer#send(Object)
                          —> AbstractClient#send(Object, boolean)
                            —> NettyChannel#send(Object, boolean)   //Netty通信
                              —> NioClientSocketChannel#write(Object)

DubboInvoker

Dubbo 的底层IO操作都是异步的。Consumer端发起调用后,得到一个Future对象。
对于同步调用,业务线程通过Future#get(timeout),阻塞等待Provider端将结果返回;timeout则是Consumer端定义的超时时间。

  • RpcInvocation设置相关参数pathversion
  • 获取ExchangeClient
  • 同步/异步调用模式
    1. 同步调用模式:框架获得DefaultFuture对象后,会立即调用get方法进行等待
    2. 异步调用模式:将该对象封装到FutureAdapter实例中,并将FutureAdapter实例设置到RpcContext中,供用户使用

FutureAdapter 是一个适配器,用于将Dubbo中的ResponseFutureJDK中的Future进行适配。

DubboInvoker:

public class DubboInvoker<T> extends AbstractInvoker<T> {
   
   

    private final ExchangeClient[] clients;

    protected Result doInvoke(final Invocation invocation) throws Throwable {
   
   
        RpcInvocation inv = (RpcInvocation) invocation;
        final String methodName = RpcUtils.getMethodName(invocation);
        // 设置 path 和 version 到 attachment 中
        inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
        inv.setAttachment(Constants.VERSION_KEY, version);

        ExchangeClient currentClient;
        if (clients.length == 1) {
   
   
            // 从 clients 数组中获取 ExchangeClient
            currentClient = clients[0];
        } else {
   
   
            currentClient = clients[index.getAndIncrement() % clients.length];
        }
        try {
   
   
            // 获取异步配置
            boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
            // isOneway 为 true,表示“单向”通信
            boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
            int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);

            // 异步无返回值
            if (isOneway) {
   
   
                boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
                // 发送请求
                currentClient.send(inv, isSent);
                // 设置上下文中的 future 字段为 null
                RpcContext.getContext().setFuture(null);
                // 返回一个空的 RpcResult
                return new RpcResult();
            } 

            // 异步有返回值
            else if (isAsync) {
   
   
                // 发送请求,并得到一个 ResponseFuture 实例
                ResponseFuture future = currentClient.request(inv, timeout);
                // 设置 future 到上下文中
                RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
                // 暂时返回一个空结果
                return new RpcResult();
            } 

            // 同步调用
            else {
   
   
                RpcContext.getContext().setFuture(null);
                // 发送请求,得到一个 ResponseFuture 实例,并调用该实例的 get 方法进行等待
                return (Result) currentClient.request(inv, timeout).get();
            }
        } catch (TimeoutException e) {
   
   
            throw new RpcException(..., "Invoke remote method timeout....");
        } catch (RemotingException e) {
   
   
            throw new RpcException(..., "Failed to invoke remote method: ...");
        }
    }

    // 省略其他方法
}

Dubbo调用方式

Dubbo 缺省协议采用单一长连接,底层实现是 NettyNIO 异步通讯机制;基于这种机制,Dubbo 实现了以下几种调用方式:

  • 同步调用
  • 异步调用
  • 参数回调
  • 事件通知

下述只描述异步调用,其他调用方式详细描述及例子见Dubbo 关于同步/异步调用的几种方式

异步调用

基于Dubbo底层的异步NIO实现异步调用,对于Provider响应时间较长的场景是必须的,它能有效利用Consumer端的资源,相对于Consumer端使用多线程来说开销较小。

在这里插入图片描述

Provider 端接口

public interface AsyncService {
   
   
    String goodbye(String name);
}

Consumer 配置

<dubbo:reference id="asyncService" interface="com.alibaba.dubbo.samples.async.api.AsyncService">
    <dubbo:method name="goodbye" async="true"/>
</dubbo:reference>

需要异步调用的方法,均需要使用 <dubbo:method/>标签进行描述。

Consumer 端发起调用

AsyncService service = ...;
String result = service.goodbye("samples");// 这里的返回值为空,请不要使用
Future<String> future = RpcContext.getContext().getFuture();
... // 业务线程可以开始做其他事情
result = future.get(); // 阻塞需要获取异步结果时,也可以使用 get(timeout, unit) 设置超时时间

参考资料:
1.Dubbo 关于同步/异步调用的几种方式
2.服务调用过程
3.框架设计

相关文章
|
3天前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
20 5
|
13天前
|
监控 负载均衡 Java
Spring Boot与微服务治理框架的集成
Spring Boot与微服务治理框架的集成
|
14天前
|
负载均衡 Java Nacos
Spring Boot与微服务治理框架的集成策略
Spring Boot与微服务治理框架的集成策略
|
20天前
|
存储 消息中间件 API
“论微服务架构及其应用”写作框架,软考高级,系统架构设计师
论微服务架构及其应用近年来,随着互联网行业的迅猛发展,公司或组织业务的不断扩张,需求的快速变化以及用户量的不断增加,传统的单块(Monolithic)软件架构面临着越来越多的挑战,已逐渐无法适应互联网时代对软件的要求。在这一背景下,微服务架构模式(MicroserviceArchitecturePattern)逐渐流行,它强调将单一业务功能开发成微服务的形式,每个微服务运行在一个进程中;采用HTTP等通用协议和轻量级API实现微服务之间的协作与通信。这些微服务可以使用不同的开发语言以及不同数据存储技术,能够通过自动化部署工具独立发布,并保持最低限制的集中式管理。
|
25天前
|
开发框架 移动开发 JavaScript
SpringCloud微服务实战——搭建企业级开发框架(四十七):【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能
在uni-app中,使用axios实现网络请求和登录功能涉及以下几个关键步骤: 1. **安装axios和axios-auth-refresh**: 在项目的`package.json`中添加axios和axios-auth-refresh依赖,可以通过HBuilderX的终端窗口运行`yarn add axios axios-auth-refresh`命令来安装。 2. **配置自定义常量**: 创建`project.config.js`文件,配置全局常量,如API基础URL、TenantId、APP_CLIENT_ID和APP_CLIENT_SECRET等。
152 52
|
29天前
|
Cloud Native Java API
Java一分钟之-Micronaut:轻量级微服务框架
【6月更文挑战第16天】Micronaut是面向JVM的微服务框架,以其快速启动、低内存占用著称。文章探讨了配置管理、注解理解和AOT编译的挑战,提供了解决方案,并通过一个简单的HTTP服务示例展示了如何创建控制器和应用启动类。通过克服这些问题,开发者能更好地利用Micronaut构建高效微服务。
46 8
|
12天前
|
负载均衡 监控 Java
Spring Boot与微服务治理框架的集成方法
Spring Boot与微服务治理框架的集成方法
|
12天前
|
存储 Java 数据中心
Spring Boot与微服务治理框架的集成成功案例
Spring Boot与微服务治理框架的集成成功案例
|
2月前
|
Dubbo Cloud Native 应用服务中间件
【阿里云云原生专栏】云原生环境下的微服务治理:阿里云 Dubbo 与 Nacos 的深度整合
【5月更文挑战第25天】阿里云Dubbo和Nacos提供微服务治理的强大工具,整合后实现灵活高效的治理。Dubbo是高性能RPC框架,Nacos则负责服务发现和配置管理。整合示例显示,通过Nacos注册中心,服务能便捷注册发现,动态管理配置。简化部署,提升适应性,但也需注意服务稳定性和策略规划。这种整合为云原生环境的微服务架构带来强大支持,未来应用前景广阔。
223 2
|
2月前
|
监控 Java Nacos
Java微服务框架面试总结(全面,实时更新)
Java微服务框架面试总结(全面,实时更新)