传统项目 | 互联网项目 | |
---|---|---|
用户群体 | 企业员工(数量少) | 网民(数量大) |
用户的忍耐力 | 忍耐力高 | 0忍耐力 |
复杂度 | 低 | 高 |
数据量 | 较少 | 海量 |
安全性 | 相对安全 | 易受攻击 |
需求变更 | 变更慢 | 变更快 |
互联网项目特点:
● 用户多
● 流量大,发高
● 海量数据.
● 易受攻击
● 功能繁琐
● 更快
⭐ 高性能:提供快速的访问体验
● 响应时间:指执行一个请求从开始到最后收到响应数据所花费的总体时间。
● 并发数:指系统同时能处理的请求数量。
● 并发连接数: 指的是客户端向服务器发起请求,建立了TCP连接。每秒钟服务器连接的总TCP数量
● 请求数:也称为QPS(Query Per Second)指每秒多少请求.
● 并发用户数: 单位时间内有多少用户
● 吞吐量: 指单位时间内系统能处理的请求数量。
QPS: Query Per Second每秒查询数。
TPS: Transactions Per Second每秒事务数。
一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束
计时,以此来计算使用的时间和完成的事务个数。
一个页面的一次访问,只会形成一个TPS; 但-次页面请求,可能产生多次对服务器的请求,就会有多个QPS。
QPS >=并发连接数>= TPS
● 高性能:提供快速的访问体验。
● 高可用:网站服务一直可以正常访问。
● 可伸缩:通过硬件增加/减少,提高/降低处理能力。
● 高可扩展:統间耦合低,方便的通过新增/移除方式,增加/减
少新的功能模块。
● 安全性:提供网站安全访问和数据加密,安全存储等策略。
● 敏捷性:随需应变,快速响应。
● 集群:很多“人”一起,干一样的事。
● 分布式:很多“人”一起,环样的事.这些不样的事,合起来是一件大事,
● 集群:很多"人”一起,干一样的事。
一个业务模块,部署在多台服务器上。
● 分布式:很多“人”一起,干不一样的事。这些不一样的事, 合起来是一件大事。
一个大的业务系统, 拆分为小的业务模块,分别部罢在不同的机器上。
Dubbo是SOA时代的产物,SpringCloud 是微服务时代的产物
Dubbo是阿里巴巴公司开源的一个高性能轻量级的Java RPC框架。
致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
官网: Dubbo官网
● Provider: 暴露服务的服务提供方
● Container:服务运行容器
● Consumer: 调用远程服务的服务消费方
● Registry:服务注册与发现的注册中心
● Monitor:统计服务的调用次数和调用时间的监控中心
Dubbo官方推荐使用Zookeeper作为注册中心
安装到虚拟机上
1.首先把安装包放到虚拟机共享目录中,或者用Xftp发送给虚拟机也行。
其中安装包去官网下载,或者课程资料中有。
2.进入虚拟机,创建目录
mkdir /opt/Zookeeper
ls
cp apache-zookeeper-3.5.6-bin.tar.gz /opt/Zookeeper
tar -zxvf apache-zookeeper-3.5.6-bin.tar.gz
cd apache-zookeeper-3.5.6-bin/conf
6.把配置文件拷贝一份,将拷贝过后的文件重命名,作为配置文件
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
8.再开另一个命令窗口,创建一个zookeeper的数据目录
mkdir zkdata
pwd
9.更改当前编辑的配置文件,目录为创建的数据目录地址
在配置文件中更改dataDir为8中复制的地址
:wq
cd bin
12.运行服务
./zkServer.sh start
./zkServer.sh stop
./zkServer.sh status
服务启动时查看状态,端口默认是2181
mode:standalone 表示单结点运行
./zkServer.sh status
1.IDEA中创建空项目
起名dubbo-pro
2.配置IDEA
1.配置SDK为JDK1.8
2.调整编码
3.调整Maven
4.本地创建模块
new-Module,选择Maven
配置Maven的相关坐标
name:dubbo-service
groupid:com.itheima
5.模块创建成功
重复以上1~5的步骤创建一个新的模块叫dubbo-web,效果如下
6.给dubbo-web项目下的pom.xml导入依赖
<properties>
<spring.version>5.1.9.RELEASEspring.version>
<dubbo.version>2.7.4.1dubbo.version>
<zookeeper.version>4.0.0zookeeper.version>
properties>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.21version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.21version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubboartifactId>
<version>${dubbo.version}version>
dependency>
<dependency>
<groupId>org.apache.curatorgroupId>
<artifactId>curator-frameworkartifactId>
<version>${zookeeper.version}version>
dependency>
<dependency>
<groupId>org.apache.curatorgroupId>
<artifactId>curator-recipesartifactId>
<version>${zookeeper.version}version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>8000port>
<path>/path>
configuration>
plugin>
plugins>
build>
7.给dubbo-service的pom.xml导入依赖
因为不是web项目,所以不用导入tomcat的插件
其次是web项目,所以打包形式是war
<packaging>warpackaging>
<properties>
<spring.version>5.1.9.RELEASEspring.version>
<dubbo.version>2.7.4.1dubbo.version>
<zookeeper.version>4.0.0zookeeper.version>
properties>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.21version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.21version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubboartifactId>
<version>${dubbo.version}version>
dependency>
<dependency>
<groupId>org.apache.curatorgroupId>
<artifactId>curator-frameworkartifactId>
<version>${zookeeper.version}version>
dependency>
<dependency>
<groupId>org.apache.curatorgroupId>
<artifactId>curator-recipesartifactId>
<version>${zookeeper.version}version>
dependency>
dependencies>
8.在dubbo-service项目下创建UserService接口
写入代码
UserService
public interface UserService {
public String sayHello();
}
package com.itheima.service.impl;
import com.itheima.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "hello dubbo";
}
}
10.编写配置文件applicationContext.xml
<context:component-scan base-package="com.itheima.service">context:component-scan>
11.紧接着去dubbo-web中添加web.xml
这一步基于步骤7,配置打包形式是web
修改web.xml路径
F:\javawebwork\dubbo-pro\dubbo-web\src\main\webapp\WEB-INF\web.xml
把资料中web.xml拷贝过来,具体内容如下:
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath*:spring/applicationContext*.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring/springmvc.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
会发现内容报红
解决报红
(1).加入依赖,修改dubbo-web中的pom.xml
<dependency>
<groupId>com.itheimagroupId>
<artifactId>dubbo-serviceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
发现报红消失了
(2).拷贝资料中的配置
发现报红消失
12.修改springmvc.xml
<mvc:annotation-driven/>
<context:component-scan base-package="com.itheima.controller">context:component-scan>
13.紧接着去dubbo-web中写controller
代码如下:
package com.itheima.controller;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
}
14.安装maven,因为dubbo-service项目被依赖了
15.启动web项目
用run maven 启动dubbo-web项目
因为pom.xml中配置了tomcat插件,所以这里用插件启动
看到控制台启动成功
那么我们输入网址
http://localhost:8000/user/sayHello.do
发现加载成功
这里地址后缀加了.do是因为web.xml中配置了
目前的架构模式如下:仍然是单体模式
后续我们要在此基础上改成分布式的SOA架构如下:
1.先更改dubbo-service模块
更改pom.xml,也让它变为war包的打包形式
增加Tomcat插件,这里的端口号和之前dubbo-wen项目中的不一致才行,比如改成9000
<packaging>warpackaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>9000port>
<path>/path>
configuration>
plugin>
plugins>
build>
2.更改UserServiceImpl
把以前org.springframework.stereotype.Service ;下的注解更改为
org.apache.dubbo.config.annotation.Service
这个注解会去注册中心将访问地址、ip进行注册
package com.itheima.service.impl;
import com.itheima.service.UserService;
import org.apache.dubbo.config.annotation.Service;
// 将该类对象创建出来,放到Spring的IOC容器中
//@Service
// 将这个类提供的方法(服务)对外发布,将访问的地址、ip路径、注册到注册中心中
@Service
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "hello dubbo";
}
}
3.去applicationContext.xml中加入dubbo配置
<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">
<dubbo:application name="dubbo-service"/>
<dubbo:registry address="zookeeper://192.176.154.322:2181"/>
<dubbo:annotation package="com.itheima.service">dubbo:annotation>
beans>
4.既然配置成了web项目,那么需要生成web.xml文件
更改web.xml
springmvc的内容就可以不要了
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath*:spring/applicationContext*.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
web-app>
5.用tomcat插件启动dubbo-service
启动成功
1.现在来更改dubbo-web模块即服务的消费方,首先去掉pom.xml中对dubbo-service模块的依赖
这个时候controller层会报错
我们暂时的处理方式是在dubbo-web模块中创建一个interface
package com.itheima.service;
public interface UserService {
public String sayHello();
}
2.去web.xml中删除掉spring的配置
删除后如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--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>
3.修改UserController
把@Autowired注解去掉,换上@Reference注解,注意导入的包是
org.apache.dubbo.config.annotation.Reference
package com.itheima.controller;
import com.itheima.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
// 本地注入
//@Autowired
/**
* @Reference远程注入
* 1.从zookeeper(注册中心)获取UserService的访问路径(url)
* 2.进行远程调用RPC
* 3.将结果封装为代理对象,给变量赋值
*
*/
@Reference
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
}
4.修改springmvc.xml
<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.itheima.controller">context:component-scan>
<dubbo:application name="dubbo-web">dubbo:application>
<dubbo:registry address="zookeeper://192.176.154.322:2181"/>
<dubbo:annotation package="com.itheima"/>
beans>
5.启动dubbo-web项目
启动成功
这里注意dubbo-service中的tomcat服务是已经启动的
登录地址
http://localhost:8000/user/sayHello.do
发现载入成功
控制台加载成功
6.但是控制台有报错,端口已经被占用
那么我们更改dubbo-web的端口即可,原因是我们是在一台电脑上开发的,dubbo-service已经启动了该端口22222,用来监听,这个时候dubbo-web启动也是这个端口,所以报错。
解决方式:修改springmvc.xml
增加< dubbo:parameter >
<dubbo:application name="dubbo-web">
<dubbo:parameter key="qos.port" value="33333">dubbo:parameter>
dubbo:application>
<dubbo:registry address="zookeeper://192.176.154.322:2181"/>
<dubbo:annotation package="com.itheima"/>
8.现在来处理一下问题,之前因为编译报错,我们在consumer中写了和provider一样的接口,这个案例接口少没问题,那么到企业开发中,很多的接口,也需要consumer全部写一遍,这是很不现实的,那我们的解决方案是:
把接口做成公共接口,让dubbo-service和dubbo-web都去调用
1.我们新写一个模块,最后结构如下:
groupid:com.itheima
artifactid:dubbo-interface
拷贝接口过去
2.可以把之前dubbo-service和dubbo-web中的接口删掉了
3.删除接口之后,我们需要将dubbo-service和dubbo-web都依赖于dubbo-interface中的接口
修改两者的pom.xml
添加
<dependency>
<groupId>com.itheimagroupId>
<artifactId>dubbo-interfaceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
4.去dubbo-service模块中发现类UserServiceImpl.java报红
因为接口的路径更改了,是通过公共接口获取的,这里要点击导入依赖
代码如下:
UserServiceImpl.java
package com.itheima.service.impl;
import com.itheima.service.UserService;
import org.apache.dubbo.config.annotation.Service;
// 将该类对象创建出来,放到Spring的IOC容器中
//@Service
// 将这个类提供的方法(服务)对外发布,将访问的地址、ip路径、注册到注册中心中
@Service
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "hello dubbo!!";
}
}
修改UserController
将公共接口的依赖引入
代码如下:
package com.itheima.controller;
import com.itheima.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
// 本地注入
//@Autowired
/**
* @Reference远程注入
* 1.从zookeeper(注册中心)获取UserService的访问路径(url)
* 2.进行远程调用RPC
* 3.将结果封装为代理对象,给变量赋值
*
*/
@Reference
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
}
5.需要将新加的公共接口模块,在maven中安装
6.启动dubbo-service和dubbo-web
载入成功
①创建服务提供者Provider模块
②创建服务消费者Consumer模块
③在服务提供者模块编写UserServicelmpl提供服务
④在服务消费者中的UserController远程调用UserServicelmpl提供的服务
⑤分别启动两个服务,测试
●dubbo-admin管理平台,图形化的服务管理页面。
● 从注册中心中获取到所有的提供者/消费者进行配置管理。
● 路由规则、动态配置、服务降级、访问控制、权重调整、负载均衡等管理功能。
● dubbo- admin是- -个前后端分离的项目。前端使用vue后端使用springboot。
● 安装dubbo admin实就是部署该项目。
dubbo-admin 是一个前后端分离的项目。前端使用vue,后端使用springboot,安装 dubbo-admin 其实就是部署该项目。我们将dubbo-admin安装到开发环境上。要保证开发环境有jdk,maven,nodejs。
安装node**(如果当前机器已经安装请忽略)**
安装资料中的node-v12.14.0-x64
因为前端工程是用vue开发的,所以需要安装node.js,node.js中自带了npm,后面我们会通过npm启动。
下载地址:
nodejs官网
进入github,搜索dubbo-admin
Dubbo-Admin github 下载地址
如图所示下载:
资料中有直接用即可
安装过程可以参考
node.js安装 版本:node-v12.14.0-x64
安装完后,在命令操作符中输入
node -v
如下图即可
然后安装教程配置环境变量和npm的全局模块缓存这里就不赘述了。
解压后我们进入…\dubbo-admin-develop\dubbo-admin-server\src\main\resources目录,找到 application.properties 配置文件 进行配置修改。
修改zookeeper地址
# centers in dubbo2.7
admin.registry.address=zookeeper://192.168.149.135:2181
admin.config-center=zookeeper://192.168.149.135:2181
admin.metadata-report.address=zookeeper://192.168.149.135:2181
admin.registry.address注册中心
admin.config-center 配置中心
admin.metadata-report.address元数据中心
在 dubbo-admin-develop 目录执行打包命令,
这里需要较长时间,要耐心等待。
mvn clean package -Dmaven.skip.test=true
切换到目录
dubbo-Admin-develop\dubbo-admin-distribution\target>
执行下面的命令启动 dubbo-admin,dubbo-admin后台由SpringBoot构建。
java -jar .\dubbo-admin-0.1.jar
进入dubbo-admin-ui 目录下执行命令
npm run dev
浏览器输入。用户名密码都是root
http://localhost:8081/
注意:Dubbo Admin【服务Mock】【服务统计】将在后续版本发布。
在上面的步骤中,我们已经进入了Dubbo-Admin的主界面,在【快速入门】章节中,我们定义了服务生产者、和服务消费者,下面我们从Dubbo-Admin管理界面找到这个两个服务。
A:输入的查询条件com.itheima.service.UserService
B:搜索类型,主要分为【按服务名】【按IP地址】【按应用】三种类型查询
C:搜索结果
我们查看com.itheima.service.UserService (服务提供者)的具体详细信息,包含【元数据信息】
从【详情】界面查看,主要分为3个区域
A区域:主要包含服务端 基础信息比如服务名称、应用名称等
B区域:主要包含了生产者、消费者一些基本信息
C区域:是元数据信息,注意看上面的图,元数据信息是空的
我们需要打开我们的生产者配置文件加入下面配置
<dubbo:metadata-report address="zookeeper://192.168.149.135:2181" />
重新启动生产者,再次打开Dubbo-Admin,这样我们的元数据信息就出来了。
● dubbo 内部已经将序列化和反例化的过程内部封装了
● 我们只需要在定义pojo类时实现serializable接口即可
● 一般会定义一 个公共的pojo模块, 让生产者和消费者都依赖该模块。
1.创建一个模块dubbo-pojo
2.dubbo-pojo模块中新建一个类User
package com.itheima.pojo;
public class User {
private Integer id;
private String username;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer 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 User(){}
}
3.在dubbo-interface中增加依赖
修改pom.xml
<dependencies>
<dependency>
<groupId>com.itheimagroupId>
<artifactId>dubbo-pojoartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
4.在dubbo-interface的接口中增加方法
UserService.java
public interface UserService {
public String sayHello();
public User getUserId(Integer id);
}
5.在dubbbo-service模块中添加接口的实现方法
UserServiceImpl.java
@Service
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "hello dubbo!!";
}
@Override
public User getUserId(Integer id) {
// 创建user对象
User user = new User(1, "小王", "123");
return user;
}
}
6.修改dubbo-web模块中的
UserController.java
package com.itheima.controller;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
// 本地注入
//@Autowired
/**
* @Reference远程注入
* 1.从zookeeper(注册中心)获取UserService的访问路径(url)
* 2.进行远程调用RPC
* 3.将结果封装为代理对象,给变量赋值
*
*/
@Reference
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
@RequestMapping("/getUserId")
public User getUserId(){
return userService.getUserId(id);
}
}
7.进行服务的测试
这个时候要注意User类我们是没有实现Serializable接口实例化的。
我们要mvn install 改动的2个模块 dubbo-interface和dubbo-pojo
这个时候我们启动服务,发现报了很多错误
我们回控制台看错误
8.调整User实体类
实现Serializable 接口
public class User implements Serializable
9.重新mvn install dubbo-pojo
10.重启服务再看一下
输入地址
http://localhost:8000/user/find.do?id=1
提问:注册中心挂了,服务是否可以正常访问?
●可以,因为dubbo服务消费者在第一次调用时,会将服务提供方地址缓存到本地,以后在调用则不会访问注册中心。
●当服务提供者地址发生变化时,注册中心会通知服务消费者。
比如现在我们把Zookeeper停了,再看一下,服务仍然正常
服务如下:说明一下,Zookeeper挂了之后,服务仍然正常。
●服务消费者在调用服务提供者的时候发生 了阻塞、等待的情形,这个时候,服务消费者会直等待下去。
●在某个峰值时刻, 大的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩。
●服务消费者在调用服务提供者的时候发生 了阻塞、等待的情形,这个时候,服务消费者会待下去。
●在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩。
●dubbo 利用超时机制来解决这个问题,设置一个超时时间, 在这个时间段内,无法完成服务访问,则自动断开连接。
●使用timeout属性配置 超时时间,默认值1000,单位毫秒。
●设置了超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。
●如果出现网络抖动,则这- -次请求就会失败。
●Dubbo 提供重试机制来避免类似问题的发生。
●通过retries属性来设置重试次数。默认为2次。
超时示例:
1.可以在dubbo-service模块设置超时
修改UserServiceImpl.java
注解中增加超时时间
// 将这个类提供的方法(服务)对外发布,将访问的地址、ip路径、注册到注册中心中
// 当前服务3秒超时
@Service(timeout = 3000,retries = 0)
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "hello dubbo!!";
}
@Override
public User getUserId(Integer id) {
// 创建user对象
User user = new User(1, "小王", "123");
// 数据库查询很慢,查询了5秒
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return user;
}
}
修改UserController.java
增加线程启动逻辑
@RestController
@RequestMapping("/user")
public class UserController {
// 本地注入
//@Autowired
/**
* @Reference远程注入
* 1.从zookeeper(注册中心)获取UserService的访问路径(url)
* 2.进行远程调用RPC
* 3.将结果封装为代理对象,给变量赋值
*
*/
@Reference
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
@RequestMapping("/find")
public User getUserId(Integer id){
AtomicInteger atomicInteger = new AtomicInteger(1);
Thread thread = new Thread(()->{
while (true){
System.out.println(atomicInteger.getAndIncrement());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
return userService.getUserId(id);
}
}
这时候启动,看一下控制台
发现达到的效果是3秒后报错,因为我们超时时间就是3秒。
那我们把dubbo-service中
UserServiceImpl.java的注解去掉,默认是1秒,我们再看一下
@Service(retries = 0)
重启服务
这次控制台中1秒后报错了。
1.可以在dubbo-web模块设置超时
更改UserController.java
我们在@Reference注解后增加超时时间
@Reference(timeout = 1000)
更改dubbo-sercvice模块UserServiceImpl.java
我们在@Service注解后增加超时时间
@Service(timeout = 3000,retries = 0)
这里我们启动服务看一下是1秒超时还是3秒超时,看一下后台控制台,发现同时配置了provider端和consumer端的超时时间后,consumer端的超时时间生效了。
但是对于我们实际生产中,建议超时时间设置在provider上,因为是提供方提供服务,自己应该知道超时时间。
重试示例:
在UserServiceImpl.java中配置重试次数
超时后重试2次,一共3次
@Service(timeout = 3000,retries = 2)
增加打印语句UserServiceImpl.java
private int i;
@Override
public User getUserId(Integer id) {
System.out.println("服务被调用了:"+ i + "次");
// 创建user对象
User user = new User(1, "小王", "123");
// 数据库查询很慢,查询了5秒
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return user;
}
●灰度发布:当出现新功能时,会让一部分户先使用新功能,用户反馈没问题
时,再将所有用户迁移到新功能。
●dubbo 中使用version属性来设置和调用同一个接口的不同版本。
多版本示例:
修改dubbo-service模块
给UserServiceImpl.java增加一份为2.0版本。
分别配置如下:
v1.0版本:
UserServiceImpl.java
@Service(version = "v1.0")
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "hello dubbo!!";
}
@Override
public User getUserId(Integer id) {
System.out.println("这里是 version 1.0版本");
// 创建user对象
User user = new User(1, "小王", "123");
// 数据库查询很慢,查询了5秒
return user;
}
}
v2.0版本:
UserServiceImpl2.java
@Service(version = "v2.0")
public class UserServiceImpl2 implements UserService {
@Override
public String sayHello() {
return "hello dubbo!!";
}
@Override
public User getUserId(Integer id) {
System.out.println("这里是 version 2.0版本");
// 创建user对象
User user = new User(1, "小王", "123");
return user;
}
}
这个时候,我们有2个版本,需要告诉dubbo-web中我们使用的是哪一个版本
修改UserController.java
@Reference(version = "v1.0")
private UserService userService;
然后我们重启一下服务器,可以看到启动的是v1.0的版本
那我们要更改成v2.0的版本呢,只需要
修改UserController.java
@Reference(version = "v2.0")
private UserService userService;
负载均衡策略(4种) :
Random :按权重随机,默认值。按权重设置随机概率。
示例:
修改dubbo-service模块,模拟3个服务提供者,那我们开3个服务即可,先修改第一个服务。
修改UserServiceImpl.java
@Service(weight = 100)
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
//return "hello dubbo!!";
return "服务器1";
}
}
启动服务器1即可。
紧接着修改UserServiceImpl.java
@Service(weight = 200)
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
//return "hello dubbo!!";
return "服务器2";
}
}
修改一些参数pom.xml
配置端口号为9002
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>9002port>
<path>/path>
configuration>
plugin>
修改applicationContext.xml
增加dubbo端口和监听端口的配置
<dubbo:protocol port="20882"/>
<dubbo:application name="dubbo-service">
<dubbo:parameter key="qos.port" value="44444"/>
dubbo:application>
然后再启动一个服务2
继续修改
UserServiceImpl .java
@Service(weight = 100)
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
//return "hello dubbo!!";
return "服务器3";
}
}
修改pom.xml
更改端口为9003
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>9003port>
<path>/path>
configuration>
plugin>
修改applicationContext.xml
<dubbo:protocol port="20883"/>
<dubbo:application name="dubbo-service">
<dubbo:parameter key="qos.port" value="55555"/>
dubbo:application>
之后我们需要去dubbo-web模块中配置负载均衡的策略
修改UserController.java
这里需要更改 @Reference注解中的属性loadbalance,但是属性值是字符串,我们不知道,查找的办法:
(1).双击shift或者ctrl+shift+a 查找loadBalance找到抽象类
(2).对类名 ctrl + h
修改UserController.java
@Reference(loadbalance = "random")
private UserService userService;
http://localhost:8000/user/sayHello.do
RoundRobin :按权重轮询
比如3个服务,现在的顺序是调用1 → 2 → 3 再来一次请求发现2的权重高,那么就该2了
消费者在每次发送请求前,会问服务提供者最后一次请求的响应时间,比如1是1000ms,2是2000ms,3是3000ms,那就挑最小的响应时间的服务提供者。
如果活跃数相同,就随机调用。
ConsistentHash:一致性Hash,相同参数的请求总是发到同一提供者。
集群容错模式:
● Failover Cluster: 失败重试。默认值。当出现失败,重试其它服务器,默认重试2次,使用retries配置。一般用于读操作。
● Failfast Cluster :快速失败,只发起一次调用,失败立即报错。通常用于写操作。
● Failsafe Cluster :失败安全,出现异常时,直接忽略。返回一个空结果。
● Failback Cluster :失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
● Forking Cluster :并行调用多个服务器,只要一个成功即返回。
● Broadcast Cluster :广播调用所有提供者,逐个调用,任意一台报错则报错。
失败重试IDEA示例:
修改UserServiceImpl.java
@Override
public User getUserId(Integer id) {
System.out.println("机器1");
// 创建user对象
User user = new User(1, "小王", "123");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return user;
}
pom.xml和applicationContext.xml恢复到初始状态。
启动服务1
继续修改UserServiceImpl.java
@Override
public User getUserId(Integer id) {
System.out.println("机器2");
// 创建user对象
User user = new User(1, "小王", "123");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return user;
}
修改pom.xml
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>9002port>
<path>/path>
configuration>
plugin>
修改applicationContext.xml
<dubbo:protocol port="20882"/>
<dubbo:application name="dubbo-service">
<dubbo:parameter key="qos.port" value="44444"/>
dubbo:application>
启动服务2
继续修改UserServiceImpl.java
注意这里不再超时
@Override
public User getUserId(Integer id) {
System.out.println("机器3");
// 创建user对象
User user = new User(1, "小王", "123");
return user;
}
修改pom.xml
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>9003port>
<path>/path>
configuration>
plugin>
修改applicationContext.xml
<dubbo:protocol port="20883"/>
<dubbo:application name="dubbo-service">
<dubbo:parameter key="qos.port" value="55555"/>
dubbo:application>
启动服务3
在dubbo-web中设置集群容错属性
集群容错属性是@Reference下的cluster属性,其属性值也是字符串,我们用上面的方面查找。
1.shift2下或者shift + ctrl + a 搜索 Cluster
2.ctrl + h 选中类名
修改UserController.java
@Reference(cluster = "failover")
之后我们启动dubbo-web
访问
http://localhost:8000/user/find.do?id=1
发现访问成功
我们看一下控制台
这次恰好是3这台机器,那么我们多刷新几次看下
看到dubbo-web控制台虽然报错了但是每次访问页面都是没问题的,这就是失败重试机制,选择到了服务器3的缘故
服务降级方式:
●mock=force:return null表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
●mock=fail:return null表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
修改UserServiceImpl.java
@Service()
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "服务器3";
}
@Override
public User getUserId(Integer id) {
System.out.println("机器3");
// 创建user对象
User user = new User(1, "小王", "123");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return user;
}
}
修改UserController.java
相当于不调用UserService的服务了
@Reference(mock = "force:return null")
启动服务
访问
http://localhost:8000/user/find.do?id=1
发现页面空白,控制台也没有报错
之后我们试一下另一种模式
修改UserController.java
相当于失败调用UserService的服务才返回null
@Reference(mock = "fail:return null")