61-Java-分布式开发框架Dubbo-- 笔记
笔记内容来源与黑马程序员教学视频
文章目录
- 61-Java-分布式开发框架Dubbo-- 笔记
- 分布式开发框架Dubbo
- 一、分布式系统中的相关概念
- 二、Dubbo 概述
- 三、Dubbo 快速入门
- 四、Dubbo 高级特性
分布式开发框架Dubbo
笔记中涉及资源:
链接:https://pan.baidu.com/s/1lne-ZWLJR3OcZkg8EoZOhg
提取码:Coke
一、分布式系统中的相关概念
①:大型互联网项目架构目标
-
大型互联网项目架构目标
-
互联网项目特点:
用户多
流量大,并发高
海量数据
易受攻击
功能繁琐
变更快 -
高性能:提供快速的访问体验。
-
-
衡量网站的性能指标:
-
响应时间:指执行一个请求从开始到最后收到响应数据所花费的总体时间。
-
并发数:指系统同时能处理的请求数量。
- 并发连接数:指的是客户端向服务器发起请求,并建立了TCP连接。每秒钟服务器连接的总TCP数量
- 请求数:也称为QPS(Query Per Second) 指每秒多少请求.
并发用户数:单位时间内有多少用户
-
吞吐量:指单位时间内系统能处理的请求数量。
- QPS:Query Per Second 每秒查询数。
- TPS:Transactions Per Second 每秒事务数。
- 一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。
- 一个页面的一次访问,只会形成一个TPS;但一次页面请求,可能产生多次对服务器的请求,就会有多个QPS
-
QPS >= 并发连接数 >= TPS
②:集群和分布式
③:架构演进
二、Dubbo 概述
①:概述
- Dubbo是阿里巴巴公司开源的一个高性能、轻量级的 Java RPC 框架。
- 致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。
- 官网:http://dubbo.apache.org
②:Dubbo架构
三、Dubbo 快速入门
①:Zookeeper安装
Zookeeper安装笔记: https://mp.csdn.net/mp_blog/creation/success/127578406
②:Dubbo快速入门
1. 创建工程和模块
- 环境Jdk1.8 使用本地Maven 不要忘记
2. 导入依赖和Tomcat插件
- dubbo-web 和dubbo-service 中导入以下依赖
- dubbo-web 打包方式为war包
- dubbo-service 不需要导入Tomcat插件
<properties>
<spring.version>5.1.9.RELEASE</spring.version>
<dubbo.version>2.7.4.1</dubbo.version>
<zookeeper.version>4.0.0</zookeeper.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- servlet3.0规范的坐标 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--spring的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<!-- <version>${spring.version}</version>-->
<version>5.1.9.RELEASE</version>
</dependency>
<!--springmvc的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<!-- <version>${spring.version}</version>-->
<version>5.1.9.RELEASE</version>
</dependency>
<!--日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<!-- <version>${dubbo.version}</version>-->
<version>2.7.4.1</version>
</dependency>
<!--ZooKeeper客户端实现 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<!-- <version>${zookeeper.version}</version>-->
<version>4.0.0</version>
</dependency>
<!--ZooKeeper客户端实现 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<!-- <version>${zookeeper.version}</version>-->
<version>4.0.0</version>
</dependency>
<!--公共接口模块-->
<!-- <dependency>-->
<!-- <groupId>com.it</groupId>-->
<!-- <artifactId>dubbo-interface</artifactId>-->
<!-- <version>1.0-SNAPSHOT</version>-->
<!-- </dependency>-->
</dependencies>
<build>
<plugins>
<!--tomcat插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8000</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
3. 代码实现
1.UserService
public interface UserService {
public String sayHello();
}
2.UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "Hello Dubbo~~";
}
}
3. dubbo-service --→ applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.it.service"/>
</beans>
4. dubbo-service --→ log4j.properties
# DEBUG < INFO < WARN < ERROR < FATAL
# Global logging configuration
log4j.rootLogger=info, stdout,file
# My logging configuration...
#log4j.logger.com.tocersoft.school=DEBUG
#log4j.logger.net.sf.hibernate.cache=debug
## Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=../logs/iask.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
5.dubbo-web --→ web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Springmvc -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
6.dubbo-web 引入service依赖
<dependency>
<groupId>com.it</groupId>
<artifactId>dubbo-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
7.UserController
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello() {
return userService.sayHello();
}
}
8.springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解-->
<mvc:annotation-driven/>
<context:component-scan base-package="com.it.controller"/>
</beans>
4. 启动项目
- 因为web模块中引入了service模块 所有先将service模块安装一下
- 启动web模块
- 访问
③:使用Dubbo实现
1. 导入dubbo相关依赖(所有模块)
<!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<!-- <version>${dubbo.version}</version>-->
<version>2.7.4.1</version>
</dependency>
<!--ZooKeeper客户端实现 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<!-- <version>${zookeeper.version}</version>-->
<version>4.0.0</version>
</dependency>
<!--ZooKeeper客户端实现 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<!-- <version>${zookeeper.version}</version>-->
<version>4.0.0</version>
</dependency>
2.代码实现(dubbo-service)
1.dubbo-service中引入Tomcat插件 端口为8223
<build>
<plugins>
<!--tomcat插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8223</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
2.修改打包方式 为war包启动
3.@Servie注解换成Dubbo中的
4.添加配置信息
<!-- dubbo的配置-->
<!-- 1. 配置项目的名称(唯一)-->
<dubbo:application name="dubbo-service"/>
<!-- 2. 配置注册中心地址(如NAcos ZooKeeper)-->
<dubbo:registry address="zookeeper://192.168.100.200:2181"/>
<!-- 3. 配置dubbo包扫描-->
<dubbo:annotation package="com.it.service.impl"/>
5.添加web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
3.代码实现(dubbo-web)
1.注释掉web模块中对service模块的依赖
2. 删除web.xml中的Spring的配置信息
3.使用dubbo中的@Reference注解远程注入
4.创建UserService
package com.it.service;
public interface UserService {
public String sayHello();
}
5.springmvc.xml中添加以下配置
<!-- dubbo的配置-->
<!-- 1. 配置项目的名称(唯一)-->
<dubbo:application name="dubbo-web"/>
<!-- 2. 配置注册中心地址(如NAcos ZooKeeper)-->
<dubbo:registry address="zookeeper://192.168.100.200:2181"/>
<!-- 3. 配置dubbo包扫描-->
<dubbo:annotation package="com.it.controller"/>
④:启动测试
- 启动两个模块(访问)
- 修改任何一个服务的端口
<!-- 1. 配置项目的名称(唯一)-->
<dubbo:application name="dubbo-web">
<dubbo:parameter key="qos.port" value="33333"/>
</dubbo:application>
- 重新启动服务测试
⑤:优化代码
1.创建公共包(dubbo-interface)
2.创建UserService接口
1.在dubbo-interface模块中创建接口
2.删除dubbo-service和dubbo-web中的UserService接口
3.dubbo-service和dubbo-web中引入dubbo-interface模块依赖
<dependency>
<groupId>com.it</groupId>
<artifactId>dubbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3.重启测试访问
- dubbo-interface模块进行install安装
四、Dubbo 高级特性
①:dubbo-admin管理平台安装
dubbo-admin管理平台安装与简单使用笔记:https://mp.csdn.net/mp_blog/creation/success/127585897
②:dubbo-序列化
1. 创建一个新的模块(dubbo_pojo)
- 在模块中创建一个User实体类
public class User {
private int id;
private String name;
private String gender;
private int age;
// 提供有参 无参 get set 方法
}
2. 代码实现
1.dubbo-web 中定义Controller方法
/**
* 根据id查询用户
* @return
*/
@RequestMapping("id")
public User getUserById(id){
return userService.getById(id);
}
2.dubbo-interface中引入dubbo-pojo包的依赖,并创建User接口方法
<dependency>
<groupId>com.it</groupId>
<artifactId>dubbo_pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
/**
* 根据id查询用户
* @param id
* @return
*/
User getById(int id);
3.在dubbo-service中完成接口的具体实现
@Override
public User getById(int id) {
return new User(id,"zhangsan","男",20);
}
3.启动服务测试
1.dubbo-interface和dubbo_pojo模块进行install安装
重启service和web 进行访问
4.实现Serializable接口
5.启动服务在测试
1.dubbo-interface和dubbo_pojo模块进行install安装
重启service和web 进行访问
③:dubbo-地址缓存
1.测试停止zookeeper在进行访问
- 可以,因为dubbo服务消费者在第一次调用时,会将服务提供方地址缓存到本地,以后在调用则不会访问注册中心。
- 当服务提供者地址发生变化时,注册中心会通知服务消费者。
④:dubbo-超时
1.模拟超时
1.在生产者中添加睡眠程序,模拟超时
@Service(timeout = 3000, retries = 0)
public class UserServiceImpl implements UserService {
private final ExecutorService fixedThreadPool = newFixedThreadPool(1);
@Override
public User getById(int id){
// 开一个新的线程打印数字
fixedThreadPool.execute(UserServiceImpl::run);
// 使主程序睡眠
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new User(id,"zhangsan","男",20);
}
private static void run() {
int time = 0;
while (true) {
System.out.println("time = " + time);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
time++;
}
}
.....
}
2.访问测试
2.消费和生产都设置超时时间
- 为了更好的观察将开线程打印数字的代码放到controller中
private final ExecutorService fixedThreadPool = newFixedThreadPool(1);
/**
* 根据id查询用户
* @return
*/
@RequestMapping("id")
public User getUserById(int id){
// 开一个新的线程打印数字
fixedThreadPool.execute(() -> {
int time = 0;
while (true) {
System.out.println("time = " + time);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
time++;
}
});
return userService.getById(id);
}
- 结果一秒之后就报错了
- 建议:超时时间(timeout)配置在服务的提供方
⑤:dubbo-重试
⑥:dubbo-多版本
1.在复制一个接口实现类(模拟多个版本)
2.测试1
3.测试2
⑦:dubbo-负载均衡
负载均衡策略(4种):
- Random :按权重随机,默认值。按权重设置随机概率。
- RoundRobin :按权重轮询。
- LeastActive:最少活跃调用数,相同活跃数的随机。
- ConsistentHash:一致性 Hash,相同参数的请求总是发到同一提供者。
1. 启动多台服务
1.第一次启动
2.第二次启动需要修改端口号
3.按照同样的方式修改在启动一次
4.启动成功后查看dubbo-admin
2.配置负载均衡策略
1.测试 重启web服务 访问测试
⑧:dubbo-集群容错
1. 容错模式
集群容错模式:
- Failover Cluster:失败重试。默认值。当出现失败,重试其它服务器 ,默认重试2次,使用 retries 配置。一般用于读操作
- Failfast Cluster :快速失败,只发起一次调用,失败立即报错。通常用于写操作。
- Failsafe Cluster :失败安全,出现异常时,直接忽略。返回一个空结果。
- Failback Cluster :失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
- Forking Cluster :并行调用多个服务器,只要一个成功即返回。
- Broadcast Cluster :广播调用所有提供者,逐个调用,任意一台报错则报错。
2. 代码实现
1.分别启动3太service服务
2.调用端配置 集群容错模式
3.启动web服务进行测试
4.在进行一次访问测试
⑨:dubbo-服务降级
服务降级方式:
-
mock=force:return null 表示消费方对该服务的方法调用都直
接返回u川值,不发起远程调用。用来屏蔽不重要服务不可用
时对调用方的影响。 -
mock=fail:return null 表示消费方对该服务的方法调用在失败
后,再返回u川值,不抛异常。用来容忍不重要服务不稳定时
对调用方的影响。 -
具体使用可参考官方文档:https://dubbo.apache.org/zh/docs3-v2/java-sdk/advanced-features-and-usage/service/service-downgrade/
1.配置降级策略
1.@Reference(mock=“fail:return null” ) // 失败后返回null 不抛异常
2.测试