一、简介
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
二、优点
- 面向接口的远程方法调用
- 智能容错和负载均衡
- 服务自动注册和发现
- 服务接口监控与治理
三、Dubbo架构
1、 节点说明
节点 | 角色名称 |
---|---|
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 监控中心,查看服务消费者和提供者的基本信息 |
Container | 服务运行容器 |
2、调用关系说明(6步):
0.服务容器负责启动,加载,运行服务提供者。
1.服务提供者在启动时,向注册中心注册自己提供的服务。
2.服务消费者在启动时,向注册中心订阅自己所需的服务。
3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
3、Dubbo提供的注册中心有如下几种类型可供选择:
- Multicast注册中心
- Zookeeper注册中心(推荐使用)
(注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。)
- Redis注册中心
- Simple注册中心
四、推荐顺序
- 启动zookeeper注册中心
- 启动管理控制台
- 编写并启动provider
- 最后编写并启动consumer
五、服务提供者
①、pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<dependencies>
<!--基础环境-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--dubbo的起步依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
<!-- zookeeper的api管理依赖 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<!-- zookeeper依赖 -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.12</version>
</dependency>
<!--依赖公共接口-->
<dependency>
<groupId>com.zj</groupId>
<artifactId>dubbo-demo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
②、编写service实现类
@Service // 注意:这里使用org.apache.dubbo包下的
public class UserServiceImpl implements UserService {
@Override
public String sayHello(String name) {
return "Hello " + name;
}
}
③、application.yml
# dubbo.application.name 服务名称,一般跟模块名称一致即可
# dubbo.application.qos-port 服务质量模块的端口,默认值:22222
# dubbo.registry.address 注册中心的连接地址
# dubbo.protocol.name 当前服务的访问协议,支持dubbo、rmi、hessian、http、webservice、rest、redis等
# dubbo.protocol.port 当前服务的访问端口
# dubbo.scan.base-packages 包扫描,将对象交给ioc容器并暴露到注册中心
dubbo:
application:
name: dubbo-demo-provider
qos-port: 22223
registry:
address: zookeeper://127.0.0.1:2181
protocol:
name: dubbo
port: 20880
scan:
base-packages: com.zj.service
④、启动类
@SpringBootApplication
public class ProviderApp {
public static void main(String[] args) {
SpringApplication.run(ProviderApp.class, args);
}
}
六、服务消费者
①、pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<dependencies>
<!--web环境-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--dubbo的起步依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
<!-- zookeeper的api管理依赖 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<!-- zookeeper依赖 -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.12</version>
</dependency>
<!--依赖公共接口-->
<dependency>
<groupId>com.zj</groupId>
<artifactId>dubbo-demo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
②、编写controller
@RestController
public class UserController {
@Reference // 使用 org.apache.dubbo 包下注解
private UserService userService;
@GetMapping("/user/hello")
public String sayHello(String name){
return userService.sayHello(name);
}
}
③、application.yml
# dubbo.application.name 服务名称,一般跟模块名称一致即可
# dubbo.registry.address 注册中心的连接地址
# dubbo.scan.base-packages 包扫描
dubbo:
application:
name: dubbo-demo-consumer
registry:
address: zookeeper://127.0.0.1:2181
scan:
base-packages: com.zj.controller
④、启动类
@SpringBootApplication
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class, args);
}
}
七、公共接口模块抽取
①、pom.xml
<dependencies>
<!-- 因为本次我们简单练习案例,所以导入该坐标依赖,将实体类写到该模块
-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
</dependencies>
<!--没有父工程进行版本锁定,所以手动设置jdk和字符集编码-->
<build>
<plugins>
<!-- 设置编译版本为1.8 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
②、编写service接口
String sayHello(String name);
八、使用细节
1、序列化
- dubbo底层是需要通过网络传输数据的,因此被传输的对象必须实现序列化接口
- 当消费者和服务生产者之间进行传输时,不管是参数还是返回值,只要是传输的都必须实现序列化接口
2、启动时检查
启动时检查,配置在服务消费者
一方,用于服务消费者在启动的时候主动检查注册中心或者服务提供者是否准备好提供服务
- 如果配置为false,代表不检查
- 如果配置为true,代表检查,一旦检查到服务提供者未准备好,就会直接抛异常
dubbo:
consumer: # 检查服务提供者是否正常启动
check: false
registry: # 检查注册中心是否正常启动
check: false
3、服务超时
- 服务消费者在调用服务提供者的时候可能会发生阻塞、等待的情形,这个时候,如果服务消费者会一直等下去,就会造成线程堆积,服务宕机。
① 全局配置
- 如果同时设置了,消费者提供者优先级高
# dubbo允许设置一个服务的超时时间(默认为1s),如果超过这个时间,服务无法作出反应,直接终止线程。
dubbo:
provider:
timeout: 5000
retries: 0
# 这个时间可以设置在服务调用者一端,也可以设置在服务提供者一端
dubbo:
consumer:
timeout: 3000
retries: 0
② 局部配置【推荐】
- dubbo还支持在类上定义超时时间,其优先级高于全局配置
//1. 在服务提供端声明
@Service(timeout = 3000, retries = 0)
public class UserServiceImpl implements UserService{}
//2. 在服务调用端声明
public class Controller{
@Reference(timeout = 6000,retries = 0)
private UserService userService;
}
4、服务重试
-
dubbo设置了超时时间,如果在这个时间段内,无法完成服务访问,则自动断开连接。
-
为了弥补这一特性的缺点,保证系统健壮,dubbo提供了重试机制。
public class Controller{
@Reference(timeout = 2000,retries = 4) // 默认值是重试两次
private UserService userService;
}
5、 服务降级
当一个请求发生超时,一直等待着服务响应,那么在高并发情况下,很多请求都是因为这样一直等着响应,
直到服务资源耗尽产生宕机,而宕机之后会导致分布式其他服务调用该宕机的服务也会出现资源耗尽宕机, 这样下去将导致整个分布式服务都瘫痪。
@RestController
public class Controller {
@Reference(mock = "fail:return 默认值")
private UserService userService;
}
6、负载均衡–智能容错
- 负载均衡策略 : 解决服务器消费者的一个请求到底应该由哪一个服务提供者去处理
- 在高并发情况下,一个服务往往需要以集群的形式对外工作。
dubbo支持四种负载均衡策略:
- Random:按权重随机选择,这是默认值。
- RoundRobin:按权重轮询选择。
- LeastActive:最少活跃调用数,相同活跃数的随机选择。
- ConsistentHash:一致性Hash,相同参数的请求总是发到同一提供者。
使用:
@Reference(loadbalance = "RoundRobin")
集群和分布式区别:
* 集群:(高可用)
多台服务器重复完成同一个任务,即同一个任务部署在多台服务器上
* 分布式:(高性能)
多台服务器协同完成同一个任务,即同一个任务拆分为多个子任务,多个子任务部署在多台服务器上协同完成同一个任务
7 、多版本
- dubbo使用version属性来设置和调用同一个接口的不同版本
实例:
①、服务提供者1(provider1)
@Service(version = "v1.0") //设置版本为v1.0
public class HelloServiceImpl implements HelloService {}
②、服务提供者2(provider2)
@Service(version = "v2.0") //设置版本为v2.0
public class HelloServiceImpl implements HelloService {}
③、服务消费者(consumer)
@RestController
public class HelloController {
@Reference(version = "v1.0") // 指定哪个版本
private HelloService helloService;
}