目录

  • Dubbo
  • RPC
  • 什么是RPC
  • Dubbo简介
  • Dubbo 的架构
  • 支持的协议
  • Dubbo案例学习
  • 本地直连方式
  • **服务接口模块**
  • **服务提供方**
  • **服务消费方**
  • **测试**
  • Dubbo+Nacos
  • **服务公共接口**
  • **服务提供方**
  • **服务消费方**
  • **测试**



Dubbo

RPC

什么是RPC

RPC是远程过程调用(Remote Procedure Call)的缩写形式。是一种进程间的通信方式,是一种技术思想,而不是一种规范。在如今微服务火热的时代,进场需要在不同异地的服务需要互相调用,而RPC可以允许程序调用另一个地址空间(在不同服务器的服务)的过程或函数,而不用程序员去显示的编写远程调用的代码。意思即是说:无论是调用本地的方法,还是需要远程调用其他服务的方法,所需要编写的代码本质是相同的。

RPC远程调用过程示例:

dubborpc调用实战 dubbo rpc调用_java

RPC框架:Dubbo、gRPC、Thrift、HSF

RPC最核心的内容:序列化和网络通信


Dubbo简介

Dubbo是一个分布式服务框架,拥有高性能和透明化的RPC远程服务调用方案以及SOA服务治理方案。

Dubbo 是阿里巴巴公司一个开源的高性能服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案,使得应用可通过高性能 RPC 实现服务的输出、输入功能和 Spring 框架无缝集成。

其核心部分包含:

  1. 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
  2. 集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
  3. 自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。

Dubbo 的架构

dubborpc调用实战 dubbo rpc调用_alibaba_02

步骤:

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

支持的协议

dubbo、hession、rmi、http、webservice、thrift、memcached,redis。

dubbo官方推荐使用dubbo。dubbo的默认端口是20880。

因此,配置文件:

<dubbo:protocol name="dubbo" port="20880"/>

Dubbo案例学习

本地直连方式

直连模式:无注册中心,无监控,快速测试Dubbo的效果。

dubborpc调用实战 dubbo rpc调用_dubborpc调用实战_03

所需要的依赖:springboot(2.4.0)+Dubbo(2.7.1)

一共需要三个模块:

  • 服务接口模块:对外暴漏的服务接口(消费方与提供方都需要),pojo对象。
  • 服务提供方:提供方法的一方
  • 服务消费方:使用方法的一方

dubborpc调用实战 dubbo rpc调用_java_04

服务接口模块

dubborpc调用实战 dubbo rpc调用_dubborpc调用实战_05

  1. pom.xml:所需要的依赖
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!--引入dubbo相关的依赖-->
		<dependency>
			<groupId>org.apache.dubbo</groupId>
			<artifactId>dubbo</artifactId>
			<version>2.7.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
		<dependency>
			<groupId>org.apache.dubbo</groupId>
			<artifactId>dubbo-spring-boot-starter</artifactId>
			<version>2.7.1</version>
		</dependency>
  1. pojo:实现序列化
public class Student implements Serializable {
    private Integer id;
    private String name;
    //getset,toString, 构造方法省略
}
  1. service
public interface StudentService {
    public Student findAStudent();
}
服务提供方
  1. pom.xml:导入api(共同方法模块)依赖
<!--引入api的依赖-->
		<dependency>
			<groupId>com.sixu</groupId>
			<artifactId>api</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
  1. 配置文件:配置提供方端口号以及Dubbo相关配置
server.port=8081
#指定注册中心 N/A表示没有注册中心
dubbo.registry.address=N/A      
dubbo.application.name=provider
# 扫描带有@Service(指Dubbo的)的包
dubbo.scan.base-packages=com.sixu.provider.service.impl
  1. 启动类,添加@EnableDubboConfig
@SpringBootApplication
@EnableDubboConfig
public class ProviderApplication {
	public static void main(String[] args) {
		SpringApplication.run(ProviderApplication.class, args);
	}
}
  1. service层的impl

注意:类上有两个@service注解

其中一个是将这个类的Bean对象注入容器,属于Srping的,标注业务层的。

另一个属于Dubbo,作用是用来标注这是服务提供方。

@Service		//spring的
@org.springframework.stereotype.Service("studentService")		//dubbo的
public class StudentServiceImpl implements StudentService {
    @Override
    public Student findAStudent() {
        return new Student(001,"sixu");		//模拟从数据库中查询
    }
}
服务消费方
  1. pom.xml:与服务方相同,导入api(共同方法模块)依赖
  2. 配置文件
server.port=8082
dubbo.application.name=consumer
  1. 启动类上标注@EnableDubboConfig注解
  2. controller层
@RestController
public class StudentController {

    @Reference(url = "dubbo://localhost:20880")		//因为是本地直连,所以服务方有固定的地址,dubbo默认端口为20880.
    private StudentService studentService;

    @GetMapping("findAStudent")
    public String findAStudent(){
        return studentService.findAStudent().toString();
    }
}
测试

在网址上输入消费方的地址

dubborpc调用实战 dubbo rpc调用_分布式_06


Dubbo+Nacos

踩过的坑:我第一次做这个案例时,Dubbo的启动器以及dubbo-registry-nacos使用的版本都是2.7.1,但是启动项目时会报错。

No such extension com.alibaba.dubbo.registry.RegistryFactory by name nacos

然后我将版本都换成2.7.5,就正常启动了。

本次案例使用nacos作为注册中心,没有监控模块。

所以需要学习Nacos:

dubborpc调用实战 dubbo rpc调用_dubborpc调用实战_07

**案例结构:**与本地直连案例一样,3个模块。

服务公共接口

结构与本地直连案例的服务接口模块相同

  1. pom.xml
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<!--引入dubbo相关的依赖-->
		<dependency>
			<groupId>org.apache.dubbo</groupId>
			<artifactId>dubbo</artifactId>
			<version>2.7.5</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
		<dependency>
			<groupId>org.apache.dubbo</groupId>
			<artifactId>dubbo-spring-boot-starter</artifactId>
			<version>2.7.5</version>
		</dependency>

		<!--引入Nacos依赖-->
		<dependency>
			<groupId>org.apache.dubbo</groupId>
			<artifactId>dubbo-registry-nacos</artifactId>
			<version>2.7.5</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba.nacos</groupId>
			<artifactId>nacos-client</artifactId>
			<version>1.0.0</version>
		</dependency>
  1. pojo(相同)
  2. service(相同)
服务提供方
  1. pom.xml
<!--引入公共接口模块-->
		<dependency>
			<groupId>com.sixu</groupId>
			<artifactId>api</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
  1. 配置文件:application.yml
server:
  port: 8081

dubbo:
  # 配置服务信息
  application:
    name: provider
    # 禁用QOS同一台机器可能会有端口冲突现象
    qos-enable: false
    qos-accept-foreign-ip: false
  # 配置注册中心
  registry:
    address: nacos://127.0.0.1:8848
  # 设置协议-协议由提供方指定消费方被动接受
  protocol:
    name: dubbo
    port: 20880
  #扫描有@service注解的包
  scan:
    base-packages: com.sixu.provider.service.impl

spring:
  main:
    # 解决Bean重复定义问题
    allow-bean-definition-overriding: true
  1. 启动类,添加@EnableDubboConfig
  2. service层的impl(相同)
服务消费方
  1. pom.xml
<!--引入公共接口模块-->
		<dependency>
			<groupId>com.sixu</groupId>
			<artifactId>api</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
  1. 配置文件:application.yml
server:
  port: 8080

dubbo:
  # 配置服务信息
  application:
    name: consumer
    # 禁用QOS同一台机器可能会有端口冲突现象
    qos-enable: false
    qos-accept-foreign-ip: false
  # 配置注册中心
  registry:
    address: nacos://127.0.0.1:8848
  # 设置超时时间
  consumer:
    timeout: 4000
spring:
  main:
    # 解决Bean重复定义问题
    allow-bean-definition-overriding: true
  1. 启动类上标注@EnableDubboConfig注解
  2. controller层
@RestController
public class StudentController {

    @Reference
    private StudentService studentService;

    @GetMapping("findAStudent")
    public String findAStudent(){
        return studentService.findAStudent().toString();
    }
}
测试
  1. 首先启动Nacos
  2. dubborpc调用实战 dubbo rpc调用_分布式_08

  3. 依次启动提供方和消费方。
    则提供方和消费方都被注册进注册中心。
  4. dubborpc调用实战 dubbo rpc调用_分布式_09

  5. 测试结果:
  6. dubborpc调用实战 dubbo rpc调用_dubborpc调用实战_10