Dubbo 简介
Apach Dubbo 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程调用、智能容错和负载均衡、服务自动注册和发现。
Dubbo 设计架构
服务发现的一个核心组件是注册中心,Provider 注册地址到注册中心,Consumer 从注册中心读取和订阅 Provider 地址列表。
Dubbo注册中心 Zookeeper
Dubbo目前支持的注册中心有nacos、zookeeper、multicast、redis、simple,当然官方还是推荐使用zookeeper作为注册中心,所以本文使用zookeeper进行演示。相关的安装教程可以参考 服务注册与发现-Zookeeper(二)
Dubbo 监控中心
监控中心可以帮助用户通过可视化界面管理和维护众多的服务,可以通过可视化界面很直观的查看各个服务的情况,下载地址:https://github.com/apache/dubbo-admin,目前支持docker快速部署,或者你也可以通过运行源码或手动打包部署,本文演示手动打包部署到Linux系统中。注意:监控中心目前不兼容3.0+版本,本文仅做演示,可能后期会出兼容的版本
1. 从github 上下载源码
git clone https://github.com/apache/dubbo-admin.git
2. 在 \dubbo-admin\dubbo-admin-server\src\main\resources 目录下修改配置文件指定注册中心地址
# 配置zookeeper地址
admin.registry.address=zookeeper://192.168.0.132:2181,192.168.0.133:2181,192.168.0.134:2181
admin.config-center=zookeeper://192.168.0.132:2181,192.168.0.133:2181,192.168.0.134:2181
admin.metadata-report.address=zookeeper://192.168.0.132:2181,192.168.0.133:2181,192.168.0.134:2181
3. 在dubbo-admin 根目录进行打包
mvn clean package -Dmaven.test.skip=true
4. 运行,监控中心可以通过源码启动,也可以通过打包后的jar启动
方式1:源码启动
监控中心是前后端分离开发的,所以源码启动时需要前后端分开启动
# 启动前端,dubbo-admin-ui 为前端源码
npm install # 安装依赖
npm run dev
# 启动后端,dubbo-admin-server 为后端源码
# 通过编译器或者mvn命令进行启动
mvn spring-boot:run
启动后访问8082端口:http://localhost:8082/,默认用户名和密码都为 root
方式2:打包部署
将步骤三打包后的jar包上传到服务器进行启动,打包后的文件已经默认集成了UI
java -jar dubbo-admin-server-0.4.0.jar
Dubbo Monitor Simple主要用户监控服务调用,例如进行统计等操作查询。下载地址:https://github.com/apache/dubbo/tree/2.5.x/dubbo-simple,注意是2.5.x分支,其他分支已经没有这个项目了,不知道新版本能不能支持它。
1. 将整个dubbo克隆到本地
# 克隆项目
git clone https://github.com/apache/dubbo.git
# 切换到2.5.x分支
git checkout 2.5.x
2. 在 \dubbo\dubbo-simple\dubbo-monitor-simple 目录下将项目进行打包,打包之前,也可以先进行修改配置:\dubbo\dubbo-simple\dubbo-monitor-simple\src\main\assembly\conf\dubbo.properties
# 打包
mvn clean package -Dmaven.test.skip=true
3. 打包完成,在target目录,注意,打包后的文件是dubbo-monitor-simple-2.5.10-assembly.tar.gz 而不是jar,直接运行jar是跑不起来的,接下来就将压缩包进行解压,如果你在上一步没有修改配置,需要在此修改配置,在conf目录下修改dubbo.properties
# 注册中心地址
dubbo.registry.address=zookeeper://192.168.0.132:2181?backup=192.168.0.133:2181,192.168.0.134:2181
# 其他服务与监控中心的通信端口
dubbo.protocol.port=7070
# 监控中心web访问端口
dubbo.jetty.port=8081
4. 启动,在bin目录下已经写好的了启动脚本
5. 服务配置,需要在服务中配置 dubbo:monitor 节点,具体的参考下一节
<dubbo:monitor protocol="registry"/>
6. 访问web页面,启动后在浏览器中进行访问:http://localhost:8081/
Dubbo 入门案例
1. 导入jar包
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubboartifactId>
<version>3.0.7version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-dependencies-zookeeperartifactId>
<version>3.0.7version>
<type>pomtype>
dependency>
2. 配置服务提供者,在资源目录下创建 provider.xml 文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="dubbo-provider-demo"/>
<dubbo:registry protocol="zookeeper" address="192.168.0.132:2181,192.168.0.133:2181,192.168.0.134:2181"/>
<dubbo:protocol name="dubbo" port="20881"/>
<dubbo:service interface="com.hxz.dubbo.service.IProviderDemoService" ref="prodiverDemoService"/>
<bean id="prodiverDemoService" class="com.hxz.dubbo.service.ProdiverDemoService"/>
<dubbo:monitor protocol="registry"/>
beans>
3. 启动,由于使用的是普通maven项目,需要使用上下文进行启动
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml");
context.start();
System.in.read();
}
4. 测试服务提供者,在监控中心的控制页面,可以看到服务提供者已经注册到dubbo里面了
1. 导入jar包
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubboartifactId>
<version>3.0.7version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-dependencies-zookeeperartifactId>
<version>3.0.7version>
<type>pomtype>
dependency>
2. 配置服务消费者,在资源目录下创建 consumer.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.hxz.dubbo.service"/>
<dubbo:application name="dubbo-consumer-demo"/>
<dubbo:registry address="zookeeper://192.168.0.132:2181,192.168.0.133:2181,192.168.0.134:2181"/>
<dubbo:consumer timeout="3000"/>
<dubbo:reference id="providerService" interface="com.hxz.dubbo.service.IProviderDemoService"/>
<dubbo:monitor protocol="registry"/>
beans>
3. 测试,消费者去远程调用服务提供者,相关的接口代码请查看Gitee源码
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
context.start();
ConsumerDemoService service = context.getBean(ConsumerDemoService.class);
List<DemoEntity> list = service.list();
list.forEach(System.out::println);
System.in.read();
}
SpringBoot 整合 Dubbo
1. 导入jar,我是用的是apache的整合包而不是alibaba的整合包,注意两者区别还是挺大的,alibaba的整合包网上的教程还是挺多,但是apache的整合包教程就很少
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>3.0.7version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-dependencies-zookeeperartifactId>
<version>3.0.7version>
<type>pomtype>
<exclusions>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
exclusion>
exclusions>
dependency>
2. 配置dubbo
server:
port: 8001
spring:
application:
name: dubbo-provider-boot-demo
dubbo:
# 应用相关
application:
name: ${spring.application.name} # dubbo 应用名称
# 注册中心相关
registry:
protocol: zookeeper # 注册协议 zookeeper nacos multicast redis
address: 192.168.0.132:2181,192.168.0.133:2181,192.168.0.134:2181 # 注册地址
register: true
# 通信规则
protocol:
name: dubbo # 通信协议
port: 20881 # 通信端口
# 监控中心
monitor:
protocol: register # 协议
3. 测试demo接口代码
@Service
@DubboService(group = "${spring.application.name}",version = "1.0.0") // 暴露服务, 注意目前3.0+版本需要指定组和版本,否则在web控制中心会莫名其妙的不显示了
public class ProdiverDemoService implements IProviderDemoService {
@Override
public List<DemoEntity> list() {
return Arrays.asList(new DemoEntity(UUID.randomUUID().toString().replace("-", ""), "张三", new Random().nextInt(100)),
new DemoEntity(UUID.randomUUID().toString().replace("-", ""), "李四", new Random().nextInt(100)),
new DemoEntity(UUID.randomUUID().toString().replace("-", ""), "王五", new Random().nextInt(100)));
}
}
4. 开启dubbo功能并启动测试,使用 @EnableDubbo 注解开启,启动后在web控制中心可以看到注册的服务
@SpringBootApplication
@EnableDubbo // 开启dubbo功能
public class DubboProviderBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(DubboProviderBootDemoApplication.class, args);
}
}
1. 导入jar包
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>3.0.7version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-dependencies-zookeeperartifactId>
<version>3.0.7version>
<type>pomtype>
<exclusions>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
2. 配置dubbo
server:
port: 8002
spring:
application:
name: dubbo-consumer-boot-demo
dubbo:
# 应用相关
application:
name: ${spring.application.name} # dubbo 应用名称
# 注册中心相关
registry:
protocol: zookeeper # 注册协议 zookeeper nacos multicast redis
address: 192.168.0.132:2181,192.168.0.133:2181,192.168.0.134:2181 # 注册地址
register: true
# 监控中心
monitor:
protocol: register # 协议
3. 通过 @DubboReference 调用远程,注意:调用远程接口的组和版本如果配置了就要保持一致
@Service
public class ConsumerDemoService implements IConsumerDemoService {
@DubboReference(group = "dubbo-provider-boot-demo",version = "1.0.0") // 远程调用服务
private IProviderDemoService providerService;
@Override
public List<DemoEntity> list() {
return providerService.list();
}
}
4. 开启dubbo功能进行测试
@SpringBootApplication
@EnableDubbo // 开启dubbo功能
public class DubboConsumerBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(DubboConsumerBootDemoApplication.class, args);
}
}
通过postman调用controller接口,成功获取返回值
Dubbo 高可用
当注册中心宕机后,经过测试发现,还可以消费dubbo暴露的服务;服务提供者和消费者可以通过本地缓存通信,即当消费者调用了一次提供者,会在消费者本地缓存提供者的详细信息,因此注册中心宕机后可以跳过注册中直接调用提供者。除此之外,其他的如监控中心宕机也不影响
Dubbo 直连可以绕过注册中心,即不使用注册中心直接调用dubbo的其他服务,通过 @DubboReference 的 url 属性直接连接服务提供者的通信地址
注意:使用dubbo直连时,需要将注册中心相关的配置注释掉,并且不建议在生产环境使用
@Service
public class ConsumerDemoService implements IConsumerDemoService {
@DubboReference(group = "dubbo-provider-boot-demo", version = "1.0.0",url = "127.0.0.1:20881") // 远程调用服务, 直接连接服务提供者
private IProviderDemoService providerService;
@Override
public List<DemoEntity> list() {
return providerService.list();
}
}
集群模式下,Dubbo提供了多种负载均衡策略,默认为Random 随机调用。
算法 | 特性 | 备注 |
---|---|---|
RandomLoadBalance | 加权随机 | 默认算法,默认权重相同 |
RoundRobinLoadBalance | 加权轮询 | 借鉴于 Nginx 的平滑加权轮询算法,默认权重相同 |
LeastActiveLoadBalance | 最少活跃优先 + 加权随机 | 背后是能者多劳的思想 |
ShortestResponseLoadBalance | 最短响应优先 + 加权随机 | 更加关注响应速度 |
ConsistentHashLoadBalance | 一致性 Hash | 确定的入参,确定的提供者,适用于有状态请求 |
// 注解方式
@DubboService(group = "${spring.application.name}",version = "1.0.0",loadbalance = "leastactive") // 暴露服务.// 轮询值loadbalance :consistenthash leastactive random roundrobin shortestresponse
public class ProdiverDemoService implements IProviderDemoService {}
// xml 配置方式
<!-- 暴露的接口服务,ref指向服务的实现 轮询值loadbalance :consistenthash leastactive random roundrobin shortestresponse -->
<dubbo:service interface="com.hxz.dubbo.service.IProviderDemoService" ref="prodiverDemoService" loadbalance="leastactive"/>
示例:服务消费者
// 注解方式
// 轮询值loadbalance :consistenthash leastactive random roundrobin shortestresponse
@DubboReference(group = "dubbo-provider-boot-demo", version = "1.0.0",loadbalance = "roundrobin") // 远程调用服务
private IProviderDemoService providerService;
// xml 配置
<!-- 声明需要调用的远程服务接口, 生成远程服务的代理 轮询值loadbalance :consistenthash leastactive random roundrobin shortestresponse -->
<dubbo:reference id="providerService" interface="com.hxz.dubbo.service.IProviderDemoService" loadbalance="consistenthash"/>
关于更多的用法可以参考官方文档:https://dubbo.apache.org/zh/docs/advanced/
源码地址:https://gitee.com/peachtec/hxz-study