Dubbo 最早是 Alibaba 开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo 采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。
官网地址:http://dubbo.apache.org/zh-cn/
简单来说,dubbo是一种提供PRC(远程服务调用)服务的框架,一些老鸟可能有了解过jdk提供的rmi,这也是一种提供rpc服务的模块,但是使用rmi太麻烦了并且功能远远不如dubbo好,所以我们一般使用dubbo作为我们的rpc框架。
RPC是远程服务调用的缩写,其功能是能够在主机A上调用主机B提供的方法,实现跨主机的调用。在实际应用中往往将一个大型项目中分成多个模块,而总有一些模块是公共模块(其他模块都需要调用它),将这些公共模块提取出来放在机房中并为其部署集群,然后其他模块分布在另外的服务器上,需要用到公共模块的方法的时候直接调用就行。
其实这是应用开发到一定的阶段的强烈需求驱动的。
如果我们开发简单的单一应用,逻辑简单、用户不多、流量不大,那我们用不着。
当我们的系统访问量增大、业务增多时,我们会发现一台单机运行此系统已经无法承受。此时,我们可以将业务拆分成几个互不关联的应用,分别部署在各自机器上,以划清逻辑并减小压力。此时,我们也可以不需要RPC,因为应用之间是互不关联的。
当我们的业务越来越多、应用也越来越多时,自然的,我们会发现有些功能已经不能简单划分开来或者划分不出来。此时,可以将公共业务逻辑抽离出来,将之组成独立的服务Service应用 。而原有的、新增的应用都可以与那些独立的Service应用 交互,以此来完成完整的业务功能。
所以此时,我们急需一种高效的应用程序之间的通讯手段来完成这种需求,所以你看,RPC大显身手的时候来了!
其实描述的场景也是服务化 、微服务和分布式系统架构的基础场景。即RPC框架就是实现以上结构的有力方式。
provider是服务提供方,dubbo要求服务方必须基于spring容器,服务方将consumer调用的接口实现,通过dubbo提供的service注解(注意是dubbo的不是spring的)将接口实现类暴露给注册中心。
注册中心,provider将服务暴露给注册中心(包括服务的ip地址、端口、接口实现类等等),consumer再通过注册中心得到暴露服务的信息,从而调用被暴露的服务
只需要配置registry的信息,就可以从注册中心那里获得暴露的服务
监控中心,监控 Provider 的压力情况等。
每隔 2 分钟 Consumer 和 Provider 会把调用次数发送给 Monitor,由 Monitor 进行统计。
**我们可以从图中了解到,除了consumer调用远程方法是同步的以外,其它均是异步操作,也就是说consumer调用远程服务的时候会阻塞后面的代码,而像provider向registry暴露服务,consumer从registry获取服务信息这类操作都是异步的,高效的。
**
优点:
采用 NIO 复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率,
性能较好(推荐使用)
缺点:
大文件上传时,可能出现问题(不使用 Dubbo 文件上传)
优点:
JDK 自带的能力。
缺点:
偶尔连接失败.
优点:
可与原生 Hessian 互操作,基于 HTTP 协议
缺点:
需 hessian.jar 支持,http 短链接开销大
api模块主要是提供接口和实体类,在此demo中我为了方便在api模块中添加了mybatis-plus依赖,自动生成代码(在实际持久层框架不会在该模块中)
pom
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
com.baomidou
mybatis-plus-boot-starter
3.4.2
mysql
mysql-connector-java
runtime
org.projectlombok
lombok
实体类
@Data
@EqualsAndHashCode(callSuper = false)
public class Consumer implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField(condition = SqlCondition.LIKE)
private String username;
private String password;
private Integer sex;
private String phoneNum;
private String email;
private LocalDateTime birth;
private String introduction;
private String location;
private String avator;
@TableField(fill= FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
}
接口
public interface IConsumerService extends IService {
List findAllUser();
List findUserOnCondition(Consumer consumer);
int deleteUser(Consumer consumer);
int updateUser(Consumer consumer);
}
pom
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
com.codexie
commons_api
0.0.1-SNAPSHOT
org.apache.dubbo
dubbo-spring-boot-starter
2.7.6
org.apache.dubbo
dubbo-registry-zookeeper
2.7.6
配置文件
dubbo:
应用名称
application:
name: springbootProvider
registry:
protocol: zookeeper
address: 101.43.***.***:2181,101.43.***.***:2182,101.43.***.***:2183
timeout: 10000
protocol:
name: dubbo
port: 20883
scan:
base-packages: com.codexie.provider.service.impl
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
# 填写你数据库的url、登录名、密码和数据库名
url: jdbc:mysql://127.0.0.1:3306/musical-site?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
servlet:
multipart:
max-file-size: 10MB
max-request-size: 20MB
mapper接口和service实现类
mapper接口
public interface ConsumerMapper extends BaseMapper {
}
service实现类
@Service #此注解是dubbo提供的不是spring提供的,不要用错
public class ConsumerServiceImpl extends ServiceImpl implements IConsumerService {
@Autowired
private ConsumerMapper consumerMapper;
@Override
public List findAllUser() {
List list = consumerMapper.selectList(new QueryWrapper<>());
return list;
}
@Override
public List findUserOnCondition(Consumer consumer) {
QueryWrapper wrapper = new QueryWrapper<>(consumer);
List list = consumerMapper.selectList(wrapper);
return list;
}
@Override
public int deleteUser(Consumer consumer) {
return consumerMapper.deleteById(consumer.getId());
}
@Override
public int updateUser(Consumer consumer) {
return consumerMapper.updateById(consumer);
}
}
pom
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
com.codexie
commons_api
0.0.1-SNAPSHOT
org.apache.dubbo
dubbo-spring-boot-starter
2.7.6
org.apache.dubbo
dubbo-registry-zookeeper
2.7.6
配置文件
dubbo:
application:
name: springbootConsumer
registry:
protocol: zookeeper
address:101.43.***.***:2181,101.43.***.***:2182,101.43.***.***:2183
timeout: 10000
protocol:
name: dubbo
consumer:
loadbalance: roundrobin
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
# 填写你数据库的url、登录名、密码和数据库名
url: jdbc:mysql://127.0.0.1:3306/musical-site?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
servlet:
multipart:
max-file-size: 10MB
max-request-size: 20MB
业务接口以及实现类
public interface UserService {
List findAllUserService();
List findUserByCon(Consumer consumer);
boolean addUser(Consumer consumer);
boolean addUserList(List list);
int delUser(Consumer consumer);
int updateUser(Consumer consumer);
}
实现类
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Reference
IConsumerService consumerServiceImpl;
@Override
public List findAllUserService() {
return consumerServiceImpl.findAllUser();
}
@Override
public List findUserByCon(Consumer consumer) {
return consumerServiceImpl.findUserOnCondition(consumer);
}
@Override
public boolean addUser(Consumer consumer) {
return consumerServiceImpl.save(consumer);
}
@Override
public boolean addUserList(List list) {
return consumerServiceImpl.saveBatch(list);
}
@Override
public int delUser(Consumer consumer) {
return consumerServiceImpl.deleteUser(consumer);
}
@Override
public int updateUser(Consumer consumer) {
return 0;
}
}
controller
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userServiceImpl;
@RequestMapping("all")
public List findAll(){
return userServiceImpl.findAllUserService();
}
@RequestMapping("add")
public Map addUser(Consumer consumer){
HashMap