简介
Apache Dubbo是一款高性能的Java RPC框架.其前身是阿里巴巴公司开源的一个高性能,轻量级的开源Java RPC框架,可以和Spring框架无缝集成.
Dubbo 官网
RPC
RPC介绍
Remote Procedure Call 远程过程调用,是分布式架构的核心,按响应方式分以下两种:
- 同步调用:客户端调用服务方方法,等待直到服务方返回结果或者超时,再继续自己的操作
- 异步调用:客户端把消息发送给中间件,不再等待服务端返回,直接继续自己的操作
RPC是一种进程间的通信方式,它允许应用程序调用网络上的另一个应用程序中的方法,对于服务消费者而言,无需了解远程调用的底层细节,是透明的.
需要注意的是RPC并不是一个具体的技术,而是指整个网络远程调用过程
RPC是一个泛化的概念,严格来说一切远程过程调用手段都属于RPC范畴,各种开发语言都有自己的RPC框架.JAVA中RPC框架比较多,广发使用的有Dubbo,RMI,Spring Cloud,Hessian等.
RPC组件
简单来说一个RPC架构里包含以下4个组件:
- 客户端(Client):服务调用者
- 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数打包成网络消息,再通过网络发送给服务方
- 服务端存根(Server Stub):接受客户端发送过来的消息并解包,再调用本地服务
- 服务端(Server):服务提供者
RPC调用
- 客户端调用以本地调用方式调用服务
- 客户端存根接收到调用后负责将方法,参数等组装成能够进行网络传输的消息体,在Java里就是序列化的过程
- 客户端存根找到服务地址,并将消息通过网络发送到服务端;
- 服务端存根收到消息后进行解码,在Java里就是反序列化的过程
- 服务端存根根据解码结果调用本地服务
- 本地服务执行处理逻辑
- 本地服务将结果返回给服务端存根
- 服务端存根将返回结果打包成消息,Java里的序列化
- 服务端存根将打包后的消息通过网络发送至消费方
- 客户端存根接收到消息,并进行解码,Java里的反序列化
- 服务调用方得到最终结果
Dubbo
Dubbo架构
Dubbo架构图(Dubbo官方提供)如下:
节点角色说明
节点 | 角色说明 |
---|---|
Provider(服务提供者) | 暴露服务的服务提供方 |
Consumer(服务消费者) | 调用远程服务的服务消费方 |
Registry(服务注册中心) | 服务注册与发现的注册中心 |
Monitor(服务监控中心) | 统计服务的调用次数和调用时间的监控中心 |
Container(服务容器) | 服务运行容器 |
注意:
- 虚线都是异步访问,实线都是同步访问
- 蓝色虚线:在启动时完成的功能
- 红色虚线(实线)都是程序运行过程中执行的功能
调用关系说明
- 服务容器负责启动,加载,运行服务提供者
- 服务提供者在启动时,向注册中心注册自己提供的服务
- 服务消费者在启动时,向注册中心订阅自己所需的服务
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
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
*/
@RestController
public class UserController {
@Reference
UserService 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
*/
@Service
public class UserServiceImpl implements UserService {
@Override
public User findById(String id) {
User user = new User();
user.setId(id);
user.setName("番茄炒蛋");
return user;
}
}
测试: