Dubbo之原理讲解及demo测试

我与影子孤独终老i 提交于 2020-03-27 10:08:22

3 月,跳不动了?>>>

前言:今天给大家给大家讲解的是Dubbp的调用原理,以及一个demo测试向大家展示Dubbo的运行过程。在前面一文中,给大家讲到了---Dubbo之Zookeeper安装测试和Zookeeper集群的搭建 ,在其中已经给大家讲到了Zookeeper集群的搭建,今天我们也要用到该集群,如果没有安装的,请先行安装,再看下文!!


1.Dubbo原理

1.1 高性能Java RPC框架

Apache Dubbo 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

在这里插入图片描述

1.2 Dubbo特性

  • 面向接口代理的高性能RPC调用
  • 服务自动注册与发现
  • 运行期流量调度
  • 智能负载均衡
  • 高度可扩展能力
  • 可视化的服务治理与运维

以上几点接来源于dubbo的官网:http://dubbo.apache.org/zh-cn/

1.3 Dubbo工作原理

1.3.1 Dubbo高可用测试

  • 测试1:将后台提供者宕机一台,检查是否影响消费者调用。

不影响 注册中心实现心跳检测机制. 即使没有注册中心,又要有提供者就可以正常访问

  • 测试2: 将zookeeper宕机一台,检查是否影响用户使用。

不影响 因为zk搭建了集群.可以实现高可用

  • 测试3: 将zookeeper集群全部宕机,检查是否影响用户使用。

不影响. 因为消费者将zk注册中心的数据,已经保存到本地(消费者的内存中),所以不收影响

1.3.2 Dubbo通讯问题

核心:微服务通信一般都是靠RPC(统称)
dubbo中的RPC基于dubbo的协议规范

在这里插入图片描述

1.4 Dubbo调用原理

1.4.1 原理说明

  • 需求:是否可以实现服务的自动发现和注册

在这里插入图片描述

图很丑,没有大神级的画得好看,将就着看吧。
图示解析

  1. 当服务提供者启动时,会将服务数据保存到zk中。
  2. 当zk接收用户服务信息之后,会将数据保存到服务列表中。
  3. 当消费者启动时,先连接zk获取zk的服务列表。
  4. 之后缓存到本地,方便下次访问。
  5. 消费者接收用户的请求时,根据负载均衡策略,实现请求的发送,并且获取服务端的数据(RPC)。
  6. Zk实时的心跳检测,如果后台服务器宕机,则需要更新自己的服务列表,同时广播给全部的客户端。

1.5 Dubbo入门案例

1.5.0 导入数据库

CREATE DATABASE /*!32312 IF NOT EXISTS*/`jtdb` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `jtdb`;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(40) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `sex` char(40) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `cc` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8;

/*Data for the table `user` */

insert  into `user`(`id`,`name`,`age`,`sex`) values (1,'黑熊精',4000,'男'),(2,'鲤鱼精',5000,'男'),(3,'金角大王',3000,'男'),(4,'银角大王',4000,'男'),(5,'唐僧',30,'男'),(6,'悟空',501,'男'),(7,'白龙驴',2000,'男'),(8,'八戒',502,'男'),(9,'沙悟净',503,'男'),(11,'小乔',17,'女'),(12,'貂蝉',18,'女'),(16,'黄月英',18,'女'),(17,'孙尚香',18,'女'),(18,'甄姬c',20,'女'),(21,'孙尚香D',18,'女'),(22,'刘备',40,'男'),(23,'陆逊',33,'男'),(24,'陆逊',33,'男'),(25,'关羽',40,'男'),(27,'阿科',20,'女'),(31,'王昭君',19,'女'),(38,'貂蝉',18,'女'),(39,'西施',18,'女'),(40,'严真煌',16,'女'),(41,'白骨精',18,'女'),(43,'小乔',19,'男'),(44,'大乔',19,'女'),(46,'不知火舞',18,'女'),(49,'小兰兰',18,'男'),(50,'柳鹏林',18,'男'),(51,'妲己',18,'男'),(52,'如花',17,'男');

1.5.1 项目搭建

  1. 创建 dubbo-jt 为父类项目(Maven Project)
  2. 在dubbo-jt下,创建dubbo-jt-demo-consumer/interface/provider/provider2 四个子级项目(Maven Module)
  3. 在此之前你可以创建dubbo的工作空间

在这里插入图片描述

在这里插入图片描述

  1. 如果前三步做成,你将会看到

在这里插入图片描述

1.5.2 导入pom文件 -- 最后一个dependency就是dubbo的配置

dubbo-jt的pom文件
<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.5.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<java.version>1.8</java.version>
		<!--添加maven插件 -->
		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
	</properties>

	<dependencies>
		<!--springBoot动态的引入springMVC全部的配置 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!--引入测试类 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!--添加属性注入依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>

		<!--支持热部署 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
			<version>1.2.8.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>

		<!--引入插件lombok 自动的set/get/构造方法插件 -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

		<!--引入数据库驱动 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

		<!--引入druid数据源 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.12</version>
		</dependency>

		<!--spring整合mybatis-plus -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.0.6</version>
		</dependency>

		<!--spring整合redis -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-redis</artifactId>
		</dependency>

		<!--springBoot整合JSP添加依赖 -->
		<!--servlet依赖 注意与eureka整合时的问题 -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
		</dependency>

		<!--jstl依赖 -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<!--使jsp页面生效 -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

		<!--添加httpClient jar包 -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
		</dependency>
		
		<!--引入dubbo配置 -->
		<dependency>
			<groupId>com.alibaba.boot</groupId>
			<artifactId>dubbo-spring-boot-starter</artifactId>
			<version>0.2.0</version>
		</dependency>	
	</dependencies>
	<modules>
		<module>dobbo-jt-demo-interface</module>
		<module>dubbo-jt-demo-provider</module>
		<module>dubbo-jt-demo-consumer</module>
		<module>dubbo-jt-demo-provider2</module>
	</modules>
dubbo-jt-demo-consumer --编辑pom文件(消费者)
  <parent>
    <groupId>com.jt.dubbo</groupId>
    <artifactId>dubbo-jt</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>dubbo-jt-demo-consumer</artifactId>
  <dependencies>
  	<dependency>
  		<groupId>com.jt.dubbo</groupId>
  		<artifactId>dubbo-jt-demo-interface</artifactId>
  		<version>0.0.1-SNAPSHOT</version>
  	</dependency>
  </dependencies>
dubbo-jt-demo-provider/provider2 --编辑pom文件(提供者)
  <parent>
    <groupId>com.jt.dubbo</groupId>
    <artifactId>dubbo-jt</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>dubbo-jt-demo-provider</artifactId>
  <dependencies>
  	<dependency>
  		<groupId>com.jt.dubbo</groupId>
  		<artifactId>dubbo-jt-demo-interface</artifactId>
  		<version>0.0.1-SNAPSHOT</version>
  	</dependency>
  </dependencies>

1.5.3 编写intrface (第三方接口)

在com.jt.dubbo.pojo中,创建User实体类
@Data
@Accessors(chain=true)
@TableName
public class User implements Serializable{
	//dubbo协议传输的对象必须序列化
	private static final long serialVersionUID = 1L;
	@TableId(type=IdType.AUTO)
	private Integer id;
	private String name;
	private Integer age;
	private String sex;
}
在com.jt.dubbo.service中创建UserService
public interface UserService {
	
	//查询全部用户信息
	List<User> findAll();
	//导入数据库
	@Transactional
	void saveUser(User user);
}

1.5.4 编写consumer(消费者)

在com.jt下编写启动类SpringBoot_Run
//springBoot启动时排除数据源启动项
@SpringBootApplication(exclude=DataSourceAutoConfiguration.class)
public class SpringBoot_Run {
	
	public static void main(String[] args) {
		
		SpringApplication.run(SpringBoot_Run.class, args);
	}
}
在resources下编辑application.yml 文件
server:
  port: 9001
dubbo:
  scan:
    basePackages: com.jt
  application:
    name: consumer-user    #消费者名称
  registry:
    address: zookeeper://192.168.126.166:2181?backup=192.168.126.166:2182,192.168.126.166:2183
在com.jt.dubbo.controller下创建UserController类
@RestController
public class UserController {
	
	@Reference(timeout=3000,check=true)
	//@Autowired   //从spring容器中进行注入
	private UserService userService;    //注入第三方管理的service
	
	@RequestMapping("/findAll")
	public List<User> findAll(){
		
		return userService.findAll();
	}
	
	@RequestMapping("/saveUser/{name}/{age}/{sex}")
	public String saveUser(User user) {
		
		userService.saveUser(user);
		return "用户入库成功!!!";
	}
}

1.5.5 编写provider(提供者1)

启动类SpringBoot_Run
@SpringBootApplication
@MapperScan("com.jt.dubbo.mapper")
public class SpringBoot_Run {
	
	public static void main(String[] args) {
		
		SpringApplication.run(SpringBoot_Run.class, args);
	}
}
application.yml文件编写
server:
  port: 9000  #定义端口

spring:
  datasource:
    #引入druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: root
    
dubbo:
  scan:
    basePackages: com.jt      #指定dubbo包路径
  application:
    name: provider-user       #指定服务名称(必须指定)
  registry:
    address: zookeeper://192.168.126.166:2181?backup=192.168.126.166:2182,192.168.126.166:2183
  protocol:     #指定协议
    name: dubbo      #使用dubbo协议(tcp-ip) web-controller直接调用sso-service
    port: 20880      #服务链接时的端口

      
mybatis-plus:
  type-aliases-package: com.jt.dubbo.pojo       #配置别名包路径
  mapper-locations: classpath:/mybatis/mappers/*.xml  #添加mapper映射文件
  configuration:
    map-underscore-to-camel-case: true                #开启驼峰映射规则
在resources/mybatis/mappers下创建UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jt.dubbo.mapper.UserMapper">

</mapper>
在com.jt.dubbo.mapper下编写UserMapper接口(使用的是MybatisPlus)
public interface UserMapper extends BaseMapper<User>{
	
}
在com.jt.dubbo.service下创建UserServiceImpl类
@Service(timeout=3000)	//3秒超时	
public class UserServiceImpl implements UserService {
	
	@Autowired
	private UserMapper userMapper;
	@Override
	public List<User> findAll() {
		
		System.out.println("我是第一个服务的提供者");
		return userMapper.selectList(null);
	}
	
	@Override
	public void saveUser(User user) {
		
		userMapper.insert(user);
	}

}

1.5.6 provider2 (提供者2)

与provider相比,

  • 更改application.yml中的server:port:9003
  • 以及更改dubbo的端口号为20882因为每个服务都应该有自己独立的端口
  • UserServiceImpl中的---System.out.println("我是第二个服务提供者");

1.6 测试效果

1.6.0 开启zk集群

在这里插入图片描述

1.6.1 开启consumer/provider/provider2

1.6.2 搜索 localhost:9001/findAll 数据显示,表示查询成功

在这里插入图片描述

1.6.3 在后台显示provider/provider2均可被调用

在这里插入图片描述

在这里插入图片描述

1.6.4 将zk集群全部宕机 -- 后台会一直报如错误

在这里插入图片描述

1.6.5 即使所有集群被宕机,也不会影响消费者的使用

因为 消费者启动时已经将服务信息缓存到本地,故不会影响
亦或者有一个提供者宕机了,用户依然可以正常访问,且本地服务列表还会动态更新,只不过该程序将处于高位运行状态之下。

在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!