【微服务】Dubbo初体验
一、前言
之前微服务这块只用过SpringCloud搭建,但是最近面试会被问到dubbo框架,虽然之前也学了但是都忘了,故写此博客加深印象。
二、原理简介
Dubbo是一个分布式服务框架,以及阿里巴巴内部的SOA服务化治理方案的核心框架。其功能主要包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等。
Dubbo核心部分包含:
- 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
- 集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
- 自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
Dubbo能做什么:
- 透明化的远程调用,就像调用本地方法一样调用远程方法,只需要简单配置,没有任何侵入。
- 软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
- 服务自动注册与发现,不再需要写死服务提供放地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
Dubbo的架构图如下:
节点说明:
1.Provider
暴露服务的生产者,向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销。
2.Container
服务运行容器
3.Consumer
调用远程服务的服务消费者,服务消费者向注册中心获取服务提供者地址列表 , 并根据负载算法直接调用提供者,同时汇报调用时间到监控中心,此时间包含网络开销。
4.Monitor
统计服务的调用次调和调用时间的监控中心,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示。
5.Registry
注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小 。
dubbo不同服务间的区别与联系:
(1) 注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外
(2) 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者
(3) 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表
(4) 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者
三、传统maven项目整合
3.1搭建注册中心zookeeper
- 解压 tar -zxf zookeeper-3.4.13.tar.gz
- 将conf目录下的zoo_sample.cfg重命名为zoo.cfg
- 进入bin目录启动,./zkServer.sh start ../conf/zoo.cfg
3.2参考这里
https://www.jianshu.com/p/302001c1c21f
四、SpringBoot整合Dubbo
4.1创建公共依赖m-common
里面就只包括实体类User和接口UserService
User.java
- // 使用dubbo要求传输的对象必须实现序列化接口
- public class User implements Serializable {
- private Long id;
- private String username;
- private String password;
- public Long getId() {
- return id;
- }
- public void setId(Long id) {
- this.id = id;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public String toString() {
- return "User{" +
- "id=" + id +
- ", username='" + username + '\'' +
- ", password='" + password + '\'' +
- '}';
- }
- }
UserService.java
public interface UserService {
/**
* 查询所有用户
* @return
*/
public List<User> queryAll();
}
4.2创建服务生产者
项目结构如图:
- 在pom.xml文件引入依赖
<dependency>
<groupId>cn.sp</groupId>
<artifactId>m-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
- 在application.properties添加配置
dubbo.application.name=dubbo-producer
# 注册中心地址
dubbo.registry.address=zookeeper://ip:2181
# 指定通信协议
dubbo.protocol.name=dubbo
# 通信端口 这里指的是与消费者间的通信协议与端口
dubbo.protocol.port=12345
- 在启动类添加注解 @EnableDubbo来启用dubbo
- 编写UserService的实现类
- package cn.sp.service.impl;
- import cn.sp.bean.User;
- import cn.sp.service.UserService;
- import com.alibaba.dubbo.config.annotation.Service;
- import org.springframework.stereotype.Component;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by 2YSP on 2019/5/12.
- */
- (interfaceClass = UserService.class)
- public class UserServiceImpl implements UserService {
- public List<User> queryAll() {
- // 模拟查询数据库
- List<User> userList = new ArrayList<>(100);
- for(int i=1;i < 101;i++){
- User user = new User();
- user.setId((long) i);
- user.setUsername("username_"+i);
- user.setPassword("xxxx");
- userList.add(user);
- }
- return userList;
- }
- }
注意: 这里的 @Service注解包名是 com.alibaba.dubbo.config.annotation.Service,而不是Spring的那个。
最后启动即可。
4.3创建消费者
- 创建SpringBoot项目dubbo-consumer
- pom.xml引入依赖
与生产者的相同。 - 添加配置
dubbo.application.name=dubbo-consumer
dubbo.registry.address=zookeeper://ip:2181 - 在启动类添加注解 @EnableDubbo
- 编写测试类
- (SpringRunner.class)
- public class DubboConsumerApplicationTests {
- private UserService userService;
- public void contextLoads() {
- List<User> users = userService.queryAll();
- users.forEach(user -> System.out.println(user));
- }
- }
- 运行contextLoads()方法,控制台输出如下表示整合成功。
User{id=1, username='username_1', password='xxxx'}
User{id=2, username='username_2', password='xxxx'}
User{id=3, username='username_3', password='xxxx'}
User{id=4, username='username_4', password='xxxx'}
User{id=5, username='username_5', password='xxxx'}
User{id=6, username='username_6', password='xxxx'}
User{id=7, username='username_7', password='xxxx'}
User{id=8, username='username_8', password='xxxx'}
User{id=9, username='username_9', password='xxxx'}
。。。。
参考资料:https://github.com/apache/incubator-dubbo-spring-boot-project
代码地址:https://github.com/2YSP/dubbo-springboot-demo