Dubbo是阿里的内部RPC框架,于2011年对外提供,2019年捐献给Apache,至此由Apache维护更新,Dubbo依赖Spring,除了RPC访问外,还提供了服务治理功能,如:负载均衡、数据统计等
结合上图,Dubbo主要分为5个角色:
角色 | 描述 |
---|---|
Provider | 服务提供者 |
Container | 容器,即Spring容器,提供者借助Spring初始化 |
Register | 注册中心,存放提供者对外提供的信息。如ip、端口、协议、对外接口等 |
Consumer | 消费者,RPC调用方 |
Monitor | 监控中心,统计访问情况 |
图中虚线部分均为异步,实线为同步,流程为:
0. start:启动Spring容器时,初始化Provider
1. register:Provider信息注册到Registry
2. subscribe:Consumer通过Registry订阅
3. notify:Registry将Provider信息通知给Consumer
4. invoke:Consumer通过Provider信息调用Provider方法
5. count:将访问信息上传到Monitor
Dubbo支持的协议
协议 | 优点 | 缺点 |
---|---|---|
Dubbo协议(官方推荐) | 采用NIO复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率,性能较好 | 大文件上传时,可能出现问题 |
RMI协议 | JDK自带 | 偶尔连接失败 |
Hessian协议 | 可与原生Hessian互操作,基于HTTP协议 | 需hessian.jar支持,http短连接的开销大 |
Dubbo支持的注册中心
注册中心 | 优点 | 缺点 |
---|---|---|
Zookeeper(官方推荐) | 支持分布式,生态圈大 | 受限于zookeeper软件的稳定性,但通过分布式辅助软件可以解决 |
Multicast | 去中心化,不需要单独安装软件 | Provider和Consumer和Registry不能跨机房(路由) |
Redis | 支持集群,性能高 | 要求服务器时间同步,否则会出现集群失败问题 |
Simple | 标准RPC服务,没有兼容问题 | 不支持集群 |
一、使用Dubbo
创建一个maven工程,依赖springboot
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.0</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.8</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
</dependencies>
</dependencyManagement>
1. api模块
新建Maven子模块,作为对外接口:
定义接口:
public interface DemoService {
public String demo(String demo);
}
2. provider模块
新建Maven子模块,作为提供者
2.1 导入依赖
provider不需要作为web项目
<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>
</dependency>
<!--zookeeper-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<!--api模块-->
<dependency>
<groupId>com.aruba.demo1</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
2.2 springboot配置文件
resources目录下新建application.yml,配置dubbo,内容如下:
dubbo:
application:
name: dubbo-provider
registry:
address: zookeeper://192.168.42.4:2181
2.3 实现对外接口
使用@DubboService注解,表示该对象为Dubbo使用的Provider对象
@DubboService
public class DemoServiceImpl implements DemoService {
@Override
public String demo(String demo) {
return demo + ",hello";
}
}
2.4 启动springboot
使用注解开启dubbo
@SpringBootApplication
@EnableDubbo
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
3. consumer模块
创建一个Maven子模块,作为调用方
3.1 导入依赖
<dependencies>
<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>
</dependency>
<!--zookeeper-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<!--api模块-->
<dependency>
<groupId>com.aruba.demo1</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
3.2 springboot配置文件
在resources目录下新建application.xml,内容为:
dubbo:
application:
name: dubbo-consumer
registry:
address: zookeeper://192.168.42.4:2181
3.3 service层
定义接口:
public interface DemoConsumerService {
public String demoConsumer();
}
实现接口,远程对象使用@DubboReference注解注入:
@Service
public class DemoConsumerServiceImpl implements DemoConsumerService {
@DubboReference
private DemoService service;
@Override
public String demoConsumer() {
return service.demo("dubbo");
}
}
3.4 controller层
@RestController
public class DemoController {
@Autowired
private DemoConsumerService service;
@RequestMapping("/demo")
public String demo() {
return service.demoConsumer();
}
}
3.5 SpringBoot启动类
同样需要使用@EnableDubbo注解开启dubbo
@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
浏览器访问结果:
二、负载均衡
Dubbo内置了以下负载均衡策略:
策略名 | 描述 |
---|---|
Random(默认) | 随机访问集群中节点,概论与权重有关 |
RoundRobin | 轮询访问集群中节点,频率与权重有关,2.7.8版本权重不设置不生效 |
LeastActive | 活跃数相同的随机,高活跃数的优先访问 |
ConsistentHash | 相同请求参数总是发到一个节点 |
ShortestResponse | 最快响应,选出响应时间最短的节点 |
使用方式
Provider和Consumer都可以使用以上策略,指定策略名使用全小写,第一种方式为注解时指定:
对象 | 注解 | 指定属性 |
---|---|---|
Provider | @DubboService | loadbalance 如:@DubboService(loadbalance = "roundrobin") |
Consumer | @DubboReference | loadbalance 如:@DubboReference(loadbalance = "random") |
第二种方式为springboot配置文件中指定全局策略:
dubbo:
application:
name: dubbo-provider
registry:
address: zookeeper://192.168.42.4:2181
#指定provider的负载均衡策略
provider:
loadbalance: random
#指定consumer的负载均衡策略
consumer:
loadbalance: random
下面以Provider注解为例子
1. 为Provider实现类指定策略
方法中加个控制台输出,以便于后续观察负载均衡策略的效果
@DubboService(weight = 1, loadbalance = "roundrobin")
public class DemoServiceImpl implements DemoService {
@Override
public String demo(String demo) {
System.out.println(demo);
return demo + ",hello";
}
}
2. 模拟集群环境
复制springboot启动类:
springboot配置文件中,指定协议端口,来启动多次
dubbo:
application:
name: dubbo-provider
registry:
address: zookeeper://192.168.42.4:2181
protocol:
name: dubbo
port: 20881
修改port,我这边是从20881改到20884,每次修改完启动下对应的springboot启动类,4个启动完的效果:
3. Consumer调用
轮询的效果是依次访问节点,启动Consumer后,进行浏览器访问:
网友评论