Dubbo简单体验
Dubbo是一款高性能的RPC框架,他主要实现了在分布式系统中,服务之间的相互调用,也支持一些负载均衡策略和限流降级策略。由于Dubbo在通信协议层使用自有的二进制流协议传输,因此效率比基于Http协议的RPC框架效率要高,也因此Dubbo成为了现在分布式系统领域中炙手可热的一个框架
在使用Dubbo之前,需要先介绍一下分布式系统中的几个概念
以下是Dubbo官网中的一张图片,可以看到,在分布式系统中,一个服务要去远程调用另一个服务,则调用方为“消费者”,被调用方为“提供者”
在分布式系统中,还需要一个注册中心,用于记录消费者和生产者的地址和服务,他相当于一个中介,提供者在启动时将自己注册到注册中心中,消费者需要调用远程服务的时候,也去注册中心查找可供调用的提供者
另外还有一个监控中心,用于监控分布式系统中各个服务的状态,以及调用次数
搭建注册中心
Dubbo默认使用Zookeeper作为注册中心,我们下载一个Zookeeper,这里使用的版本是3.6.2版本,在启动Zookeeper之前,需要配置一下
打开Zookeeper下的conf目录,有一个zoo_sample.cfg文件,需要将它更名为zoo.cfg才能生效,这个是Zookeeper的配置文件
打开配置文件,配置Zookeeper的数据保存目录,注意这个目录需要是存在的,否则启动会报错
然后设置Zookeeper的启动端口号,默认为2181
Zookeeper有一个内置管理控制台,默认占有用8080端口,如有需要使用admin.serverPort配置修改
修改完配置,切换到bin目录,使用zkServer.cmd命令启动Zookeeper
D:\Develop\apache-zookeeper-3.6.2-bin\bin>zkServer.cmd
正常启动,可以看到Zookeeper在2181端口上运行
构建服务提供者
搭建完注册中心后,我们来创建提供者服务
在创建服务之前,我们先来看一下Dubbo官方文档在服务化最佳实践章节中给出建议
我们遵循微服务开发中的规范,将服务提供者和服务消费者都需要的一些服务提供者的接口,DTO类和接口会产生的异常,都打包成一个单独的api项目,然后由提供者和消费者都依赖这个api项目
创建远程调用使用的DTO类,注意DTO类为提供者和消费者远程调用之间所用的参数的类,这个类需要序列化。
我们模拟一个订单模块和用户模块,订单模块需要调用用户模块的接口,获取用户地址列表,在这个场景中,订单模块为消费者,用户模块为提供者
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserAddress implements Serializable {
private Integer id;
private String userAddress;
private String userId;
private String consignee;
private String phone;
private String isDefault;
}
使用Dubbo搭配Zookeeper注册中心,需要导入dubbo的启动器依赖和Zookeeper和Dubbo的整合依赖,同时导入服务提供者的api依赖
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.12</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>2.7.12</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.blackball</groupId>
<artifactId>user-service-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
@Service
@DubboService
public class UserServiceImpl implements UserService {
@Override
public List<UserAddress> getUserAddressList() {
UserAddress userAddress1 = new UserAddress(1, "HZ", "00000", "小王", "15652211111", "1");
UserAddress userAddress2 = new UserAddress(2, "BJ", "00001", "小张", "17911111111", "1");
return Arrays.asList(userAddress1, userAddress2);
}
}
server:
port: 9000
dubbo:
application:
name: user-service-provider
registry:
protocol: zookeeper
address: 127.0.0.1:2181
protocol:
name: dubbo
port: 20080
最后在Spring Boot启动引导类上或者配置类上添加@EnableDubbo
注解,还可以在这个注解中使用scanBasePackages属性指定扫描暴露接口所在的包
@SpringBootApplication
@EnableDubbo
public class UserServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceProviderApplication.class, args);
}
}
构建服务消费者
导入依赖
@Service
public class OrderServiceImpl implements OrderService {
@DubboReference
UserService userService;
@Override
public UserAddress initOrder(String userId) {
List<UserAddress> userAddressList = userService.getUserAddressList();
for (UserAddress userAddress : userAddressList) {
if (userAddress.getUserId().equals(userId)) {
return userAddress;
}
}
return null;
}
}
@RestController
public class OrderController {
@Autowired
OrderService orderService;
@GetMapping("/initOrder/{uid}")
public UserAddress initOrder(@PathVariable("uid") String userId) {
return orderService.initOrder(userId);
}
}
server:
port: 9001
dubbo:
application:
name: order-service-consumer
registry:
protocol: zookeeper
address: 127.0.0.1:2181
最后别忘记添加@EnableDubbo
注解
先启动服务提供者服务,再启动服务消费者服务,然后发送请求到消费者的接口进行测试