1:dubbo是什么?
dubbo的是一个基于Java开发的高性能rpc框架,提供了3大功能,如下:
1:基于接口的远程方法调用(依赖于netty)
2:智能容错和负载均衡
3:服务的注册和发现(依赖于zk,nacos等三方组件)
2:dubbo有什么?
在dubbo中一个有5大角色,分别是注册中心Registry,服务提供者Provider,服务消费者Consumer,监控中心Monitor,服务运行容器Container,三者的功能如下:
Registry:服务提供者注册自己的服务,服务消费者发现服务
Provider:提供服务,并将自己的信息注册到Registry
Consumer:服务的调用方,从Registry中获取Provider的信息,直接调用服务
Monitor:统计服务的调用次数,调用时间等信息
Container:启动Provider
需要我们进行编码的只有Provider和Consumer这2个角色,本文我们来重点分析二者。各种的关系可以用下图来表示:
接下来我们通过xml配置方式和注解配置方式来看下dubbo的基本搭建和使用。
3:XML方式配置
本实例,我们会定义3个项目,最终效果如下:
rpc-service-api:用于提供服务的公共接口定义
rpc-service-consumer:服务消费者项目
rpc-service-provider:服务提供者项目
3.1:rpc-service-api
3.1.1:UserDTO
// 因为dubbo的rpc调用涉及到对象的序列化和反序列化,所以需要实现java.io.Serializable接口
public class UserDTO implements Serializable {
/**
* 用户编号
*/
private Integer id;
/**
* 昵称
*/
private String name;
/**
* 性别
*/
private Integer gender;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
@Override
public String toString() {
return "UserDTO{" +
"id=" + id +
", name='" + name + '\'' +
", gender=" + gender +
'}';
}
}
3.1.2:接口定义
public interface UserRpcService {
/**
* 根据指定用户编号,获得用户信息
*
* @param id 用户编号
* @return 用户信息
*/
UserDTO get(Integer id);
}
3.1.3:pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dubbo-helloworld-with-xml</artifactId>
<groupId>dongshi.daddy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>rpc-service-api</artifactId>
</project>
3.2:rpc-service-provider
3.2.1:pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dubbo-helloworld-with-xml</artifactId>
<groupId>dongshi.daddy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>rpc-service-provider</artifactId>
<dependencies>
<!-- 引入定义的 Dubbo API 接口 -->
<dependency>
<groupId>dongshi.daddy</groupId>
<artifactId>rpc-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入 Spring Boot 依赖 -->
<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.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.4.1</version>
</dependency>
<!-- 使用 Zookeeper 作为注册中心 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
</project>
3.2.2:配置文件
resources/application.yml
:
# dubbo 配置项,对应 DubboConfigurationProperties 配置类
dubbo:
# Dubbo 应用配置
application:
name: user-service-provider # 应用名
# Dubbo 注册中心配
registry:
address: zookeeper://127.0.0.1:2181 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。
# Dubbo 服务提供者协议配置
protocol:
port: -1 # 协议端口。使用 -1 表示随机端口。
name: dubbo # 使用 `dubbo://` 协议。更多协议,可见 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文档
# Dubbo 服务提供者配置
provider:
timeout: 1000 # 【重要】远程服务调用超时时间,单位:毫秒。默认为 1000 毫秒,胖友可以根据自己业务修改
UserRpcService:
version: 1.0.0
resources/dubbo.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 服务提供者暴露服务配置 -->
<dubbo:service ref="userRpcServiceImpl" interface="dongshi.daddy.api.UserRpcService"
version="${dubbo.provider.UserRpcService.version}" />
</beans>
使用了dubbo的自定义标签dubbo:service
。
3.2.3:服务实现类
@Service
public class UserRpcServiceImpl implements UserRpcService {
@Override
public UserDTO get(Integer id) {
/*return new UserDTO().setId(id)
.setName("没有昵称:" + id)
.setGender(id % 2 + 1); // 1 - 男;2 - 女*/
UserDTO userDTO = new UserDTO();
userDTO.setId(id);
userDTO.setName("没有昵称:" + id);
userDTO.setGender(id % 2 + 1);
return userDTO;
}
}
3.2.4:启动类
@SpringBootApplication
@ImportResource("classpath:dubbo.xml")
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
使用了@ImportResource 来导入bubbo.xml配置文件。
启动后输出如下的日志信息,则说明成功了:
...
2021-11-09 18:20:04.719 INFO 17800 --- [pool-1-thread-1] .b.c.e.AwaitingNonWebApplicationListener : [Dubbo] Current Spring Boot Application is await...
从zk查看注册的信息:
D:\program_files\zookeeper-3.4.12\bin>zkCli.cmd
Connecting to localhost:2181
...
[zk: localhost:2181(CONNECTED) 0] ls /dubbo
[dongshi.daddy.api.UserRpcService]
[zk: localhost:2181(CONNECTED) 1] ls /dubbo/dongshi.daddy.api.UserRpcService
[consumers, routers, providers, configurators]
[zk: localhost:2181(CONNECTED) 2] ls /dubbo/dongshi.daddy.api.UserRpcService/providers
[dubbo%3A%2F%2F192.168.10.119%3A20881%2Fdongshi.daddy.api.UserRpcService%3Fanyhost%3Dtrue%26application%3Duser-service-provider%26bean.name%3Ddongshi.daddy.api.UserRpcService%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Ddongshi.daddy.api.UserRpcService%26methods%3Dget%26pid%3D17800%26release%3D2.7.4.1%26revision%3D1.0.0%26side%3Dprovider%26timeout%3D1000%26timestamp%3D1636453204287%26version%3D1.0.0]
[zk: localhost:2181(CONNECTED) 3]
3.3:rpc-service-consumer
3.3.1:pom
<dependencies>
<!-- 引入定义的 Dubbo API 接口 -->
<dependency>
<groupId>dongshi.daddy</groupId>
<artifactId>rpc-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入 Spring Boot 依赖 -->
<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.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.4.1</version>
</dependency>
<!-- 使用 Zookeeper 作为注册中心 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
3.3.2:配置文件
resource/application.yml
:
# dubbo 配置项,对应 DubboConfigurationProperties 配置类
dubbo:
# Dubbo 应用配置
application:
name: user-service-consumer # 应用名
# Dubbo 注册中心配置
registry:
address: zookeeper://127.0.0.1:2181 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。
# Dubbo 消费者配置
consumer:
timeout: 1000 # 【重要】远程服务调用超时时间,单位:毫秒。默认为 1000 毫秒,胖友可以根据自己业务修改
UserRpcService:
version: 1.0.0
resource/dubbo.yml
:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 服务消费者引用服务配置 -->
<dubbo:reference id="userService" interface="dongshi.daddy.api.UserRpcService"
version="${dubbo.consumer.UserRpcService.version}"/>
</beans>
创建了名称为userService
的spring bean,就可以像使用本地的一个spring bean一样来调用方法了,内部通过netty的长连接就可以调用到服务提供者的服务了。
3.3.3:启动类
@SpringBootApplication
@ImportResource("classpath:dubbo.xml")
public class ConsumerApplication {
public static void main(String[] args) {
// 启动 Spring Boot 应用
ConfigurableApplicationContext context = SpringApplication.run(ConsumerApplication.class, args);
}
@Component
public class UserRpcServiceTest implements CommandLineRunner {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Resource
private UserRpcService userRpcService;
@Override
public void run(String... args) throws Exception {
UserDTO user = userRpcService.get(1);
logger.info("[run][发起一次 Dubbo RPC 请求,获得用户为({})", user);
}
}
}
这里使用CommandLineRunner只是为了方便启动时就看到调用的效果。
启动后查看zk的注册信息:
D:\program_files\zookeeper-3.4.12\bin>zkCli.cmd
Connecting to localhost:2181
...
[zk: localhost:2181(CONNECTED) 3] ls /
[dubbo, zookeeper]
[zk: localhost:2181(CONNECTED) 4] ls /dubbo
[dongshi.daddy.api.UserRpcService]
[zk: localhost:2181(CONNECTED) 5] ls /dubbo/dongshi.daddy.api.UserRpcService
[consumers, routers, providers, configurators]
[zk: localhost:2181(CONNECTED) 7] ls /dubbo/dongshi.daddy.api.UserRpcService/consumers
[consumer%3A%2F%2F192.168.10.119%2Fdongshi.daddy.api.UserRpcService%3Fapplication%3Duser-service-consumer%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.0.2%26interface%3Ddongshi.daddy.api.UserRpcService%26lazy%3Dfalse%26methods%3Dget%26pid%3D18988%26qos.enable%3Dfalse%26release%3D2.7.4.1%26revision%3D1.0.0%26side%3Dconsumer%26sticky%3Dfalse%26timeout%3D1000%26timestamp%3D1636454208368%26version%3D1.0.0]
[zk: localhost:2181(CONNECTED) 8]
如果看到如下的输出信息,则说明调用成功了:
...
2021-11-09 18:36:49.191 INFO 18988 --- [ main] c.ConsumerApplication$UserRpcServiceTest : [run][发起一次 Dubbo RPC 请求,获得用户为(UserDTO{id=1, name='没有昵称:1', gender=2})
2021-11-09 18:36:49.193 INFO 18988 --- [pool-1-thread-1] .b.c.e.AwaitingNonWebApplicationListener : [Dubbo] Current Spring Boot Application is await...
4:注解方式配置
本实例,我们会定义3个项目,最终效果如下:
rpc-service-api-02:用于提供服务的公共接口定义
rpc-service-consumer-02:服务消费者项目
rpc-service-provider-02:服务提供者项目
4.1:rpc-service-api-02
4.1.1 UserDTO
// 因为dubbo的rpc调用涉及到对象的序列化和反序列化,所以需要实现java.io.Serializable接口
public class UserDTO implements Serializable {
/**
* 用户编号
*/
private Integer id;
/**
* 昵称
*/
private String name;
/**
* 性别
*/
private Integer gender;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
@Override
public String toString() {
return "UserDTO{" +
"id=" + id +
", name='" + name + '\'' +
", gender=" + gender +
'}';
}
}
4.1.2 UserRpcService
public interface UserRpcService {
/**
* 根据指定用户编号,获得用户信息
*
* @param id 用户编号
* @return 用户信息
*/
UserDTO get(Integer id);
}
4.2: rpc-service-provider-02
4.2.1: pom
<dependencies>
<!-- 引入定义的 Dubbo API 接口 -->
<dependency>
<groupId>dongshi.daddy</groupId>
<artifactId>rpc-service-api-02</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入 Spring Boot 依赖 -->
<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.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.4.1</version>
</dependency>
<!-- 使用 Zookeeper 作为注册中心 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
4.2.2 application.yml
# dubbo 配置项,对应 DubboConfigurationProperties 配置类
dubbo:
# Dubbo 应用配置
application:
name: user-service-provider02 # 应用名
# Dubbo 注册中心配
registry:
address: zookeeper://127.0.0.1:2181 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。
# Dubbo 服务提供者协议配置
protocol:
port: -1 # 协议端口。使用 -1 表示随机端口。
name: dubbo # 使用 `dubbo://` 协议。更多协议,可见 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文档
# Dubbo 服务提供者配置
provider:
timeout: 1000 # 【重要】远程服务调用超时时间,单位:毫秒。默认为 1000 毫秒,胖友可以根据自己业务修改
UserRpcService:
version: 1.0.0
# 配置扫描 Dubbo 自定义的 @Service 注解,暴露成 Dubbo 服务提供者
scan:
base-packages: dongshi.daddy.service
注意这里增加了dubbo.scan.base-packages
定义了服务提供类的自动扫描路径,需要配合dubbo的自定义注解org.apache.dubbo.config.annotation.Service
使用。所以就不需要bubbo.xml
了。
3.2.3: UserRpcServiceImpl
@Service(version = "${dubbo.provider.UserRpcService.version}")
public class UserRpcServiceImpl implements UserRpcService {
@Override
public UserDTO get(Integer id) {
/*return new UserDTO().setId(id)
.setName("没有昵称:" + id)
.setGender(id % 2 + 1); // 1 - 男;2 - 女*/
UserDTO userDTO = new UserDTO();
userDTO.setId(id);
userDTO.setName("没有昵称:" + id);
userDTO.setGender(id % 2 + 1);
return userDTO;
}
}
注意这里的@Service注解是dubbo自定义的org.apache.dubbo.config.annotation.Service
,而非spring中的org.springframework.stereotype.Service
。
4.2.4: ProviderApplication
@SpringBootApplication
// @ImportResource("classpath:dubbo.xml")
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
这里就不需要@ImportResource注解来引入xml配置文件了,因为使用了基于注解的自动扫描。
启动,如下就是启动成功了:
...
2021-11-10 11:17:20.033 INFO 17332 --- [pool-1-thread-1] .b.c.e.AwaitingNonWebApplicationListener : [Dubbo] Current Spring Boot Application is await...
5.3: rpc-service-consumer-02
5.3.1: pom
<dependencies>
<!-- 引入定义的 Dubbo API 接口 -->
<dependency>
<groupId>dongshi.daddy</groupId>
<artifactId>rpc-service-api-02</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入 Spring Boot 依赖 -->
<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.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.4.1</version>
</dependency>
<!-- 使用 Zookeeper 作为注册中心 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
5.3.2 application.yml
# dubbo 配置项,对应 DubboConfigurationProperties 配置类
dubbo:
# Dubbo 应用配置
application:
name: user-service-consumer02 # 应用名
# Dubbo 注册中心配置
registry:
address: zookeeper://127.0.0.1:2181 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。
# Dubbo 消费者配置
consumer:
timeout: 1000 # 【重要】远程服务调用超时时间,单位:毫秒。默认为 1000 毫秒,胖友可以根据自己业务修改
UserRpcService:
version: 1.0.0
5.3.3 ConsumerApplication
@SpringBootApplication
//@ImportResource("classpath:dubbo.xml")
public class ConsumerApplication {
public static void main(String[] args) {
// 启动 Spring Boot 应用
ConfigurableApplicationContext context = SpringApplication.run(ConsumerApplication.class, args);
}
@Component
public class UserRpcServiceTest implements CommandLineRunner {
private final Logger logger = LoggerFactory.getLogger(getClass());
// @Resource
@Reference(version = "${dubbo.consumer.UserRpcService.version}")
private UserRpcService userRpcService;
@Override
public void run(String... args) throws Exception {
UserDTO user = userRpcService.get(1);
logger.info("[run][发起一次 Dubbo RPC 请求,获得用户为({})", user);
}
}
}
这里就不需要@ImportResource注解来引入dubbo.xml了,并且通过dubbo的自定义注解com.alibaba.dubbo.config.annotation.Reference
来引用用来调用dubbo服务提供者服务的spring bean。
启动,如下就是启动并调用成功了:
2021-11-10 11:47:22.914 INFO 22476 --- [ main] dongshi.daddy.ConsumerApplication : Started ConsumerApplication in 1.537 seconds (JVM running for 2.054)
2021-11-10 11:47:22.967 INFO 22476 --- [ main] d.ConsumerApplication$UserRpcServiceTest : [run][发起一次 Dubbo RPC 请求,获得用户为(UserDTO{id=1, name='没有昵称:1', gender=2})
2021-11-10 11:47:22.969 INFO 22476 --- [pool-1-thread-1] .b.c.e.AwaitingNonWebApplicationListener : [Dubbo] Current Spring Boot Application is await...