简介

Apache Dubbo是一款高性能的Java RPC框架.其前身是阿里巴巴公司开源的一个高性能,轻量级的开源Java RPC框架,可以和Spring框架无缝集成.

Dubbo 官网

RPC

RPC介绍

Remote Procedure Call 远程过程调用,是分布式架构的核心,按响应方式分以下两种:

  1. 同步调用:客户端调用服务方方法,等待直到服务方返回结果或者超时,再继续自己的操作
  2. 异步调用:客户端把消息发送给中间件,不再等待服务端返回,直接继续自己的操作

RPC是一种进程间的通信方式,它允许应用程序调用网络上的另一个应用程序中的方法,对于服务消费者而言,无需了解远程调用的底层细节,是透明的.

需要注意的是RPC并不是一个具体的技术,而是指整个网络远程调用过程

RPC是一个泛化的概念,严格来说一切远程过程调用手段都属于RPC范畴,各种开发语言都有自己的RPC框架.JAVA中RPC框架比较多,广发使用的有Dubbo,RMI,Spring Cloud,Hessian等.

RPC组件

简单来说一个RPC架构里包含以下4个组件:

  1. 客户端(Client):服务调用者
  2. 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数打包成网络消息,再通过网络发送给服务方
  3. 服务端存根(Server Stub):接受客户端发送过来的消息并解包,再调用本地服务
  4. 服务端(Server):服务提供者

RPC调用

  1. 客户端调用以本地调用方式调用服务
  2. 客户端存根接收到调用后负责将方法,参数等组装成能够进行网络传输的消息体,在Java里就是序列化的过程
  3. 客户端存根找到服务地址,并将消息通过网络发送到服务端;
  4. 服务端存根收到消息后进行解码,在Java里就是反序列化的过程
  5. 服务端存根根据解码结果调用本地服务
  6. 本地服务执行处理逻辑
  7. 本地服务将结果返回给服务端存根
  8. 服务端存根将返回结果打包成消息,Java里的序列化
  9. 服务端存根将打包后的消息通过网络发送至消费方
  10. 客户端存根接收到消息,并进行解码,Java里的反序列化
  11. 服务调用方得到最终结果

Dubbo

Dubbo架构

Dubbo架构图(Dubbo官方提供)如下:

节点角色说明

节点角色说明
Provider(服务提供者)暴露服务的服务提供方
Consumer(服务消费者)调用远程服务的服务消费方
Registry(服务注册中心)服务注册与发现的注册中心
Monitor(服务监控中心)统计服务的调用次数和调用时间的监控中心
Container(服务容器)服务运行容器

注意:

  • 虚线都是异步访问,实线都是同步访问
  • 蓝色虚线:在启动时完成的功能
  • 红色虚线(实线)都是程序运行过程中执行的功能

调用关系说明

  1. 服务容器负责启动,加载,运行服务提供者
  2. 服务提供者在启动时,向注册中心注册自己提供的服务
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

Dubbo快速开发

代码结构过于复杂,这里只展示部分代码,全部代码地址 存入git.


服务消费者

package com.fanqiechaodan.controller;import com.fanqiechaodan.pojo.User;import com.fanqiechaodan.service.UserService;import org.apache.dubbo.config.annotation.Reference;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;/** * @author fanqiechaodan * @Classname UserController * @Description */@RestControllerpublic class UserController {@ReferenceUserService userService;@GetMapping(value = "/get/{id}")public User getUser(@PathVariable(value = "id")String id){return userService.findById(id);}}

服务提供者

package com.fanqiechaodan.service.impl;import com.fanqiechaodan.service.UserService;import com.fanqiechaodan.pojo.User;import org.apache.dubbo.config.annotation.Service;/** * @author fanqiechaodan * @Classname UserServiceImpl * @Description */@Servicepublic class UserServiceImpl implements UserService {@Overridepublic User findById(String id) {User user = new User();user.setId(id);user.setName("番茄炒蛋");return user;}}

测试: