前置知识-Dubbo
1.介绍
- Dubbo是阿里巴巴公司开源的一个高性能、轻量级的 Java RPC 框架。
- 致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。
- 官网:http://dubbo.apache.org
目前Dubbo在企业中有两种开发思路
- 基于SOA思想
- 将传统单一应用拆分为web(消费者)模块和service(提供者)模块,基于Dubbo通信
- 辅助SpringCloud架构提升效率
- Dubbo基于TCP(传输层)协议,效率更高。可以替换Feign,提升高并发压力
- Dubbo的基本架构
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于负载均衡算法,选择提供者进行调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
2.快速入门
- 下载nacos
- 下载nacos并解压
- 在bin目录下startup.cmd -m standalone
- 查看 http://127.0.0.1:8848/nacos
- 下载DubboAdmin管理后台
1
2
3
4
5
6
7
8
9
10#1、下载代码:
git clone https://github.com/apache/dubbo-admin.git
#2、在 dubbo-admin-server/src/main/resources/application.properties中指定注册中心地址
#3、构建
mvn clean package -D maven.test.skip=true
#4、启动
mvn --projects dubbo-admin-server spring-boot:run
#或者
cd dubbo-admin-distribution/target; java -jar dubbo-admin-0.1.jar
#5、访问 http://localhost:8080 - 搭建服务提供者
- 依赖导入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--dubbo的起步依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>2.7.8</version>
</dependency>
</dependencies> - 将service,mapper,domain导入到提供者模块中
- 把实现类的@service注解改为@DubboService
- 配置application.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27server:
port: 18081
spring:
datasource:
url: jdbc:mysql://localhost:3306/dubbo-demo?useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
application:
name: user-provider
logging:
level:
cn.itcast: debug
pattern:
dateformat: HH:mm:ss:SSS
#配置Dubbo提供者
#Dubbo协议和访问端口
dubbo:
protocol:
name: dubbo
port: 20881
#注册中心地址
registry:
address: nacos://127.0.0.1:8848
#Dubbo注解的扫描
scan:
base-packages: cn.itcast.user.service
- 依赖导入
- 搭建消费者
- 导入依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<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.8</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>2.7.8</version>
</dependency>
</dependencies> - 将controller,service接口导入到提供者模块中
- 把控制层的@Autowired注解改为@DubboReference
- 配置application.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13server:
port: 18080
spring:
application:
name: user-consumer
logging:
level:
cn.itcast: debug
pattern:
dateformat: HH:mm:ss:SSS
dubbo:
registry:
address: nacos://127.0.0.1:8848
- 导入依赖
- 最佳实践
- 将API接口抽取为独立模块,并且把接口有关的domain都放到这个模块中
- 抽取服务提供者的domain和service接口
- 在消费者和服务者中引入公共api依赖
- 在实体类实现Serializable反序列化
3.高级特性
3.1启动检查
- 为了保障服务的正常可用,Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常
- 当启动消费者时,会去检查服务站是否存在,如果不存在,则会报错
- 关闭启动检查
1
2
3
4
5 dubbo:
registry:
address: nacos://127.0.0.1:8848
consumer:
check: false- 这时启动就不会报错,但是调用接口还是会报错
3.2多版本
- 在正式系统中,为了保证系统可用性和更好的并发性,往往通过集群部署。
- 如果提供者代码出现重大更新。如何对提供者升级部署呢?
- Dubbo提供了提供者多版本的支持,平滑处理项目功能升级部署
- 先升级一个服务者和一个消费者,等测试没问题在升级剩余的
- 实现
- 编写新的UserServce实现类,作为新版本代码
- 在暴露服务时,指定服务版本
- @DubboService(version = “2.0.0”)
- 消费者引用服务时,指定引用的服务版本
- @DubboReference(version = “2.0.0”)
3.3超时与重试
- 服务消费者在调用服务提供者发生了阻塞、等待的情形的时候,这个时候,服务消费者会一直等待下去。在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩。
- dubbo 利用超时机制来解决这个问题(使用timeout属性配置超时时间,默认值1000,单位毫秒)
- 若超时时间较短,当网络波动时请求就会失败,Dubbo通过重试机制避免此类问题的发生
- 消费者向提供者总共请求3次,所以重试机制对增删改等数据库操作可能造成问题,尽量只在查数据时使用
- 配置重试机制
- @DubboService(version = “2.0.0”,reties = 0)
1
2
3
4
5
6dubbo:
registry:
address: nacos://127.0.0.1:8848
consumer:
check: false
reties: 0
- @DubboService(version = “2.0.0”,reties = 0)
3.4负载均衡
- 在集群部署时,Dubbo提供了4种负载均衡策略,帮助消费者找到最优提供者并调用
- Random :按权重随机,默认值。按权重设置随机概率。
- RoundRobin :按权重轮询
- LeastActive:最少活跃调用数,相同活跃数的随机。
- ConsistentHash:一致性 Hash,相同参数的请求总是发到同一提供者。
- 使用
@DubboReference(loadbalance = “roundrobin”)
4.Spring-cloud整合Dubbo
4.1为什么需要Dubbo
- Feign基于Http协议(应用层),在高并发场景下性能不够理想,容易成为性能瓶颈
- Dubbo框架的通信协议采用TCP协议(数据传输层)
- Dubbo默认通过Netty构造TCP长连接的方式进行通信,性能较高
- 使用SpringCloud整合Dubbo,即为强强联合。
- 官方地址: https://github.com/alibaba/spring-cloud-alibaba
4.2案例
- 抽取接口模块dubbo-api
- 导入依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--nacos注册中心的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--springcloud alibaba dubbo依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>cn.itcast</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency> - 抽取接口
1
2
3
4
5package cn.itcast.dubbo.api;
import cn.itcast.dubbo.domain.User;
public interface UserService {
User queryById(Long id);
}
- 导入依赖
- 改造服务提供者
- 暴露接口
1
2
3
4
5
6
7
8
9
10
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public User queryById(Long id) {
return userMapper.findById(id);
}
} - 配置yaml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21spring:
datasource:
url: jdbc:mysql://localhost:3306/dubbo-demo?useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
#配置dubbo,注册中心,暴露的端口和协议,dubbo注解的包扫描
dubbo:
protocol:
name: dubbo
port: 20881
registry:
address: spring-cloud://localhost #使用SpringCloud中的注册中心
scan:
base-packages: cn.itcast.user.service #dubbo中包扫描
- 暴露接口
- 改造服务消费者
- 引入dubbo服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class OrderController {
private OrderService orderService;
private UserService userService;
public Order queryOrderByUserId( { Long orderId)
//根据id查询订单
Order order = orderService.queryOrderById(orderId);
//获取用户id
Long userId = order.getUserId();
//查询用户
User user = userService.queryById(userId);
//设置用户对象
order.setUser(user);
// 根据id查询订单并返回
return order;
}
} - 配置yaml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
#dubbo配置
dubbo:
registry:
address: spring-cloud://localhost #使用cloud的注册中心
consumer:
check: false #dubbo默认有启动检查
retries: 0 #dubbo内置的重试机制
- 引入dubbo服务
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Lemon的博客!